Bug 1303241 part 2 - Make GetVisitedDependentColor use style structs directly. r=dbaron

I think there are three advantages of this change:
1. removes some dependencies from layout / painting code to pre-computed
   value stuff in the style system;
2. makes it easier to audit usage of specific fields in style structs
   (which is probably a side effect of the first one);
3. potentially improves performance since it doesn't go through the
   unnecessary general logic in ExtractComputedValue.

Also, combined with the part before, we get a unified list for visited-
dependent properties so that we can ensure the assertion here and the
style difference calc code are consistent.

MozReview-Commit-ID: 5B9aN7CfRgI

--HG--
extra : rebase_source : ac80eaea2474b9ec4b47b1cc9a5bdd2e61f6ec4d
This commit is contained in:
Xidorn Quan 2016-12-31 00:57:37 +11:00
Родитель 801cd27579
Коммит 97d13f46a3
17 изменённых файлов: 123 добавлений и 122 удалений

Просмотреть файл

@ -5578,13 +5578,12 @@ ShouldDarkenColors(nsPresContext* aPresContext)
}
nscolor
nsLayoutUtils::GetColor(nsIFrame* aFrame, nsCSSPropertyID aProperty)
nsLayoutUtils::DarkenColorIfNeeded(nsIFrame* aFrame, nscolor aColor)
{
nscolor color = aFrame->GetVisitedDependentColor(aProperty);
if (ShouldDarkenColors(aFrame->PresContext())) {
color = DarkenColor(color);
return DarkenColor(aColor);
}
return color;
return aColor;
}
gfxFloat

Просмотреть файл

@ -1546,8 +1546,18 @@ public:
static nscoord MinISizeFromInline(nsIFrame* aFrame,
nsRenderingContext* aRenderingContext);
// Get a suitable foreground color for painting aProperty for aFrame.
static nscolor GetColor(nsIFrame* aFrame, nsCSSPropertyID aProperty);
// Get a suitable foreground color for painting aColor for aFrame.
static nscolor DarkenColorIfNeeded(nsIFrame* aFrame, nscolor aColor);
// Get a suitable foreground color for painting aField for aFrame.
// Type of aFrame is made a template parameter because nsIFrame is not
// a complete type in the header. Type-safety is not harmed given that
// DarkenColorIfNeeded requires an nsIFrame pointer.
template<typename Frame, typename T, typename S>
static nscolor GetColor(Frame* aFrame, T S::* aField) {
nscolor color = aFrame->GetVisitedDependentColor(aField);
return DarkenColorIfNeeded(aFrame, color);
}
// Get a baseline y position in app units that is snapped to device pixels.
static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,

Просмотреть файл

@ -215,7 +215,7 @@ nsDisplayTextOverflowMarker::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nscolor foregroundColor = nsLayoutUtils::
GetColor(mFrame, eCSSProperty__webkit_text_fill_color);
GetColor(mFrame, &nsStyleText::mWebkitTextFillColor);
// Paint the text-shadows for the overflow marker
nsLayoutUtils::PaintTextShadow(mFrame, aCtx, mRect, mVisibleRect,

Просмотреть файл

@ -316,7 +316,7 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
}
ColorPattern color(ToDeviceColor(
nsLayoutUtils::GetColor(this, eCSSProperty_color)));
nsLayoutUtils::GetColor(this, &nsStyleColor::mColor)));
DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
@ -423,7 +423,7 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
disable(aRenderingContext.GetDrawTarget(), aDisableSubpixelAA);
aRenderingContext.ThebesContext()->SetColor(
Color::FromABGR(nsLayoutUtils::GetColor(this, eCSSProperty_color)));
Color::FromABGR(nsLayoutUtils::GetColor(this, &nsStyleColor::mColor)));
RefPtr<nsFontMetrics> fm =
nsLayoutUtils::GetFontMetricsForFrame(this, GetFontSizeInflation());

Просмотреть файл

