From c0d0283f4f5d20a30fb274d64881e5b84afd4782 Mon Sep 17 00:00:00 2001 From: "hyatt%netscape.com" Date: Wed, 14 Nov 2001 08:19:13 +0000 Subject: [PATCH] Perf and footprint opt. Make style re-resolution cheaper. r=glazou, sr=hewitt, bug 109261 git-svn-id: svn://10.0.0.236/trunk@108035 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsRuleNode.cpp | 92 ++-- mozilla/content/base/src/nsStyleContext.cpp | 446 ++++++++++-------- mozilla/content/shared/public/nsRuleNode.h | 48 +- mozilla/layout/base/nsFrameManager.cpp | 2 +- mozilla/layout/base/public/nsIStyleContext.h | 2 +- .../layout/html/base/src/nsFrameManager.cpp | 2 +- mozilla/layout/style/nsRuleNode.cpp | 92 ++-- mozilla/layout/style/nsRuleNode.h | 48 +- mozilla/layout/style/nsStyleContext.cpp | 446 ++++++++++-------- 9 files changed, 659 insertions(+), 519 deletions(-) diff --git a/mozilla/content/base/src/nsRuleNode.cpp b/mozilla/content/base/src/nsRuleNode.cpp index 971ddfc08e5..05e475a13aa 100644 --- a/mozilla/content/base/src/nsRuleNode.cpp +++ b/mozilla/content/base/src/nsRuleNode.cpp @@ -1097,7 +1097,7 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, } const nsStyleStruct* -nsRuleNode::GetDisplayData(nsIStyleContext* aContext) +nsRuleNode::GetDisplayData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Display, mPresContext, aContext); @@ -1105,97 +1105,97 @@ nsRuleNode::GetDisplayData(nsIStyleContext* aContext) nsCSSRect clip; displayData.mClip = &clip; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData, aComputeData); displayData.mClip = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetVisibilityData(nsIStyleContext* aContext) +nsRuleNode::GetVisibilityData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Visibility, mPresContext, aContext); ruleData.mDisplayData = &displayData; - return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData); + return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetTextData(nsIStyleContext* aContext) +nsRuleNode::GetTextData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Text, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData); + return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetTextResetData(nsIStyleContext* aContext) +nsRuleNode::GetTextResetData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TextReset, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData); + return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetUIData(nsIStyleContext* aContext) +nsRuleNode::GetUIData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UserInterface, mPresContext, aContext); ruleData.mUIData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData, aComputeData); uiData.mCursor = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetUIResetData(nsIStyleContext* aContext) +nsRuleNode::GetUIResetData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UIReset, mPresContext, aContext); ruleData.mUIData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData, aComputeData); uiData.mKeyEquivalent = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetFontData(nsIStyleContext* aContext) +nsRuleNode::GetFontData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSFont fontData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Font, mPresContext, aContext); ruleData.mFontData = &fontData; - return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData); + return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetColorData(nsIStyleContext* aContext) +nsRuleNode::GetColorData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Color, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData); + return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetBackgroundData(nsIStyleContext* aContext) +nsRuleNode::GetBackgroundData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Background, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData); + return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetMarginData(nsIStyleContext* aContext) +nsRuleNode::GetMarginData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Margin, mPresContext, aContext); @@ -1204,14 +1204,14 @@ nsRuleNode::GetMarginData(nsIStyleContext* aContext) nsCSSRect margin; marginData.mMargin = &margin; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData, aComputeData); marginData.mMargin = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetBorderData(nsIStyleContext* aContext) +nsRuleNode::GetBorderData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Border, mPresContext, aContext); @@ -1226,14 +1226,14 @@ nsRuleNode::GetBorderData(nsIStyleContext* aContext) marginData.mBorderStyle = &borderStyle; marginData.mBorderRadius = &borderRadius; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData, aComputeData); marginData.mBorderWidth = marginData.mBorderColor = marginData.mBorderStyle = marginData.mBorderRadius = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetPaddingData(nsIStyleContext* aContext) +nsRuleNode::GetPaddingData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Padding, mPresContext, aContext); @@ -1242,14 +1242,14 @@ nsRuleNode::GetPaddingData(nsIStyleContext* aContext) nsCSSRect padding; marginData.mPadding = &padding; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData, aComputeData); marginData.mPadding = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetOutlineData(nsIStyleContext* aContext) +nsRuleNode::GetOutlineData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Outline, mPresContext, aContext); @@ -1258,24 +1258,24 @@ nsRuleNode::GetOutlineData(nsIStyleContext* aContext) nsCSSRect outlineRadius; marginData.mOutlineRadius = &outlineRadius; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData, aComputeData); marginData.mOutlineRadius = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetListData(nsIStyleContext* aContext) +nsRuleNode::GetListData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSList listData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_List, mPresContext, aContext); ruleData.mListData = &listData; - return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData); + return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetPositionData(nsIStyleContext* aContext) +nsRuleNode::GetPositionData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSPosition posData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Position, mPresContext, aContext); @@ -1284,66 +1284,66 @@ nsRuleNode::GetPositionData(nsIStyleContext* aContext) nsCSSRect offset; posData.mOffset = &offset; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData, aComputeData); posData.mOffset = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetTableData(nsIStyleContext* aContext) +nsRuleNode::GetTableData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Table, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData); + return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetTableBorderData(nsIStyleContext* aContext) +nsRuleNode::GetTableBorderData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TableBorder, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData); + return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetContentData(nsIStyleContext* aContext) +nsRuleNode::GetContentData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Content, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData, aComputeData); contentData.mCounterIncrement = contentData.mCounterReset = nsnull; contentData.mContent = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* -nsRuleNode::GetQuotesData(nsIStyleContext* aContext) +nsRuleNode::GetQuotesData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Quotes, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData, aComputeData); contentData.mQuotes = nsnull; // We are sharing with some style rule. It really owns the data. return res; } #ifdef INCLUDE_XUL const nsStyleStruct* -nsRuleNode::GetXULData(nsIStyleContext* aContext) +nsRuleNode::GetXULData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSXUL xulData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_XUL, mPresContext, aContext); ruleData.mXULData = &xulData; - return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData); + return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData, aComputeData); } #endif @@ -1351,7 +1351,8 @@ const nsStyleStruct* nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, nsIStyleContext* aContext, nsRuleData* aRuleData, - nsCSSStruct* aSpecificData) + nsCSSStruct* aSpecificData, + PRBool aComputeData) { // We start at the most specific rule in the tree. nsStyleStruct* startStruct = nsnull; @@ -1449,6 +1450,9 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, } // We need to compute the data from the information that the rules specified. + if (!aComputeData) + return nsnull; + ComputeStyleDataFn fn = gComputeStyleDataFn[aSID]; const nsStyleStruct* res = (this->*fn)(startStruct, *aSpecificData, aContext, highestNode, detail, !aRuleData->mCanStoreInRuleTree); @@ -4299,7 +4303,8 @@ nsRuleNode::gGetStyleDataFn[] = { const nsStyleStruct* nsRuleNode::GetStyleData(nsStyleStructID aSID, - nsIStyleContext* aContext) + nsIStyleContext* aContext, + PRBool aComputeData) { const nsStyleStruct* cachedData = mStyleData.GetStyleData(aSID); if (cachedData) @@ -4311,6 +4316,5 @@ nsRuleNode::GetStyleData(nsStyleStructID aSID, // Nothing is cached. We'll have to delve further and examine our rules. GetStyleDataFn fn = gGetStyleDataFn[aSID]; - return fn ? (this->*fn)(aContext) : nsnull; + return fn ? (this->*fn)(aContext, aComputeData) : nsnull; } - diff --git a/mozilla/content/base/src/nsStyleContext.cpp b/mozilla/content/base/src/nsStyleContext.cpp index 75072b4fae3..bbc00b6c141 100644 --- a/mozilla/content/base/src/nsStyleContext.cpp +++ b/mozilla/content/base/src/nsStyleContext.cpp @@ -99,6 +99,8 @@ public: NS_IMETHOD GetStyleBits(PRUint32* aBits) { *aBits = mBits; return NS_OK; }; virtual const nsStyleStruct* GetStyleData(nsStyleStructID aSID); + const nsStyleStruct* PeekStyleData(nsStyleStructID aSID); + virtual nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID); virtual nsresult ClearCachedDataForRule(nsIStyleRule* aRule); @@ -106,7 +108,7 @@ public: virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); virtual void ForceUnique(void); - NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBool aStopAtFirstDifference = PR_FALSE); + NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint); #ifdef DEBUG virtual void DumpRegressionData(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent); @@ -376,7 +378,15 @@ const nsStyleStruct* nsStyleContext::GetStyleData(nsStyleStructID aSID) const nsStyleStruct* cachedData = mCachedStyleData.GetStyleData(aSID); if (cachedData) return cachedData; // We have computed data stored on this node in the context tree. - return mRuleNode->GetStyleData(aSID, this); // Our rule node will take care of it for us. + return mRuleNode->GetStyleData(aSID, this, PR_TRUE); // Our rule node will take care of it for us. +} + +const nsStyleStruct* nsStyleContext::PeekStyleData(nsStyleStructID aSID) +{ + const nsStyleStruct* cachedData = mCachedStyleData.GetStyleData(aSID); + if (cachedData) + return cachedData; // We have computed data stored on this node in the context tree. + return mRuleNode->GetStyleData(aSID, this, PR_FALSE); // Our rule node will take care of it for us. } NS_IMETHODIMP @@ -617,72 +627,257 @@ void nsStyleContext::ForceUnique(void) } NS_IMETHODIMP -nsStyleContext::CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBool aStopAtFirstDifference /*= PR_FALSE*/) +nsStyleContext::CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint) { if (aOther) { + // If our rule nodes are the same, then we are looking at the same style + // data. We know this because CalcStyleDifference is always called on two + // style contexts that point to the same element, so we know that our position + // in the style context tree is the same and our position in the rule node tree + // is also the same. + nsRuleNode* ruleNode; + aOther->GetRuleNode(&ruleNode); + if (ruleNode == mRuleNode) + return NS_OK; + + PRInt32 maxHint = NS_STYLE_HINT_MAX; PRInt32 hint; - const nsStyleContext* other = (const nsStyleContext*)aOther; - - const nsStyleFont* font = (const nsStyleFont*)GetStyleData(eStyleStruct_Font); - const nsStyleFont* otherFont = (const nsStyleFont*)aOther->GetStyleData(eStyleStruct_Font); - if (font != otherFont) - aHint = font->CalcDifference(*otherFont); - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleColor* color = (const nsStyleColor*)GetStyleData(eStyleStruct_Color); - const nsStyleColor* otherColor = (const nsStyleColor*)aOther->GetStyleData(eStyleStruct_Color); - if (color != otherColor) { - hint = color->CalcDifference(*otherColor); - if (aHint < hint) - aHint = hint; + // We begin by examining those style structs that are capable of causing the maximal + // difference, a FRAMECHANGE. + // FRAMECHANGE Structs: Display, XUL, Content, UserInterface + if (aHint < maxHint) { + const nsStyleDisplay* display = (const nsStyleDisplay*)PeekStyleData(eStyleStruct_Display); + if (display) { + const nsStyleDisplay* otherDisplay = (const nsStyleDisplay*)aOther->GetStyleData(eStyleStruct_Display); + if (display != otherDisplay) { + hint = display->CalcDifference(*otherDisplay); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleBackground* background = (const nsStyleBackground*)GetStyleData(eStyleStruct_Background); - const nsStyleBackground* otherBackground = (const nsStyleBackground*)aOther->GetStyleData(eStyleStruct_Background); - if (background != otherBackground) { - hint = background->CalcDifference(*otherBackground); - if (aHint < hint) - aHint = hint; +#ifdef INCLUDE_XUL + if (aHint < maxHint) { + const nsStyleXUL* xul = (const nsStyleXUL*)PeekStyleData(eStyleStruct_XUL); + if (xul) { + const nsStyleXUL* otherXUL = (const nsStyleXUL*)aOther->GetStyleData(eStyleStruct_XUL); + if (xul != otherXUL) { + hint = xul->CalcDifference(*otherXUL); + if (aHint < hint) + aHint = hint; + } + } + } +#endif + + if (aHint < maxHint) { + const nsStyleContent* content = (const nsStyleContent*)PeekStyleData(eStyleStruct_Content); + if (content) { + const nsStyleContent* otherContent = (const nsStyleContent*)aOther->GetStyleData(eStyleStruct_Content); + if (content != otherContent) { + hint = content->CalcDifference(*otherContent); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleMargin* margin = (const nsStyleMargin*)GetStyleData(eStyleStruct_Margin); - const nsStyleMargin* otherMargin = (const nsStyleMargin*)aOther->GetStyleData(eStyleStruct_Margin); - if (margin != otherMargin) { - hint = margin->CalcDifference(*otherMargin); - if (aHint < hint) - aHint = hint; + if (aHint < maxHint) { + const nsStyleUserInterface* ui = (const nsStyleUserInterface*)PeekStyleData(eStyleStruct_UserInterface); + if (ui) { + const nsStyleUserInterface* otherUI = (const nsStyleUserInterface*)aOther->GetStyleData(eStyleStruct_UserInterface); + if (ui != otherUI) { + hint = ui->CalcDifference(*otherUI); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStylePadding* padding = (const nsStylePadding*)GetStyleData(eStyleStruct_Padding); - const nsStylePadding* otherPadding = (const nsStylePadding*)aOther->GetStyleData(eStyleStruct_Padding); - if (padding != otherPadding) { - hint = padding->CalcDifference(*otherPadding); - if (aHint < hint) - aHint = hint; + // At this point, we know that the worst kind of damage we could do is a reflow. + maxHint = NS_STYLE_HINT_REFLOW; + + // The following structs cause (as their maximal difference) a reflow to occur. + // REFLOW Structs: Font, Margin, Padding, Border, List, Position, Text, TextReset, + // Visibility, Quotes, Table, TableBorder + if (aHint < maxHint) { + const nsStyleContext* other = (const nsStyleContext*)aOther; + const nsStyleFont* font = (const nsStyleFont*)PeekStyleData(eStyleStruct_Font); + if (font) { + const nsStyleFont* otherFont = (const nsStyleFont*)aOther->GetStyleData(eStyleStruct_Font); + if (font != otherFont) { + hint = font->CalcDifference(*otherFont); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleBorder* border = (const nsStyleBorder*)GetStyleData(eStyleStruct_Border); - const nsStyleBorder* otherBorder = (const nsStyleBorder*)aOther->GetStyleData(eStyleStruct_Border); - if (border != otherBorder) { - hint = border->CalcDifference(*otherBorder); - if (aHint < hint) - aHint = hint; + + if (aHint < maxHint) { + const nsStyleMargin* margin = (const nsStyleMargin*)PeekStyleData(eStyleStruct_Margin); + if (margin) { + const nsStyleMargin* otherMargin = (const nsStyleMargin*)aOther->GetStyleData(eStyleStruct_Margin); + if (margin != otherMargin) { + hint = margin->CalcDifference(*otherMargin); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { + + if (aHint < maxHint) { + const nsStylePadding* padding = (const nsStylePadding*)PeekStyleData(eStyleStruct_Padding); + if (padding) { + const nsStylePadding* otherPadding = (const nsStylePadding*)aOther->GetStyleData(eStyleStruct_Padding); + if (padding != otherPadding) { + hint = padding->CalcDifference(*otherPadding); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleBorder* border = (const nsStyleBorder*)PeekStyleData(eStyleStruct_Border); + if (border) { + const nsStyleBorder* otherBorder = (const nsStyleBorder*)aOther->GetStyleData(eStyleStruct_Border); + if (border != otherBorder) { + hint = border->CalcDifference(*otherBorder); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleList* list = (const nsStyleList*)PeekStyleData(eStyleStruct_List); + if (list) { + const nsStyleList* otherList = (const nsStyleList*)aOther->GetStyleData(eStyleStruct_List); + if (list != otherList) { + hint = list->CalcDifference(*otherList); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStylePosition* pos = (const nsStylePosition*)PeekStyleData(eStyleStruct_Position); + if (pos) { + const nsStylePosition* otherPosition = (const nsStylePosition*)aOther->GetStyleData(eStyleStruct_Position); + if (pos != otherPosition) { + hint = pos->CalcDifference(*otherPosition); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleText* text = (const nsStyleText*)PeekStyleData(eStyleStruct_Text); + if (text) { + const nsStyleText* otherText = (const nsStyleText*)aOther->GetStyleData(eStyleStruct_Text); + if (text != otherText) { + hint = text->CalcDifference(*otherText); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleTextReset* text = (const nsStyleTextReset*)PeekStyleData(eStyleStruct_TextReset); + if (text) { + const nsStyleTextReset* otherText = (const nsStyleTextReset*)aOther->GetStyleData(eStyleStruct_TextReset); + if (text != otherText) { + hint = text->CalcDifference(*otherText); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleVisibility* vis = (const nsStyleVisibility*)PeekStyleData(eStyleStruct_Visibility); + if (vis) { + const nsStyleVisibility* otherVis = (const nsStyleVisibility*)aOther->GetStyleData(eStyleStruct_Visibility); + if (vis != otherVis) { + hint = vis->CalcDifference(*otherVis); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleTable* table = (const nsStyleTable*)PeekStyleData(eStyleStruct_Table); + if (table) { + const nsStyleTable* otherTable = (const nsStyleTable*)aOther->GetStyleData(eStyleStruct_Table); + if (table != otherTable) { + hint = table->CalcDifference(*otherTable); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleTableBorder* table = (const nsStyleTableBorder*)PeekStyleData(eStyleStruct_TableBorder); + if (table) { + const nsStyleTableBorder* otherTable = (const nsStyleTableBorder*)aOther->GetStyleData(eStyleStruct_TableBorder); + if (table != otherTable) { + hint = table->CalcDifference(*otherTable); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleQuotes* quotes = (const nsStyleQuotes*)PeekStyleData(eStyleStruct_Quotes); + if (quotes) { + const nsStyleQuotes* otherQuotes = (const nsStyleQuotes*)aOther->GetStyleData(eStyleStruct_Quotes); + if (quotes != otherQuotes) { + hint = quotes->CalcDifference(*otherQuotes); + if (aHint < hint) + aHint = hint; + } + } + } + + // At this point, we know that the worst kind of damage we could do is a re-render + // (i.e., a VISUAL change). + maxHint = NS_STYLE_HINT_VISUAL; + + // The following structs cause (as their maximal difference) a re-render to occur. + // VISUAL Structs: Color, Background, Outline, UIReset + if (aHint < maxHint) { + const nsStyleColor* color = (const nsStyleColor*)PeekStyleData(eStyleStruct_Color); + if (color) { + const nsStyleColor* otherColor = (const nsStyleColor*)aOther->GetStyleData(eStyleStruct_Color); + if (color != otherColor) { + hint = color->CalcDifference(*otherColor); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleBackground* background = (const nsStyleBackground*)PeekStyleData(eStyleStruct_Background); + if (background) { + const nsStyleBackground* otherBackground = (const nsStyleBackground*)aOther->GetStyleData(eStyleStruct_Background); + if (background != otherBackground) { + hint = background->CalcDifference(*otherBackground); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { const nsStyleOutline* outline = (const nsStyleOutline*)GetStyleData(eStyleStruct_Outline); const nsStyleOutline* otherOutline = (const nsStyleOutline*)aOther->GetStyleData(eStyleStruct_Outline); if (outline != otherOutline) { @@ -691,149 +886,18 @@ nsStyleContext::CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBo aHint = hint; } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleList* list = (const nsStyleList*)GetStyleData(eStyleStruct_List); - const nsStyleList* otherList = (const nsStyleList*)aOther->GetStyleData(eStyleStruct_List); - if (list != otherList) { - hint = list->CalcDifference(*otherList); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStylePosition* pos = (const nsStylePosition*)GetStyleData(eStyleStruct_Position); - const nsStylePosition* otherPosition = (const nsStylePosition*)aOther->GetStyleData(eStyleStruct_Position); - if (pos != otherPosition) { - hint = pos->CalcDifference(*otherPosition); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleText* text = (const nsStyleText*)GetStyleData(eStyleStruct_Text); - const nsStyleText* otherText = (const nsStyleText*)aOther->GetStyleData(eStyleStruct_Text); - if (text != otherText) { - hint = text->CalcDifference(*otherText); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleTextReset* text = (const nsStyleTextReset*)GetStyleData(eStyleStruct_TextReset); - const nsStyleTextReset* otherText = (const nsStyleTextReset*)aOther->GetStyleData(eStyleStruct_TextReset); - if (text != otherText) { - hint = text->CalcDifference(*otherText); - if (aHint < hint) - aHint = hint; + if (aHint < maxHint) { + const nsStyleUIReset* ui = (const nsStyleUIReset*)PeekStyleData(eStyleStruct_UIReset); + if (ui) { + const nsStyleUIReset* otherUI = (const nsStyleUIReset*)aOther->GetStyleData(eStyleStruct_UIReset); + if (ui != otherUI) { + hint = ui->CalcDifference(*otherUI); + if (aHint < hint) + aHint = hint; + } } } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleVisibility* vis = (const nsStyleVisibility*)GetStyleData(eStyleStruct_Visibility); - const nsStyleVisibility* otherVis = (const nsStyleVisibility*)aOther->GetStyleData(eStyleStruct_Visibility); - if (vis != otherVis) { - hint = vis->CalcDifference(*otherVis); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleDisplay* display = (const nsStyleDisplay*)GetStyleData(eStyleStruct_Display); - const nsStyleDisplay* otherDisplay = (const nsStyleDisplay*)aOther->GetStyleData(eStyleStruct_Display); - if (display != otherDisplay) { - hint = display->CalcDifference(*otherDisplay); - if (aHint < hint) - aHint = hint; - } - } - -#ifdef INCLUDE_XUL - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleXUL* xul = (const nsStyleXUL*)GetStyleData(eStyleStruct_XUL); - const nsStyleXUL* otherXUL = (const nsStyleXUL*)aOther->GetStyleData(eStyleStruct_XUL); - if (xul != otherXUL) { - hint = xul->CalcDifference(*otherXUL); - if (aHint < hint) - aHint = hint; - } - } -#endif - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleTable* table = (const nsStyleTable*)GetStyleData(eStyleStruct_Table); - const nsStyleTable* otherTable = (const nsStyleTable*)aOther->GetStyleData(eStyleStruct_Table); - if (table != otherTable) { - hint = table->CalcDifference(*otherTable); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleTableBorder* table = (const nsStyleTableBorder*)GetStyleData(eStyleStruct_TableBorder); - const nsStyleTableBorder* otherTable = (const nsStyleTableBorder*)aOther->GetStyleData(eStyleStruct_TableBorder); - if (table != otherTable) { - hint = table->CalcDifference(*otherTable); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleContent* content = (const nsStyleContent*)GetStyleData(eStyleStruct_Content); - const nsStyleContent* otherContent = (const nsStyleContent*)aOther->GetStyleData(eStyleStruct_Content); - if (content != otherContent) { - hint = content->CalcDifference(*otherContent); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleQuotes* content = (const nsStyleQuotes*)GetStyleData(eStyleStruct_Quotes); - const nsStyleQuotes* otherContent = (const nsStyleQuotes*)aOther->GetStyleData(eStyleStruct_Quotes); - if (content != otherContent) { - hint = content->CalcDifference(*otherContent); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleUserInterface* ui = (const nsStyleUserInterface*)GetStyleData(eStyleStruct_UserInterface); - const nsStyleUserInterface* otherUI = (const nsStyleUserInterface*)aOther->GetStyleData(eStyleStruct_UserInterface); - if (ui != otherUI) { - hint = ui->CalcDifference(*otherUI); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleUIReset* ui = (const nsStyleUIReset*)GetStyleData(eStyleStruct_UIReset); - const nsStyleUIReset* otherUI = (const nsStyleUIReset*)aOther->GetStyleData(eStyleStruct_UIReset); - if (ui != otherUI) { - hint = ui->CalcDifference(*otherUI); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; } return NS_OK; } diff --git a/mozilla/content/shared/public/nsRuleNode.h b/mozilla/content/shared/public/nsRuleNode.h index 915f03eb3d4..a839f905438 100644 --- a/mozilla/content/shared/public/nsRuleNode.h +++ b/mozilla/content/shared/public/nsRuleNode.h @@ -385,7 +385,8 @@ protected: const nsStyleStruct* WalkRuleTree(const nsStyleStructID aSID, nsIStyleContext* aContext, nsRuleData* aRuleData, - nsCSSStruct* aSpecificData); + nsCSSStruct* aSpecificData, + PRBool aComputeData); const nsStyleStruct* ComputeDisplayData(nsStyleStruct* aStartDisplay, const nsCSSStruct& aDisplayData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, @@ -471,30 +472,30 @@ protected: inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID, const nsCSSStruct& aCSSStruct); const nsStyleStruct* GetParentData(const nsStyleStructID aSID); - const nsStyleStruct* GetDisplayData(nsIStyleContext* aContext); - const nsStyleStruct* GetVisibilityData(nsIStyleContext* aContext); - const nsStyleStruct* GetFontData(nsIStyleContext* aContext); - const nsStyleStruct* GetColorData(nsIStyleContext* aContext); - const nsStyleStruct* GetBackgroundData(nsIStyleContext* aContext); - const nsStyleStruct* GetMarginData(nsIStyleContext* aContext); - const nsStyleStruct* GetBorderData(nsIStyleContext* aContext); - const nsStyleStruct* GetPaddingData(nsIStyleContext* aContext); - const nsStyleStruct* GetOutlineData(nsIStyleContext* aContext); - const nsStyleStruct* GetListData(nsIStyleContext* aContext); - const nsStyleStruct* GetPositionData(nsIStyleContext* aContext); - const nsStyleStruct* GetTableData(nsIStyleContext* aContext); - const nsStyleStruct* GetTableBorderData(nsIStyleContext* aContext); - const nsStyleStruct* GetContentData(nsIStyleContext* aContext); - const nsStyleStruct* GetQuotesData(nsIStyleContext* aContext); - const nsStyleStruct* GetTextData(nsIStyleContext* aContext); - const nsStyleStruct* GetTextResetData(nsIStyleContext* aContext); - const nsStyleStruct* GetUIData(nsIStyleContext* aContext); - const nsStyleStruct* GetUIResetData(nsIStyleContext* aContext); + const nsStyleStruct* GetDisplayData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetVisibilityData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetFontData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetColorData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetBackgroundData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetMarginData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetBorderData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetPaddingData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetOutlineData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetListData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetPositionData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTableData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTableBorderData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetContentData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetQuotesData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTextData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTextResetData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetUIData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetUIResetData(nsIStyleContext* aContext, PRBool aComputeData); #ifdef INCLUDE_XUL - const nsStyleStruct* GetXULData(nsIStyleContext* aContext); + const nsStyleStruct* GetXULData(nsIStyleContext* aContext, PRBool aComputeData); #endif - typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsIStyleContext*); + typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsIStyleContext*, PRBool); static GetStyleDataFn gGetStyleDataFn[]; public: @@ -519,7 +520,8 @@ public: nsresult GetPresContext(nsIPresContext** aResult); nsresult PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched); const nsStyleStruct* GetStyleData(nsStyleStructID aSID, - nsIStyleContext* aContext); + nsIStyleContext* aContext, + PRBool aComputeData); }; #endif diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index ed9258764ca..39ae2d2bf3c 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -1546,7 +1546,7 @@ CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext, nsStyleChangeList& aChangeList, PRInt32 aMinChange) { PRInt32 ourChange = NS_STYLE_HINT_NONE; - aNewContext->CalcStyleDifference(aOldContext, ourChange); + aOldContext->CalcStyleDifference(aNewContext, ourChange); if (aMinChange < ourChange) { aChangeList.AppendChange(aFrame, aContent, ourChange); aMinChange = ourChange; diff --git a/mozilla/layout/base/public/nsIStyleContext.h b/mozilla/layout/base/public/nsIStyleContext.h index f2bc335bf7e..cab9f716ad7 100644 --- a/mozilla/layout/base/public/nsIStyleContext.h +++ b/mozilla/layout/base/public/nsIStyleContext.h @@ -86,7 +86,7 @@ public: NS_IMETHOD GetBorderPaddingFor(nsStyleBorderPadding& aBorderPadding)=0; // compute the effective difference between two contexts - NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint, PRBool aStopAtFirst = PR_FALSE) = 0; + NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint) = 0; NS_IMETHOD GetRuleNode(nsRuleNode** aResult)=0; NS_IMETHOD AddStyleBit(const PRUint32& aBit)=0; diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index ed9258764ca..39ae2d2bf3c 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -1546,7 +1546,7 @@ CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext, nsStyleChangeList& aChangeList, PRInt32 aMinChange) { PRInt32 ourChange = NS_STYLE_HINT_NONE; - aNewContext->CalcStyleDifference(aOldContext, ourChange); + aOldContext->CalcStyleDifference(aNewContext, ourChange); if (aMinChange < ourChange) { aChangeList.AppendChange(aFrame, aContent, ourChange); aMinChange = ourChange; diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index 971ddfc08e5..05e475a13aa 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -1097,7 +1097,7 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, } const nsStyleStruct* -nsRuleNode::GetDisplayData(nsIStyleContext* aContext) +nsRuleNode::GetDisplayData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Display, mPresContext, aContext); @@ -1105,97 +1105,97 @@ nsRuleNode::GetDisplayData(nsIStyleContext* aContext) nsCSSRect clip; displayData.mClip = &clip; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData, aComputeData); displayData.mClip = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetVisibilityData(nsIStyleContext* aContext) +nsRuleNode::GetVisibilityData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Visibility, mPresContext, aContext); ruleData.mDisplayData = &displayData; - return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData); + return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetTextData(nsIStyleContext* aContext) +nsRuleNode::GetTextData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Text, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData); + return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetTextResetData(nsIStyleContext* aContext) +nsRuleNode::GetTextResetData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TextReset, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData); + return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetUIData(nsIStyleContext* aContext) +nsRuleNode::GetUIData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UserInterface, mPresContext, aContext); ruleData.mUIData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData, aComputeData); uiData.mCursor = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetUIResetData(nsIStyleContext* aContext) +nsRuleNode::GetUIResetData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UIReset, mPresContext, aContext); ruleData.mUIData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData, aComputeData); uiData.mKeyEquivalent = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetFontData(nsIStyleContext* aContext) +nsRuleNode::GetFontData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSFont fontData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Font, mPresContext, aContext); ruleData.mFontData = &fontData; - return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData); + return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetColorData(nsIStyleContext* aContext) +nsRuleNode::GetColorData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Color, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData); + return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetBackgroundData(nsIStyleContext* aContext) +nsRuleNode::GetBackgroundData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Background, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData); + return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetMarginData(nsIStyleContext* aContext) +nsRuleNode::GetMarginData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Margin, mPresContext, aContext); @@ -1204,14 +1204,14 @@ nsRuleNode::GetMarginData(nsIStyleContext* aContext) nsCSSRect margin; marginData.mMargin = &margin; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData, aComputeData); marginData.mMargin = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetBorderData(nsIStyleContext* aContext) +nsRuleNode::GetBorderData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Border, mPresContext, aContext); @@ -1226,14 +1226,14 @@ nsRuleNode::GetBorderData(nsIStyleContext* aContext) marginData.mBorderStyle = &borderStyle; marginData.mBorderRadius = &borderRadius; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData, aComputeData); marginData.mBorderWidth = marginData.mBorderColor = marginData.mBorderStyle = marginData.mBorderRadius = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetPaddingData(nsIStyleContext* aContext) +nsRuleNode::GetPaddingData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Padding, mPresContext, aContext); @@ -1242,14 +1242,14 @@ nsRuleNode::GetPaddingData(nsIStyleContext* aContext) nsCSSRect padding; marginData.mPadding = &padding; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData, aComputeData); marginData.mPadding = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetOutlineData(nsIStyleContext* aContext) +nsRuleNode::GetOutlineData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Outline, mPresContext, aContext); @@ -1258,24 +1258,24 @@ nsRuleNode::GetOutlineData(nsIStyleContext* aContext) nsCSSRect outlineRadius; marginData.mOutlineRadius = &outlineRadius; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData, aComputeData); marginData.mOutlineRadius = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetListData(nsIStyleContext* aContext) +nsRuleNode::GetListData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSList listData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_List, mPresContext, aContext); ruleData.mListData = &listData; - return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData); + return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetPositionData(nsIStyleContext* aContext) +nsRuleNode::GetPositionData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSPosition posData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Position, mPresContext, aContext); @@ -1284,66 +1284,66 @@ nsRuleNode::GetPositionData(nsIStyleContext* aContext) nsCSSRect offset; posData.mOffset = &offset; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData, aComputeData); posData.mOffset = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetTableData(nsIStyleContext* aContext) +nsRuleNode::GetTableData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Table, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData); + return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetTableBorderData(nsIStyleContext* aContext) +nsRuleNode::GetTableBorderData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TableBorder, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData); + return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData, aComputeData); } const nsStyleStruct* -nsRuleNode::GetContentData(nsIStyleContext* aContext) +nsRuleNode::GetContentData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Content, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData, aComputeData); contentData.mCounterIncrement = contentData.mCounterReset = nsnull; contentData.mContent = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* -nsRuleNode::GetQuotesData(nsIStyleContext* aContext) +nsRuleNode::GetQuotesData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Quotes, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData, aComputeData); contentData.mQuotes = nsnull; // We are sharing with some style rule. It really owns the data. return res; } #ifdef INCLUDE_XUL const nsStyleStruct* -nsRuleNode::GetXULData(nsIStyleContext* aContext) +nsRuleNode::GetXULData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSXUL xulData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_XUL, mPresContext, aContext); ruleData.mXULData = &xulData; - return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData); + return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData, aComputeData); } #endif @@ -1351,7 +1351,8 @@ const nsStyleStruct* nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, nsIStyleContext* aContext, nsRuleData* aRuleData, - nsCSSStruct* aSpecificData) + nsCSSStruct* aSpecificData, + PRBool aComputeData) { // We start at the most specific rule in the tree. nsStyleStruct* startStruct = nsnull; @@ -1449,6 +1450,9 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, } // We need to compute the data from the information that the rules specified. + if (!aComputeData) + return nsnull; + ComputeStyleDataFn fn = gComputeStyleDataFn[aSID]; const nsStyleStruct* res = (this->*fn)(startStruct, *aSpecificData, aContext, highestNode, detail, !aRuleData->mCanStoreInRuleTree); @@ -4299,7 +4303,8 @@ nsRuleNode::gGetStyleDataFn[] = { const nsStyleStruct* nsRuleNode::GetStyleData(nsStyleStructID aSID, - nsIStyleContext* aContext) + nsIStyleContext* aContext, + PRBool aComputeData) { const nsStyleStruct* cachedData = mStyleData.GetStyleData(aSID); if (cachedData) @@ -4311,6 +4316,5 @@ nsRuleNode::GetStyleData(nsStyleStructID aSID, // Nothing is cached. We'll have to delve further and examine our rules. GetStyleDataFn fn = gGetStyleDataFn[aSID]; - return fn ? (this->*fn)(aContext) : nsnull; + return fn ? (this->*fn)(aContext, aComputeData) : nsnull; } - diff --git a/mozilla/layout/style/nsRuleNode.h b/mozilla/layout/style/nsRuleNode.h index 915f03eb3d4..a839f905438 100644 --- a/mozilla/layout/style/nsRuleNode.h +++ b/mozilla/layout/style/nsRuleNode.h @@ -385,7 +385,8 @@ protected: const nsStyleStruct* WalkRuleTree(const nsStyleStructID aSID, nsIStyleContext* aContext, nsRuleData* aRuleData, - nsCSSStruct* aSpecificData); + nsCSSStruct* aSpecificData, + PRBool aComputeData); const nsStyleStruct* ComputeDisplayData(nsStyleStruct* aStartDisplay, const nsCSSStruct& aDisplayData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, @@ -471,30 +472,30 @@ protected: inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID, const nsCSSStruct& aCSSStruct); const nsStyleStruct* GetParentData(const nsStyleStructID aSID); - const nsStyleStruct* GetDisplayData(nsIStyleContext* aContext); - const nsStyleStruct* GetVisibilityData(nsIStyleContext* aContext); - const nsStyleStruct* GetFontData(nsIStyleContext* aContext); - const nsStyleStruct* GetColorData(nsIStyleContext* aContext); - const nsStyleStruct* GetBackgroundData(nsIStyleContext* aContext); - const nsStyleStruct* GetMarginData(nsIStyleContext* aContext); - const nsStyleStruct* GetBorderData(nsIStyleContext* aContext); - const nsStyleStruct* GetPaddingData(nsIStyleContext* aContext); - const nsStyleStruct* GetOutlineData(nsIStyleContext* aContext); - const nsStyleStruct* GetListData(nsIStyleContext* aContext); - const nsStyleStruct* GetPositionData(nsIStyleContext* aContext); - const nsStyleStruct* GetTableData(nsIStyleContext* aContext); - const nsStyleStruct* GetTableBorderData(nsIStyleContext* aContext); - const nsStyleStruct* GetContentData(nsIStyleContext* aContext); - const nsStyleStruct* GetQuotesData(nsIStyleContext* aContext); - const nsStyleStruct* GetTextData(nsIStyleContext* aContext); - const nsStyleStruct* GetTextResetData(nsIStyleContext* aContext); - const nsStyleStruct* GetUIData(nsIStyleContext* aContext); - const nsStyleStruct* GetUIResetData(nsIStyleContext* aContext); + const nsStyleStruct* GetDisplayData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetVisibilityData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetFontData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetColorData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetBackgroundData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetMarginData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetBorderData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetPaddingData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetOutlineData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetListData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetPositionData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTableData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTableBorderData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetContentData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetQuotesData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTextData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetTextResetData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetUIData(nsIStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetUIResetData(nsIStyleContext* aContext, PRBool aComputeData); #ifdef INCLUDE_XUL - const nsStyleStruct* GetXULData(nsIStyleContext* aContext); + const nsStyleStruct* GetXULData(nsIStyleContext* aContext, PRBool aComputeData); #endif - typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsIStyleContext*); + typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsIStyleContext*, PRBool); static GetStyleDataFn gGetStyleDataFn[]; public: @@ -519,7 +520,8 @@ public: nsresult GetPresContext(nsIPresContext** aResult); nsresult PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched); const nsStyleStruct* GetStyleData(nsStyleStructID aSID, - nsIStyleContext* aContext); + nsIStyleContext* aContext, + PRBool aComputeData); }; #endif diff --git a/mozilla/layout/style/nsStyleContext.cpp b/mozilla/layout/style/nsStyleContext.cpp index 75072b4fae3..bbc00b6c141 100644 --- a/mozilla/layout/style/nsStyleContext.cpp +++ b/mozilla/layout/style/nsStyleContext.cpp @@ -99,6 +99,8 @@ public: NS_IMETHOD GetStyleBits(PRUint32* aBits) { *aBits = mBits; return NS_OK; }; virtual const nsStyleStruct* GetStyleData(nsStyleStructID aSID); + const nsStyleStruct* PeekStyleData(nsStyleStructID aSID); + virtual nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID); virtual nsresult ClearCachedDataForRule(nsIStyleRule* aRule); @@ -106,7 +108,7 @@ public: virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); virtual void ForceUnique(void); - NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBool aStopAtFirstDifference = PR_FALSE); + NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint); #ifdef DEBUG virtual void DumpRegressionData(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent); @@ -376,7 +378,15 @@ const nsStyleStruct* nsStyleContext::GetStyleData(nsStyleStructID aSID) const nsStyleStruct* cachedData = mCachedStyleData.GetStyleData(aSID); if (cachedData) return cachedData; // We have computed data stored on this node in the context tree. - return mRuleNode->GetStyleData(aSID, this); // Our rule node will take care of it for us. + return mRuleNode->GetStyleData(aSID, this, PR_TRUE); // Our rule node will take care of it for us. +} + +const nsStyleStruct* nsStyleContext::PeekStyleData(nsStyleStructID aSID) +{ + const nsStyleStruct* cachedData = mCachedStyleData.GetStyleData(aSID); + if (cachedData) + return cachedData; // We have computed data stored on this node in the context tree. + return mRuleNode->GetStyleData(aSID, this, PR_FALSE); // Our rule node will take care of it for us. } NS_IMETHODIMP @@ -617,72 +627,257 @@ void nsStyleContext::ForceUnique(void) } NS_IMETHODIMP -nsStyleContext::CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBool aStopAtFirstDifference /*= PR_FALSE*/) +nsStyleContext::CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint) { if (aOther) { + // If our rule nodes are the same, then we are looking at the same style + // data. We know this because CalcStyleDifference is always called on two + // style contexts that point to the same element, so we know that our position + // in the style context tree is the same and our position in the rule node tree + // is also the same. + nsRuleNode* ruleNode; + aOther->GetRuleNode(&ruleNode); + if (ruleNode == mRuleNode) + return NS_OK; + + PRInt32 maxHint = NS_STYLE_HINT_MAX; PRInt32 hint; - const nsStyleContext* other = (const nsStyleContext*)aOther; - - const nsStyleFont* font = (const nsStyleFont*)GetStyleData(eStyleStruct_Font); - const nsStyleFont* otherFont = (const nsStyleFont*)aOther->GetStyleData(eStyleStruct_Font); - if (font != otherFont) - aHint = font->CalcDifference(*otherFont); - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleColor* color = (const nsStyleColor*)GetStyleData(eStyleStruct_Color); - const nsStyleColor* otherColor = (const nsStyleColor*)aOther->GetStyleData(eStyleStruct_Color); - if (color != otherColor) { - hint = color->CalcDifference(*otherColor); - if (aHint < hint) - aHint = hint; + // We begin by examining those style structs that are capable of causing the maximal + // difference, a FRAMECHANGE. + // FRAMECHANGE Structs: Display, XUL, Content, UserInterface + if (aHint < maxHint) { + const nsStyleDisplay* display = (const nsStyleDisplay*)PeekStyleData(eStyleStruct_Display); + if (display) { + const nsStyleDisplay* otherDisplay = (const nsStyleDisplay*)aOther->GetStyleData(eStyleStruct_Display); + if (display != otherDisplay) { + hint = display->CalcDifference(*otherDisplay); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleBackground* background = (const nsStyleBackground*)GetStyleData(eStyleStruct_Background); - const nsStyleBackground* otherBackground = (const nsStyleBackground*)aOther->GetStyleData(eStyleStruct_Background); - if (background != otherBackground) { - hint = background->CalcDifference(*otherBackground); - if (aHint < hint) - aHint = hint; +#ifdef INCLUDE_XUL + if (aHint < maxHint) { + const nsStyleXUL* xul = (const nsStyleXUL*)PeekStyleData(eStyleStruct_XUL); + if (xul) { + const nsStyleXUL* otherXUL = (const nsStyleXUL*)aOther->GetStyleData(eStyleStruct_XUL); + if (xul != otherXUL) { + hint = xul->CalcDifference(*otherXUL); + if (aHint < hint) + aHint = hint; + } + } + } +#endif + + if (aHint < maxHint) { + const nsStyleContent* content = (const nsStyleContent*)PeekStyleData(eStyleStruct_Content); + if (content) { + const nsStyleContent* otherContent = (const nsStyleContent*)aOther->GetStyleData(eStyleStruct_Content); + if (content != otherContent) { + hint = content->CalcDifference(*otherContent); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleMargin* margin = (const nsStyleMargin*)GetStyleData(eStyleStruct_Margin); - const nsStyleMargin* otherMargin = (const nsStyleMargin*)aOther->GetStyleData(eStyleStruct_Margin); - if (margin != otherMargin) { - hint = margin->CalcDifference(*otherMargin); - if (aHint < hint) - aHint = hint; + if (aHint < maxHint) { + const nsStyleUserInterface* ui = (const nsStyleUserInterface*)PeekStyleData(eStyleStruct_UserInterface); + if (ui) { + const nsStyleUserInterface* otherUI = (const nsStyleUserInterface*)aOther->GetStyleData(eStyleStruct_UserInterface); + if (ui != otherUI) { + hint = ui->CalcDifference(*otherUI); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStylePadding* padding = (const nsStylePadding*)GetStyleData(eStyleStruct_Padding); - const nsStylePadding* otherPadding = (const nsStylePadding*)aOther->GetStyleData(eStyleStruct_Padding); - if (padding != otherPadding) { - hint = padding->CalcDifference(*otherPadding); - if (aHint < hint) - aHint = hint; + // At this point, we know that the worst kind of damage we could do is a reflow. + maxHint = NS_STYLE_HINT_REFLOW; + + // The following structs cause (as their maximal difference) a reflow to occur. + // REFLOW Structs: Font, Margin, Padding, Border, List, Position, Text, TextReset, + // Visibility, Quotes, Table, TableBorder + if (aHint < maxHint) { + const nsStyleContext* other = (const nsStyleContext*)aOther; + const nsStyleFont* font = (const nsStyleFont*)PeekStyleData(eStyleStruct_Font); + if (font) { + const nsStyleFont* otherFont = (const nsStyleFont*)aOther->GetStyleData(eStyleStruct_Font); + if (font != otherFont) { + hint = font->CalcDifference(*otherFont); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleBorder* border = (const nsStyleBorder*)GetStyleData(eStyleStruct_Border); - const nsStyleBorder* otherBorder = (const nsStyleBorder*)aOther->GetStyleData(eStyleStruct_Border); - if (border != otherBorder) { - hint = border->CalcDifference(*otherBorder); - if (aHint < hint) - aHint = hint; + + if (aHint < maxHint) { + const nsStyleMargin* margin = (const nsStyleMargin*)PeekStyleData(eStyleStruct_Margin); + if (margin) { + const nsStyleMargin* otherMargin = (const nsStyleMargin*)aOther->GetStyleData(eStyleStruct_Margin); + if (margin != otherMargin) { + hint = margin->CalcDifference(*otherMargin); + if (aHint < hint) + aHint = hint; + } } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { + + if (aHint < maxHint) { + const nsStylePadding* padding = (const nsStylePadding*)PeekStyleData(eStyleStruct_Padding); + if (padding) { + const nsStylePadding* otherPadding = (const nsStylePadding*)aOther->GetStyleData(eStyleStruct_Padding); + if (padding != otherPadding) { + hint = padding->CalcDifference(*otherPadding); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleBorder* border = (const nsStyleBorder*)PeekStyleData(eStyleStruct_Border); + if (border) { + const nsStyleBorder* otherBorder = (const nsStyleBorder*)aOther->GetStyleData(eStyleStruct_Border); + if (border != otherBorder) { + hint = border->CalcDifference(*otherBorder); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleList* list = (const nsStyleList*)PeekStyleData(eStyleStruct_List); + if (list) { + const nsStyleList* otherList = (const nsStyleList*)aOther->GetStyleData(eStyleStruct_List); + if (list != otherList) { + hint = list->CalcDifference(*otherList); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStylePosition* pos = (const nsStylePosition*)PeekStyleData(eStyleStruct_Position); + if (pos) { + const nsStylePosition* otherPosition = (const nsStylePosition*)aOther->GetStyleData(eStyleStruct_Position); + if (pos != otherPosition) { + hint = pos->CalcDifference(*otherPosition); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleText* text = (const nsStyleText*)PeekStyleData(eStyleStruct_Text); + if (text) { + const nsStyleText* otherText = (const nsStyleText*)aOther->GetStyleData(eStyleStruct_Text); + if (text != otherText) { + hint = text->CalcDifference(*otherText); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleTextReset* text = (const nsStyleTextReset*)PeekStyleData(eStyleStruct_TextReset); + if (text) { + const nsStyleTextReset* otherText = (const nsStyleTextReset*)aOther->GetStyleData(eStyleStruct_TextReset); + if (text != otherText) { + hint = text->CalcDifference(*otherText); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleVisibility* vis = (const nsStyleVisibility*)PeekStyleData(eStyleStruct_Visibility); + if (vis) { + const nsStyleVisibility* otherVis = (const nsStyleVisibility*)aOther->GetStyleData(eStyleStruct_Visibility); + if (vis != otherVis) { + hint = vis->CalcDifference(*otherVis); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleTable* table = (const nsStyleTable*)PeekStyleData(eStyleStruct_Table); + if (table) { + const nsStyleTable* otherTable = (const nsStyleTable*)aOther->GetStyleData(eStyleStruct_Table); + if (table != otherTable) { + hint = table->CalcDifference(*otherTable); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleTableBorder* table = (const nsStyleTableBorder*)PeekStyleData(eStyleStruct_TableBorder); + if (table) { + const nsStyleTableBorder* otherTable = (const nsStyleTableBorder*)aOther->GetStyleData(eStyleStruct_TableBorder); + if (table != otherTable) { + hint = table->CalcDifference(*otherTable); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleQuotes* quotes = (const nsStyleQuotes*)PeekStyleData(eStyleStruct_Quotes); + if (quotes) { + const nsStyleQuotes* otherQuotes = (const nsStyleQuotes*)aOther->GetStyleData(eStyleStruct_Quotes); + if (quotes != otherQuotes) { + hint = quotes->CalcDifference(*otherQuotes); + if (aHint < hint) + aHint = hint; + } + } + } + + // At this point, we know that the worst kind of damage we could do is a re-render + // (i.e., a VISUAL change). + maxHint = NS_STYLE_HINT_VISUAL; + + // The following structs cause (as their maximal difference) a re-render to occur. + // VISUAL Structs: Color, Background, Outline, UIReset + if (aHint < maxHint) { + const nsStyleColor* color = (const nsStyleColor*)PeekStyleData(eStyleStruct_Color); + if (color) { + const nsStyleColor* otherColor = (const nsStyleColor*)aOther->GetStyleData(eStyleStruct_Color); + if (color != otherColor) { + hint = color->CalcDifference(*otherColor); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { + const nsStyleBackground* background = (const nsStyleBackground*)PeekStyleData(eStyleStruct_Background); + if (background) { + const nsStyleBackground* otherBackground = (const nsStyleBackground*)aOther->GetStyleData(eStyleStruct_Background); + if (background != otherBackground) { + hint = background->CalcDifference(*otherBackground); + if (aHint < hint) + aHint = hint; + } + } + } + + if (aHint < maxHint) { const nsStyleOutline* outline = (const nsStyleOutline*)GetStyleData(eStyleStruct_Outline); const nsStyleOutline* otherOutline = (const nsStyleOutline*)aOther->GetStyleData(eStyleStruct_Outline); if (outline != otherOutline) { @@ -691,149 +886,18 @@ nsStyleContext::CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBo aHint = hint; } } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleList* list = (const nsStyleList*)GetStyleData(eStyleStruct_List); - const nsStyleList* otherList = (const nsStyleList*)aOther->GetStyleData(eStyleStruct_List); - if (list != otherList) { - hint = list->CalcDifference(*otherList); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStylePosition* pos = (const nsStylePosition*)GetStyleData(eStyleStruct_Position); - const nsStylePosition* otherPosition = (const nsStylePosition*)aOther->GetStyleData(eStyleStruct_Position); - if (pos != otherPosition) { - hint = pos->CalcDifference(*otherPosition); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleText* text = (const nsStyleText*)GetStyleData(eStyleStruct_Text); - const nsStyleText* otherText = (const nsStyleText*)aOther->GetStyleData(eStyleStruct_Text); - if (text != otherText) { - hint = text->CalcDifference(*otherText); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleTextReset* text = (const nsStyleTextReset*)GetStyleData(eStyleStruct_TextReset); - const nsStyleTextReset* otherText = (const nsStyleTextReset*)aOther->GetStyleData(eStyleStruct_TextReset); - if (text != otherText) { - hint = text->CalcDifference(*otherText); - if (aHint < hint) - aHint = hint; + if (aHint < maxHint) { + const nsStyleUIReset* ui = (const nsStyleUIReset*)PeekStyleData(eStyleStruct_UIReset); + if (ui) { + const nsStyleUIReset* otherUI = (const nsStyleUIReset*)aOther->GetStyleData(eStyleStruct_UIReset); + if (ui != otherUI) { + hint = ui->CalcDifference(*otherUI); + if (aHint < hint) + aHint = hint; + } } } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleVisibility* vis = (const nsStyleVisibility*)GetStyleData(eStyleStruct_Visibility); - const nsStyleVisibility* otherVis = (const nsStyleVisibility*)aOther->GetStyleData(eStyleStruct_Visibility); - if (vis != otherVis) { - hint = vis->CalcDifference(*otherVis); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleDisplay* display = (const nsStyleDisplay*)GetStyleData(eStyleStruct_Display); - const nsStyleDisplay* otherDisplay = (const nsStyleDisplay*)aOther->GetStyleData(eStyleStruct_Display); - if (display != otherDisplay) { - hint = display->CalcDifference(*otherDisplay); - if (aHint < hint) - aHint = hint; - } - } - -#ifdef INCLUDE_XUL - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleXUL* xul = (const nsStyleXUL*)GetStyleData(eStyleStruct_XUL); - const nsStyleXUL* otherXUL = (const nsStyleXUL*)aOther->GetStyleData(eStyleStruct_XUL); - if (xul != otherXUL) { - hint = xul->CalcDifference(*otherXUL); - if (aHint < hint) - aHint = hint; - } - } -#endif - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleTable* table = (const nsStyleTable*)GetStyleData(eStyleStruct_Table); - const nsStyleTable* otherTable = (const nsStyleTable*)aOther->GetStyleData(eStyleStruct_Table); - if (table != otherTable) { - hint = table->CalcDifference(*otherTable); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleTableBorder* table = (const nsStyleTableBorder*)GetStyleData(eStyleStruct_TableBorder); - const nsStyleTableBorder* otherTable = (const nsStyleTableBorder*)aOther->GetStyleData(eStyleStruct_TableBorder); - if (table != otherTable) { - hint = table->CalcDifference(*otherTable); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleContent* content = (const nsStyleContent*)GetStyleData(eStyleStruct_Content); - const nsStyleContent* otherContent = (const nsStyleContent*)aOther->GetStyleData(eStyleStruct_Content); - if (content != otherContent) { - hint = content->CalcDifference(*otherContent); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleQuotes* content = (const nsStyleQuotes*)GetStyleData(eStyleStruct_Quotes); - const nsStyleQuotes* otherContent = (const nsStyleQuotes*)aOther->GetStyleData(eStyleStruct_Quotes); - if (content != otherContent) { - hint = content->CalcDifference(*otherContent); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleUserInterface* ui = (const nsStyleUserInterface*)GetStyleData(eStyleStruct_UserInterface); - const nsStyleUserInterface* otherUI = (const nsStyleUserInterface*)aOther->GetStyleData(eStyleStruct_UserInterface); - if (ui != otherUI) { - hint = ui->CalcDifference(*otherUI); - if (aHint < hint) - aHint = hint; - } - } - - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; - if (aHint < NS_STYLE_HINT_MAX) { - const nsStyleUIReset* ui = (const nsStyleUIReset*)GetStyleData(eStyleStruct_UIReset); - const nsStyleUIReset* otherUI = (const nsStyleUIReset*)aOther->GetStyleData(eStyleStruct_UIReset); - if (ui != otherUI) { - hint = ui->CalcDifference(*otherUI); - if (aHint < hint) - aHint = hint; - } - } - if (aStopAtFirstDifference && aHint > NS_STYLE_HINT_NONE) return NS_OK; } return NS_OK; }