@ -83,7 +83,7 @@ nsColumnSetFrame::PaintColumnRule(nsRenderingContext* aCtx,
return;
nscolor ruleColor =
GetVisitedDependentColor(eCSSProperty_column_rule_color);
GetVisitedDependentColor(&nsStyleColumn::mColumnRuleColor);
// In order to re-use a large amount of code, we treat the column rule as a border.
// We create a new border style object and fill in all the details of the column rule as

Просмотреть файл

@ -727,8 +727,9 @@ public:
#undef STYLE_STRUCT
/** Also forward GetVisitedDependentColor to the style context */
nscolor GetVisitedDependentColor(nsCSSPropertyID aProperty)
{ return mStyleContext->GetVisitedDependentColor(aProperty); }
template<typename T, typename S>
nscolor GetVisitedDependentColor(T S::* aField)
{ return mStyleContext->GetVisitedDependentColor(aField); }
/**
* These methods are to access any additional style contexts that

Просмотреть файл

@ -341,8 +341,8 @@ nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
// Sometimes, a frame doesn't have a background color or is transparent. In this
// case, walk up the frame tree until we do find a frame with a background color
for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
nscolor bgcolor =
frame->GetVisitedDependentColor(eCSSProperty_background_color);
nscolor bgcolor = frame->
GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
if (NS_GET_A(bgcolor) > 0) { // make sure we got an actual color
mWidget->SetBackgroundColor(bgcolor);
break;

Просмотреть файл

@ -3752,14 +3752,14 @@ nsTextPaintStyle::GetTextColor()
case eStyleSVGPaintType_None:
return NS_RGBA(0, 0, 0, 0);
case eStyleSVGPaintType_Color:
return nsLayoutUtils::GetColor(mFrame, eCSSProperty_fill);
return nsLayoutUtils::GetColor(mFrame, &nsStyleSVG::mFill);
default:
NS_ERROR("cannot resolve SVG paint to nscolor");
return NS_RGBA(0, 0, 0, 255);
}
}
return nsLayoutUtils::GetColor(mFrame, eCSSProperty__webkit_text_fill_color);
return nsLayoutUtils::GetColor(mFrame, &nsStyleText::mWebkitTextFillColor);
}
bool
@ -3853,8 +3853,8 @@ nsTextPaintStyle::InitCommonColors()
nsIFrame* bgFrame =
nsCSSRendering::FindNonTransparentBackgroundFrame(mFrame);
NS_ASSERTION(bgFrame, "Cannot find NonTransparentBackgroundFrame.");
nscolor bgColor =
bgFrame->GetVisitedDependentColor(eCSSProperty_background_color);
nscolor bgColor = bgFrame->
GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
nscolor defaultBgColor = mPresContext->DefaultBackgroundColor();
mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor);
@ -3951,9 +3951,9 @@ nsTextPaintStyle::InitSelectionColorsAndShadow()
// Use -moz-selection pseudo class.
if (sc) {
mSelectionBGColor =
sc->GetVisitedDependentColor(eCSSProperty_background_color);
sc->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
mSelectionTextColor =
sc->GetVisitedDependentColor(eCSSProperty__webkit_text_fill_color);
sc->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor);
mHasSelectionShadow =
nsRuleNode::HasAuthorSpecifiedRules(sc,
NS_AUTHOR_SPECIFIED_TEXT_SHADOW,
@ -3989,16 +3989,14 @@ nsTextPaintStyle::InitSelectionColorsAndShadow()
if (mResolveColors) {
// On MacOS X, we don't exchange text color and BG color.
if (mSelectionTextColor == NS_DONT_CHANGE_COLOR) {
nsCSSPropertyID property = mFrame->IsSVGText()
? eCSSProperty_fill
: eCSSProperty__webkit_text_fill_color;
nscoord frameColor = mFrame->GetVisitedDependentColor(property);
nscolor frameColor = mFrame->IsSVGText()
? mFrame->GetVisitedDependentColor(&nsStyleSVG::mFill)
: mFrame->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor);
mSelectionTextColor = EnsureDifferentColors(frameColor, mSelectionBGColor);
} else if (mSelectionTextColor == NS_CHANGE_COLOR_IF_SAME_AS_BG) {
nsCSSPropertyID property = mFrame->IsSVGText()
? eCSSProperty_fill
: eCSSProperty__webkit_text_fill_color;
nscolor frameColor = mFrame->GetVisitedDependentColor(property);
nscolor frameColor = mFrame->IsSVGText()
? mFrame->GetVisitedDependentColor(&nsStyleSVG::mFill)
: mFrame->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor);
if (frameColor == mSelectionBGColor) {
mSelectionTextColor =
LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectForegroundCustom);
@ -5313,7 +5311,7 @@ nsTextFrame::GetTextDecorations(
// la la</font></a> case. The link underline should be green.
useOverride = true;
overrideColor =
nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color);
nsLayoutUtils::GetColor(f, &nsStyleTextReset::mTextDecorationColor);
}
nsBlockFrame* fBlock = nsLayoutUtils::GetAsBlock(f);
@ -5367,10 +5365,11 @@ nsTextFrame::GetTextDecorations(
// for SVG text, and have e.g. text-decoration-color:red to
// override the fill paint of the decoration.
color = aColorResolution == eResolvedColors ?
nsLayoutUtils::GetColor(f, eCSSProperty_fill) :
nsLayoutUtils::GetColor(f, &nsStyleSVG::mFill) :
NS_SAME_AS_FOREGROUND_COLOR;
} else {
color = nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color);
color = nsLayoutUtils::
GetColor(f, &nsStyleTextReset::mTextDecorationColor);
}
bool swapUnderlineAndOverline = vertical && IsUnderlineRight(f);
@ -6561,7 +6560,7 @@ nsTextFrame::DrawEmphasisMarks(gfxContext* aContext, WritingMode aWM,
bool isTextCombined = StyleContext()->IsTextCombined();
nscolor color = aDecorationOverrideColor ? *aDecorationOverrideColor :
nsLayoutUtils::GetColor(this, eCSSProperty_text_emphasis_color);
nsLayoutUtils::GetColor(this, &nsStyleText::mTextEmphasisColor);
aContext->SetColor(Color::FromABGR(color));
gfxPoint pt;
if (!isTextCombined) {

Просмотреть файл

@ -2056,7 +2056,7 @@ nsMathMLChar::PaintForeground(nsPresContext* aPresContext,
// Set color ...
nscolor fgColor = styleContext->
GetVisitedDependentColor(eCSSProperty__webkit_text_fill_color);
GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor);
if (aIsSelected) {
// get color to use for selection from the look&feel object
fgColor = LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectForeground,

Просмотреть файл

@ -367,7 +367,7 @@ void nsDisplayMathMLBar::Paint(nsDisplayListBuilder* aBuilder,
mFrame->PresContext()->AppUnitsPerDevPixel(),
*drawTarget);
ColorPattern color(ToDeviceColor(
mFrame->GetVisitedDependentColor(eCSSProperty__webkit_text_fill_color)));
mFrame->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor)));
drawTarget->FillRect(rect, color);
}

Просмотреть файл

@ -780,7 +780,7 @@ void nsDisplayNotation::Paint(nsDisplayListBuilder* aBuilder,
rect.Deflate(strokeWidth / 2.f);
ColorPattern color(ToDeviceColor(
mFrame->GetVisitedDependentColor(eCSSProperty__webkit_text_fill_color)));
mFrame->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor)));
StrokeOptions strokeOptions(strokeWidth);

Просмотреть файл

@ -629,7 +629,7 @@ void nsDisplayMathMLSlash::Paint(nsDisplayListBuilder* aBuilder,
presContext->AppUnitsPerDevPixel());
ColorPattern color(ToDeviceColor(
mFrame->GetVisitedDependentColor(eCSSProperty__webkit_text_fill_color)));
mFrame->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor)));
// draw the slash as a parallelogram
Point delta = Point(presContext->AppUnitsToGfxUnits(mThickness), 0);

Просмотреть файл

@ -670,8 +670,8 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
nsStyleBorder newStyleBorder(*styleBorder);
NS_FOR_CSS_SIDES(side) {
nscolor color = aStyleContext->GetVisitedDependentColor(
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
nscolor color = aStyleContext->
GetVisitedDependentColor(nsStyleBorder::BorderColorFieldFor(side));
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
}
return PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
@ -702,8 +702,8 @@ nsCSSRendering::CreateBorderRenderer(nsPresContext* aPresContext,
nsStyleBorder newStyleBorder(*styleBorder);
NS_FOR_CSS_SIDES(side) {
nscolor color = aStyleContext->GetVisitedDependentColor(
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
nscolor color = aStyleContext->
GetVisitedDependentColor(nsStyleBorder::BorderColorFieldFor(side));
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
}
return CreateBorderRendererWithStyleBorder(aPresContext, aDrawTarget,
@ -733,8 +733,8 @@ ConstructBorderRenderer(nsPresContext* aPresContext,
bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(aForFrame, quirks);
nsStyleContext* bgContext = bgFrame->StyleContext();
nscolor bgColor =
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
nscolor bgColor = bgContext->
GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
// Compute the outermost boundary of the area that might be painted.
// Same coordinate space as aBorderArea & aBGClipRect.
@ -973,8 +973,8 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext,
nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame
(aForFrame, false);
nsStyleContext* bgContext = bgFrame->StyleContext();
nscolor bgColor =
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
nscolor bgColor = bgContext->
GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
nsRect innerRect;
if (
@ -1041,7 +1041,7 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext,
// This handles treating the initial color as 'currentColor'; if we
// ever want 'invert' back we'll need to do a bit of work here too.
nscolor outlineColor =
aStyleContext->GetVisitedDependentColor(eCSSProperty_outline_color);
aStyleContext->GetVisitedDependentColor(&nsStyleOutline::mOutlineColor);
nscolor outlineColors[4] = { outlineColor,
outlineColor,
outlineColor,
@ -2240,8 +2240,8 @@ nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext,
const nsStyleBackground *bg = aStyleContext->StyleBackground();
nscolor bgColor;
if (aDrawBackgroundColor) {
bgColor =
aStyleContext->GetVisitedDependentColor(eCSSProperty_background_color);
bgColor = aStyleContext->
GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
if (NS_GET_A(bgColor) == 0) {
aDrawBackgroundColor = false;
}

Просмотреть файл

@ -25,7 +25,6 @@
#include "nsRuleNode.h"
#include "nsStyleContext.h"
#include "mozilla/StyleAnimationValue.h"
#include "GeckoProfiler.h"
#include "nsIDocument.h"
#include "nsPrintfCString.h"
@ -1388,88 +1387,63 @@ nsStyleContext::Arena()
return PresContext()->PresShell();
}
static inline void
ExtractAnimationValue(nsCSSPropertyID aProperty,
nsStyleContext* aStyleContext,
StyleAnimationValue& aResult)
template<typename Func>
static nscolor
GetVisitedDependentColorInternal(nsStyleContext* aSc, Func aColorFunc)
{
DebugOnly<bool> success =
StyleAnimationValue::ExtractComputedValue(aProperty, aStyleContext,
aResult);
MOZ_ASSERT(success,
"aProperty must be extractable by StyleAnimationValue");
}
static Maybe<nscolor>
ExtractColor(nsCSSPropertyID aProperty,
nsStyleContext *aStyleContext)
{
StyleAnimationValue val;
ExtractAnimationValue(aProperty, aStyleContext, val);
switch (val.GetUnit()) {
case StyleAnimationValue::eUnit_Color:
return Some(val.GetCSSValueValue()->GetColorValue());
case StyleAnimationValue::eUnit_CurrentColor:
return Some(aStyleContext->StyleColor()->mColor);
case StyleAnimationValue::eUnit_ComplexColor:
return Some(aStyleContext->StyleColor()->
CalcComplexColor(val.GetStyleComplexColorValue()));
default:
return Nothing();
nscolor colors[2];
colors[0] = aColorFunc(aSc);
if (nsStyleContext* visitedStyle = aSc->GetStyleIfVisited()) {
colors[1] = aColorFunc(visitedStyle);
return nsStyleContext::
CombineVisitedColors(colors, aSc->RelevantLinkVisited());
}
return colors[0];
}
static nscolor
ExtractColorLenient(nsCSSPropertyID aProperty,
nsStyleContext *aStyleContext)
ExtractColor(nsStyleContext* aContext, const nscolor& aColor)
{
return ExtractColor(aProperty, aStyleContext).valueOr(NS_RGBA(0, 0, 0, 0));
return aColor;
}
static nscolor
ExtractColor(nsStyleContext* aContext, const StyleComplexColor& aColor)
{
return aContext->StyleColor()->CalcComplexColor(aColor);
}
static nscolor
ExtractColor(nsStyleContext* aContext, const nsStyleSVGPaint& aPaintServer)
{
return aPaintServer.Type() == eStyleSVGPaintType_Color
? aPaintServer.GetColor() : NS_RGBA(0, 0, 0, 0);
}
#define STYLE_FIELD(struct_, field_) aField == &struct_::field_ ||
#define STYLE_STRUCT(name_, fields_) \
template<> nscolor \
nsStyleContext::GetVisitedDependentColor( \
decltype(nsStyle##name_::MOZ_ARG_1 fields_) nsStyle##name_::* aField) \
{ \
MOZ_ASSERT(MOZ_FOR_EACH(STYLE_FIELD, (nsStyle##name_,), fields_) false, \
"Getting visited-dependent color for a field in nsStyle"#name_ \
" which is not listed in nsCSSVisitedDependentPropList.h"); \
return GetVisitedDependentColorInternal(this, \
[aField](nsStyleContext* sc) { \
return ExtractColor(sc, sc->Style##name_()->*aField); \
}); \
}
#include "nsCSSVisitedDependentPropList.h"
#undef STYLE_STRUCT
#undef STYLE_FIELD
struct ColorIndexSet {
uint8_t colorIndex, alphaIndex;
};
static const ColorIndexSet gVisitedIndices[2] = { { 0, 0 }, { 1, 0 } };
nscolor
nsStyleContext::GetVisitedDependentColor(nsCSSPropertyID aProperty)
{
NS_ASSERTION(aProperty == eCSSProperty_color ||
aProperty == eCSSProperty_background_color ||
aProperty == eCSSProperty_border_top_color ||
aProperty == eCSSProperty_border_right_color ||
aProperty == eCSSProperty_border_bottom_color ||
aProperty == eCSSProperty_border_left_color ||
aProperty == eCSSProperty_outline_color ||
aProperty == eCSSProperty_column_rule_color ||
aProperty == eCSSProperty_text_decoration_color ||
aProperty == eCSSProperty_text_emphasis_color ||
aProperty == eCSSProperty__webkit_text_fill_color ||
aProperty == eCSSProperty__webkit_text_stroke_color ||
aProperty == eCSSProperty_fill ||
aProperty == eCSSProperty_stroke,
"we need to add to nsStyleContext::CalcStyleDifference");
bool isPaintProperty = aProperty == eCSSProperty_fill ||
aProperty == eCSSProperty_stroke;
nscolor colors[2];
colors[0] = isPaintProperty ? ExtractColorLenient(aProperty, this)
: ExtractColor(aProperty, this).value();
nsStyleContext *visitedStyle = this->GetStyleIfVisited();
if (!visitedStyle) {
return colors[0];
}
colors[1] = isPaintProperty ? ExtractColorLenient(aProperty, visitedStyle)
: ExtractColor(aProperty, visitedStyle).value();
return nsStyleContext::CombineVisitedColors(colors,
this->RelevantLinkVisited());
}
/* static */ nscolor
nsStyleContext::CombineVisitedColors(nscolor *aColors, bool aLinkIsVisited)
{

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/RestyleLogging.h"
#include "mozilla/StyleContextSource.h"
#include "mozilla/StyleComplexColor.h"
#include "nsCSSAnonBoxes.h"
#include "nsStyleSet.h"
@ -409,11 +410,12 @@ public:
* Get a color that depends on link-visitedness using this and
* this->GetStyleIfVisited().
*
* aProperty must be a color-valued property that StyleAnimationValue
* knows how to extract. It must also be a property that we know to
* do change handling for in nsStyleContext::CalcDifference.
* @param aField A pointer to a member variable in a style struct.
* The member variable and its style struct must have
* been listed in nsCSSVisitedDependentPropList.h.
*/
nscolor GetVisitedDependentColor(nsCSSPropertyID aProperty);
template<typename T, typename S>
nscolor GetVisitedDependentColor(T S::* aField);
/**
* aColors should be a two element array of nscolor in which the first

Просмотреть файл

@ -1411,6 +1411,22 @@ public:
mozilla::StyleComplexColor mBorderColor[4];
};
static mozilla::StyleComplexColor nsStyleBorder::*
BorderColorFieldFor(mozilla::Side aSide) {
switch (aSide) {
case mozilla::eSideTop:
return &nsStyleBorder::mBorderTopColor;
case mozilla::eSideRight:
return &nsStyleBorder::mBorderRightColor;
case mozilla::eSideBottom:
return &nsStyleBorder::mBorderBottomColor;
case mozilla::eSideLeft:
return &nsStyleBorder::mBorderLeftColor;
}
MOZ_ASSERT_UNREACHABLE("Unknown side");
return nullptr;
}
protected:
// mComputedBorder holds the CSS2.1 computed border-width values.
// In particular, these widths take into account the border-style

Просмотреть файл

@ -4812,8 +4812,8 @@ GetColorAndStyle(const nsIFrame* aFrame,
(NS_STYLE_BORDER_STYLE_HIDDEN == *aStyle)) {
return;
}
*aColor = aFrame->StyleContext()->GetVisitedDependentColor(
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[physicalSide]);
*aColor = aFrame->StyleContext()->
GetVisitedDependentColor(nsStyleBorder::BorderColorFieldFor(physicalSide));
if (aWidth) {
nscoord width = styleData->GetComputedBorderWidth(physicalSide);