diff --git a/mozilla/content/base/src/nsDocumentViewer.cpp b/mozilla/content/base/src/nsDocumentViewer.cpp
index b4c73356f56..06cbb966a8d 100644
--- a/mozilla/content/base/src/nsDocumentViewer.cpp
+++ b/mozilla/content/base/src/nsDocumentViewer.cpp
@@ -4723,7 +4723,7 @@ NS_IMETHODIMP DocumentViewerImpl::SetTextZoom(float aTextZoom)
if (mDeviceContext) {
mDeviceContext->SetTextZoom(aTextZoom);
if (mPresContext) {
- mPresContext->RemapStyleAndReflow();
+ mPresContext->ClearStyleDataAndReflow();
}
}
diff --git a/mozilla/content/base/src/nsStyleContext.cpp b/mozilla/content/base/src/nsStyleContext.cpp
index 50613a4117a..7e62deb7992 100644
--- a/mozilla/content/base/src/nsStyleContext.cpp
+++ b/mozilla/content/base/src/nsStyleContext.cpp
@@ -75,8 +75,6 @@ public:
virtual PRBool Equals(const nsIStyleContext* aOther) const;
virtual PRBool HasTextDecorations() { return mBits & NS_STYLE_HAS_TEXT_DECORATIONS; };
- NS_IMETHOD RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse = PR_TRUE);
-
NS_IMETHOD GetBorderPaddingFor(nsStyleBorderPadding& aBorderPadding);
NS_IMETHOD GetStyle(nsStyleStructID aSID, const nsStyleStruct** aStruct);
@@ -89,6 +87,8 @@ public:
virtual const nsStyleStruct* GetStyleData(nsStyleStructID aSID);
virtual nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID);
+ virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule);
+
virtual void ForceUnique(void);
NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBool aStopAtFirstDifference = PR_FALSE);
@@ -104,6 +104,8 @@ protected:
void AppendChild(nsStyleContext* aChild);
void RemoveChild(nsStyleContext* aChild);
+ void ApplyStyleFixups(nsIPresContext* aPresContext);
+
nsStyleContext* mParent;
nsStyleContext* mChild;
nsStyleContext* mEmptyChild;
@@ -140,33 +142,7 @@ nsStyleContext::nsStyleContext(nsIStyleContext* aParent,
mParent->AppendChild(this);
}
- // See if we have any text decorations.
- // First see if our parent has text decorations. If our parent does, then we inherit the bit.
- if (mParent && mParent->HasTextDecorations())
- mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
- else {
- // We might have defined a decoration.
- const nsStyleTextReset* text = (const nsStyleTextReset*)GetStyleData(eStyleStruct_TextReset);
- if (text->mTextDecoration != NS_STYLE_TEXT_DECORATION_NONE &&
- text->mTextDecoration != NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL)
- mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
- }
-
- // Correct tables.
- const nsStyleDisplay* disp = (const nsStyleDisplay*)GetStyleData(eStyleStruct_Display);
- if (disp->mDisplay == NS_STYLE_DISPLAY_TABLE) {
- // -moz-center and -moz-right are used for HTML's alignment
- // This is covering the
case.
- // In this case, we don't want to inherit the text alignment into the table.
- const nsStyleText* text = (const nsStyleText*)GetStyleData(eStyleStruct_Text);
-
- if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
- text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
- {
- nsStyleText* uniqueText = (nsStyleText*)GetUniqueStyleData(aPresContext, eStyleStruct_Text);
- uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
- }
- }
+ ApplyStyleFixups(aPresContext);
}
nsStyleContext::~nsStyleContext()
@@ -545,30 +521,60 @@ nsStyleContext::SetStyle(nsStyleStructID aSID, const nsStyleStruct& aStruct)
return result;
}
-NS_IMETHODIMP
-nsStyleContext::RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse)
+void
+nsStyleContext::ApplyStyleFixups(nsIPresContext* aPresContext)
{
-#if 0 // Commenting out until we figure out why this crashes only on opt builds.
- // First we need to clear out all of our style data.
- if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData)
- mCachedStyleData.Destroy(mBits, aPresContext);
+ // See if we have any text decorations.
+ // First see if our parent has text decorations. If our parent does, then we inherit the bit.
+ if (mParent && mParent->HasTextDecorations())
+ mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
+ else {
+ // We might have defined a decoration.
+ const nsStyleTextReset* text = (const nsStyleTextReset*)GetStyleData(eStyleStruct_TextReset);
+ if (text->mTextDecoration != NS_STYLE_TEXT_DECORATION_NONE &&
+ text->mTextDecoration != NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL)
+ mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
+ }
- mBits &= ~NS_STYLE_INHERIT_MASK; // Clear out all data that indicates we should look for
- // style data in our parent.
+ // Correct tables.
+ const nsStyleDisplay* disp = (const nsStyleDisplay*)GetStyleData(eStyleStruct_Display);
+ if (disp->mDisplay == NS_STYLE_DISPLAY_TABLE) {
+ // -moz-center and -moz-right are used for HTML's alignment
+ // This is covering the case.
+ // In this case, we don't want to inherit the text alignment into the table.
+ const nsStyleText* text = (const nsStyleText*)GetStyleData(eStyleStruct_Text);
+
+ if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
+ text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
+ {
+ nsStyleText* uniqueText = (nsStyleText*)GetUniqueStyleData(aPresContext, eStyleStruct_Text);
+ uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
+ }
+ }
+}
- // Now we need to ensure that any cached data along the path from our
- // rule node back to the root is cleared out.
- mRuleNode->ClearPath();
+nsresult
+nsStyleContext::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule)
+{
+ PRBool matched = PR_TRUE;
+ if (aRule)
+ mRuleNode->PathContainsRule(aRule, &matched);
+
+ if (matched) {
+ // First we need to clear out all of our style data.
+ if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData)
+ mCachedStyleData.Destroy(mBits, aPresContext);
- // Now do the same for all of our children, but only if the recurse boolean
- // is set.
- if (!aRecurse)
- return NS_OK;
+ mBits = 0; // Clear all bits.
+ aRule = nsnull;
+ }
+
+ ApplyStyleFixups(aPresContext);
if (mChild) {
nsStyleContext* child = mChild;
do {
- child->RemapStyle(aPresContext);
+ child->ClearStyleData(aPresContext, aRule);
child = child->mNextSibling;
} while (mChild != child);
}
@@ -576,11 +582,11 @@ nsStyleContext::RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse)
if (mEmptyChild) {
nsStyleContext* child = mEmptyChild;
do {
- child->RemapStyle(aPresContext);
+ child->ClearStyleData(aPresContext, aRule);
child = child->mNextSibling;
} while (mEmptyChild != child);
}
-#endif
+
return NS_OK;
}
diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp
index 2ed87c83f2a..44921c48b5e 100644
--- a/mozilla/content/base/src/nsStyleSet.cpp
+++ b/mozilla/content/base/src/nsStyleSet.cpp
@@ -115,6 +115,7 @@ public:
NS_IMETHOD Shutdown();
virtual nsresult GetRuleTree(nsIRuleNode** aResult);
+ virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsIStyleContext* aContext);
NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
@@ -985,6 +986,53 @@ StyleSetImpl::GetRuleTree(nsIRuleNode** aResult)
return NS_OK;
}
+nsresult
+StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsIStyleContext* aContext)
+{
+ // XXXdwh. If we're willing to *really* optimize this
+ // invalidation, we could only invalidate the struct data
+ // that actually changed. For example, if someone changes
+ // style.left, we really only need to blow away cached
+ // data in the position struct.
+ if (aContext) {
+ nsCOMPtr ruleNode;
+ aContext->GetRuleNode(getter_AddRefs(ruleNode));
+ ruleNode->ClearCachedData(aRule);
+
+ // We don't need to mess with the style tree in this case, since the act of
+ // changing inline style attributes automatically causes re-resolution to a new style context
+ // (with new descendant style contexts as well).
+ }
+ else {
+ // XXXdwh This is not terribly fast, but fortunately this case is rare (and often a full tree
+ // invalidation anyway). Improving performance here would involve a footprint
+ // increase. Mappings from rule nodes to their associated style contexts as well as
+ // mappings from rules to their associated rule nodes would enable us to avoid the two
+ // tree walks that occur here.
+
+ // Crawl the entire rule tree and blow away all data for rule nodes (and their descendants)
+ // that have the given rule.
+ if (mRuleTree)
+ mRuleTree->ClearCachedDataInSubtree(aRule);
+
+ // We need to crawl the entire style context tree, and for each style context we need
+ // to see if the specified rule is matched. If so, that context and all its descendant
+ // contexts must have their data wiped.
+ nsCOMPtr shell;
+ aPresContext->GetShell(getter_AddRefs(shell));
+ nsIFrame* rootFrame;
+ shell->GetRootFrame(&rootFrame);
+ if (rootFrame) {
+ nsCOMPtr rootContext;
+ rootFrame->GetStyleContext(getter_AddRefs(rootContext));
+ if (rootContext)
+ rootContext->ClearStyleData(aPresContext, aRule);
+ }
+ }
+
+ return NS_OK;
+}
+
NS_IMETHODIMP
StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
diff --git a/mozilla/content/html/style/public/nsIRuleNode.h b/mozilla/content/html/style/public/nsIRuleNode.h
index 9cebc751989..475990b9107 100644
--- a/mozilla/content/html/style/public/nsIRuleNode.h
+++ b/mozilla/content/html/style/public/nsIRuleNode.h
@@ -299,7 +299,8 @@ public:
NS_IMETHOD GetPresContext(nsIPresContext** aResult)=0;
- NS_IMETHOD ClearPath()=0;
+ NS_IMETHOD PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched) = 0;
+
NS_IMETHOD ClearCachedData(nsIStyleRule* aRule)=0;
NS_IMETHOD ClearCachedDataInSubtree(nsIStyleRule* aRule)=0;
diff --git a/mozilla/content/html/style/src/nsRuleNode.cpp b/mozilla/content/html/style/src/nsRuleNode.cpp
index 78d15bb7647..9ff44e63953 100644
--- a/mozilla/content/html/style/src/nsRuleNode.cpp
+++ b/mozilla/content/html/style/src/nsRuleNode.cpp
@@ -412,24 +412,18 @@ nsRuleNode::GetRule(nsIStyleRule** aResult)
return NS_OK;
}
-PRBool PR_CALLBACK ClearCachedDataHelper(nsHashKey* aKey, void* aData, void* aClosure)
-{
- nsRuleNode* ruleNode = (nsRuleNode*)aData;
- ruleNode->ClearPath();
- return PR_TRUE;
-}
-
NS_IMETHODIMP
-nsRuleNode::ClearPath()
+nsRuleNode::PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched)
{
- // Any children must not be allowed to obtain cached data from parents. We must
- // clear any bits in descendants that indicate inheritance.
- mInheritBits &= ~NS_STYLE_INHERIT_MASK;
- if (mStyleData.mResetData || mStyleData.mInheritedData)
- mStyleData.Destroy(0, mPresContext);
-
- if (mChildren)
- mChildren->Enumerate(ClearCachedDataHelper);
+ *aMatched = PR_FALSE;
+ nsRuleNode* ruleDest = this;
+ while (ruleDest) {
+ if (ruleDest->mRule == aRule) {
+ *aMatched = PR_TRUE;
+ break;
+ }
+ ruleDest = ruleDest->mParent;
+ }
return NS_OK;
}
@@ -446,7 +440,10 @@ nsRuleNode::ClearCachedData(nsIStyleRule* aRule)
if (ruleDest) {
// The rule was contained along our branch. We need to blow away
- // all cached data along this path.
+ // all cached data along this path. Note that, because of the definition
+ // of inline style, all nodes along this path must have exactly one child. This
+ // is not a bushy subtree, and so we know that by clearing this path, we've
+ // invalidated everything that we need to.
nsRuleNode* curr = this;
while (curr) {
curr->mNoneBits &= ~NS_STYLE_INHERIT_MASK;
@@ -475,12 +472,13 @@ PRBool PR_CALLBACK ClearCachedDataInSubtreeHelper(nsHashKey* aKey, void* aData,
NS_IMETHODIMP
nsRuleNode::ClearCachedDataInSubtree(nsIStyleRule* aRule)
{
- if (mRule == aRule) {
+ if (aRule == nsnull || mRule == aRule) {
// We have a match. Blow away all data stored at this node.
if (mStyleData.mResetData || mStyleData.mInheritedData)
mStyleData.Destroy(0, mPresContext);
mNoneBits &= ~NS_STYLE_INHERIT_MASK;
- mInheritBits &= ~NS_STYLE_INHERIT_MASK; // XXXdwh need to clear all data in descendants!
+ mInheritBits &= ~NS_STYLE_INHERIT_MASK;
+ aRule = nsnull;
}
if (mChildren)
diff --git a/mozilla/content/html/style/src/nsRuleNode.h b/mozilla/content/html/style/src/nsRuleNode.h
index 815765f83e6..46f85b8c75a 100644
--- a/mozilla/content/html/style/src/nsRuleNode.h
+++ b/mozilla/content/html/style/src/nsRuleNode.h
@@ -240,10 +240,10 @@ public:
NS_IMETHOD GetParent(nsIRuleNode** aResult);
NS_IMETHOD IsRoot(PRBool* aResult);
NS_IMETHOD GetRule(nsIStyleRule** aResult);
- NS_IMETHOD ClearPath();
NS_IMETHOD ClearCachedData(nsIStyleRule* aRule);
NS_IMETHOD ClearCachedDataInSubtree(nsIStyleRule* aRule);
NS_IMETHOD GetPresContext(nsIPresContext** aResult);
+ NS_IMETHOD PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched);
const nsStyleStruct* GetStyleData(nsStyleStructID aSID,
nsIStyleContext* aContext);
};
diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp
index a6425c2dc90..40deca6f626 100644
--- a/mozilla/layout/base/nsCSSFrameConstructor.cpp
+++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp
@@ -10020,25 +10020,9 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
}
else if (restyle) {
if (inlineStyle) {
- if (styleContext) {
- nsCOMPtr ruleNode;
- styleContext->GetRuleNode(getter_AddRefs(ruleNode));
- ruleNode->ClearCachedData(rule); // XXXdwh. If we're willing to *really* special case
- // inline style, we could only invalidate the struct data
- // that actually changed. For example, if someone changes
- // style.left, we really only need to blow away cached
- // data in the position struct.
- }
- else {
- // Ok, our only option left is to just crawl the entire rule
- // tree and blow away the data that way.
- nsCOMPtr set;
- shell->GetStyleSet(getter_AddRefs(set));
- nsCOMPtr rootNode;
- set->GetRuleTree(getter_AddRefs(rootNode));
- if (rootNode)
- rootNode->ClearCachedDataInSubtree(rule);
- }
+ nsCOMPtr set;
+ shell->GetStyleSet(getter_AddRefs(set));
+ set->ClearStyleData(aPresContext, rule, styleContext);
}
// If there is no frame then there is no point in re-styling it,
@@ -10164,10 +10148,9 @@ nsCSSFrameConstructor::StyleRuleChanged(nsIPresContext* aPresContext,
}
if (restyle) {
- nsIStyleContext* sc;
- frame->GetStyleContext(&sc);
- sc->RemapStyle(aPresContext);
- NS_RELEASE(sc);
+ nsCOMPtr set;
+ shell->GetStyleSet(getter_AddRefs(set));
+ set->ClearStyleData(aPresContext, aStyleRule, nsnull);
}
if (reframe) {
diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp
index b4c73356f56..06cbb966a8d 100644
--- a/mozilla/layout/base/nsDocumentViewer.cpp
+++ b/mozilla/layout/base/nsDocumentViewer.cpp
@@ -4723,7 +4723,7 @@ NS_IMETHODIMP DocumentViewerImpl::SetTextZoom(float aTextZoom)
if (mDeviceContext) {
mDeviceContext->SetTextZoom(aTextZoom);
if (mPresContext) {
- mPresContext->RemapStyleAndReflow();
+ mPresContext->ClearStyleDataAndReflow();
}
}
diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp
index bf82b036e9e..c82f7702de4 100644
--- a/mozilla/layout/base/nsFrameManager.cpp
+++ b/mozilla/layout/base/nsFrameManager.cpp
@@ -1700,7 +1700,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1735,7 +1736,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1769,7 +1771,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
NS_IF_RELEASE(pseudoTag);
if (undisplayedContext) {
if (undisplayedContext == undisplayed->mStyle) {
- undisplayedContext->RemapStyle(aPresContext);
+ // XXXdwh figure this out.
+ // undisplayedContext->RemapStyle(aPresContext);
}
const nsStyleDisplay* display =
(const nsStyleDisplay*)undisplayedContext->GetStyleData(eStyleStruct_Display);
@@ -1912,7 +1915,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1947,7 +1951,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1981,7 +1986,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
NS_IF_RELEASE(pseudoTag);
if (undisplayedContext) {
if (undisplayedContext == undisplayed->mStyle) {
- undisplayedContext->RemapStyle(aPresContext);
+ // XXXdwh figure this out.
+ // undisplayedContext->RemapStyle(aPresContext);
}
const nsStyleDisplay* display =
(const nsStyleDisplay*)undisplayedContext->GetStyleData(eStyleStruct_Display);
diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp
index edd6a37c41b..afa2b2faf3e 100644
--- a/mozilla/layout/base/nsPresContext.cpp
+++ b/mozilla/layout/base/nsPresContext.cpp
@@ -25,6 +25,7 @@
#include "nsIPresShell.h"
#include "nsIPref.h"
#include "nsILinkHandler.h"
+#include "nsIDocShellTreeItem.h"
#include "nsIStyleSet.h"
#include "nsFrameImageLoader.h"
#include "nsIFrameManager.h"
@@ -399,21 +400,20 @@ nsPresContext::GetCachedBoolPref(PRUint32 prefType, PRBool &aValue)
}
NS_IMETHODIMP
-nsPresContext::RemapStyleAndReflow()
+nsPresContext::ClearStyleDataAndReflow()
{
if (mShell) {
+ // Clear out all our style data.
+ nsCOMPtr set;
+ mShell->GetStyleSet(getter_AddRefs(set));
+ set->ClearStyleData(this, nsnull, nsnull);
+
// Have the root frame's style context remap its style based on the
// user preferences
nsIFrame* rootFrame;
mShell->GetRootFrame(&rootFrame);
if (rootFrame) {
- nsIStyleContext* rootStyleContext;
-
- rootFrame->GetStyleContext(&rootStyleContext);
- rootStyleContext->RemapStyle(this);
- NS_RELEASE(rootStyleContext);
-
// boxes know how to coelesce style changes. So if our root frame is a box
// then tell it to handle it. If its a block we are stuck with a full top to bottom
// reflow. -EDV
@@ -440,6 +440,14 @@ nsPresContext::RemapStyleAndReflow()
void
nsPresContext::PreferenceChanged(const char* aPrefName)
{
+ nsCOMPtr docShell(do_QueryInterface(mContainer));
+ if (docShell) {
+ PRInt32 docShellType;
+ docShell->GetItemType(&docShellType);
+ if (nsIDocShellTreeItem::typeChrome == docShellType)
+ return;
+ }
+
// XXX for WM_FONTCHANGE messages, only flush the font cache (bug=89493)
// because nsObjectFrame can't handle a reframe at this time
if (strcmp(aPrefName,"font.internaluseonly.changed") == 0) {
@@ -459,7 +467,7 @@ nsPresContext::PreferenceChanged(const char* aPrefName)
if (mDeviceContext) {
mDeviceContext->FlushFontCache();
- RemapStyleAndReflow();
+ ClearStyleDataAndReflow();
}
}
@@ -1551,7 +1559,7 @@ NS_IMETHODIMP nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow)
SetVisualMode(IsVisualCharset(mCharset) );
}
if (mShell && aForceReflow) {
- RemapStyleAndReflow();
+ ClearStyleDataAndReflow();
}
return NS_OK;
}
diff --git a/mozilla/layout/base/nsPresContext.h b/mozilla/layout/base/nsPresContext.h
index 65a177a966d..42284a95d06 100644
--- a/mozilla/layout/base/nsPresContext.h
+++ b/mozilla/layout/base/nsPresContext.h
@@ -158,9 +158,9 @@ public:
NS_IMETHOD GetMedium(nsIAtom** aMediumResult) = 0;
/**
- * Remap style from the root frame downwards, and reflow.
+ * Clear style data from the root frame downwards, and reflow.
*/
- NS_IMETHOD RemapStyleAndReflow(void) = 0;
+ NS_IMETHOD ClearStyleDataAndReflow(void) = 0;
/**
* Resolve style for the given piece of content that will be a child
diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp
index cb062f20866..3499d301728 100644
--- a/mozilla/layout/base/nsPresShell.cpp
+++ b/mozilla/layout/base/nsPresShell.cpp
@@ -5281,11 +5281,7 @@ PresShell::BidiStyleChangeReflow()
mFrameManager->GetRootFrame(&rootFrame);
if (rootFrame) {
- nsIStyleContext* rootStyleContext;
- rootFrame->GetStyleContext(&rootStyleContext);
- rootStyleContext->RemapStyle(mPresContext.get() );
- NS_RELEASE(rootStyleContext);
-
+ mStyleSet->ClearStyleData(mPresContext, nsnull, nsnull);
ReconstructFrames();
}
return NS_OK;
diff --git a/mozilla/layout/base/public/nsIPresContext.h b/mozilla/layout/base/public/nsIPresContext.h
index 65a177a966d..42284a95d06 100644
--- a/mozilla/layout/base/public/nsIPresContext.h
+++ b/mozilla/layout/base/public/nsIPresContext.h
@@ -158,9 +158,9 @@ public:
NS_IMETHOD GetMedium(nsIAtom** aMediumResult) = 0;
/**
- * Remap style from the root frame downwards, and reflow.
+ * Clear style data from the root frame downwards, and reflow.
*/
- NS_IMETHOD RemapStyleAndReflow(void) = 0;
+ NS_IMETHOD ClearStyleDataAndReflow(void) = 0;
/**
* Resolve style for the given piece of content that will be a child
diff --git a/mozilla/layout/base/public/nsIStyleContext.h b/mozilla/layout/base/public/nsIStyleContext.h
index 476d3cfac73..2d1d8bd25f2 100644
--- a/mozilla/layout/base/public/nsIStyleContext.h
+++ b/mozilla/layout/base/public/nsIStyleContext.h
@@ -101,10 +101,12 @@ public:
// display. Don't add support for new structs or use this method without careful consideration! -dwh
virtual nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID) = 0;
+ // Used to clear away the style data for a given style context if it matches the specified |aRule|.
+ // If |aRule| is null, then the style data is always blown away.
+ virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) = 0;
+
// call this to prevent context from getting shared
virtual void ForceUnique(void) = 0;
-
- NS_IMETHOD RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse = PR_TRUE) = 0;
};
diff --git a/mozilla/layout/base/public/nsIStyleSet.h b/mozilla/layout/base/public/nsIStyleSet.h
index 6a01a01300b..9a76e1a0efd 100644
--- a/mozilla/layout/base/public/nsIStyleSet.h
+++ b/mozilla/layout/base/public/nsIStyleSet.h
@@ -82,6 +82,17 @@ public:
virtual nsresult GetRuleTree(nsIRuleNode** aResult) = 0;
+ // ClearCachedStyleData is used to invalidate portions of both the style context tree
+ // and rule tree without destroying the actual nodes in the two trees. |aRule| provides
+ // a hint as to which rule has changed, and all subtree data pruning will occur rooted
+ // only on style contexts and rule nodes that use that rule. If the rule is null, then
+ // it is assumed that both trees are to be entirely wiped.
+ //
+ // |aContext| provides an additional hint that a specific style context has changed, and
+ // that the entire rule tree need not be searched for occurrences of |aRule|. It is
+ // only specified in the inline style case, i.e., when the inline style attribute changes.
+ virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsIStyleContext* aContext) = 0;
+
// enable / disable the Quirk style sheet:
// returns NS_FAILURE if none is found, otherwise NS_OK
NS_IMETHOD EnableQuirkStyleSheet(PRBool aEnable) = 0;
diff --git a/mozilla/layout/base/public/nsPresContext.h b/mozilla/layout/base/public/nsPresContext.h
index 65a177a966d..42284a95d06 100644
--- a/mozilla/layout/base/public/nsPresContext.h
+++ b/mozilla/layout/base/public/nsPresContext.h
@@ -158,9 +158,9 @@ public:
NS_IMETHOD GetMedium(nsIAtom** aMediumResult) = 0;
/**
- * Remap style from the root frame downwards, and reflow.
+ * Clear style data from the root frame downwards, and reflow.
*/
- NS_IMETHOD RemapStyleAndReflow(void) = 0;
+ NS_IMETHOD ClearStyleDataAndReflow(void) = 0;
/**
* Resolve style for the given piece of content that will be a child
diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp
index edd6a37c41b..afa2b2faf3e 100644
--- a/mozilla/layout/base/src/nsPresContext.cpp
+++ b/mozilla/layout/base/src/nsPresContext.cpp
@@ -25,6 +25,7 @@
#include "nsIPresShell.h"
#include "nsIPref.h"
#include "nsILinkHandler.h"
+#include "nsIDocShellTreeItem.h"
#include "nsIStyleSet.h"
#include "nsFrameImageLoader.h"
#include "nsIFrameManager.h"
@@ -399,21 +400,20 @@ nsPresContext::GetCachedBoolPref(PRUint32 prefType, PRBool &aValue)
}
NS_IMETHODIMP
-nsPresContext::RemapStyleAndReflow()
+nsPresContext::ClearStyleDataAndReflow()
{
if (mShell) {
+ // Clear out all our style data.
+ nsCOMPtr set;
+ mShell->GetStyleSet(getter_AddRefs(set));
+ set->ClearStyleData(this, nsnull, nsnull);
+
// Have the root frame's style context remap its style based on the
// user preferences
nsIFrame* rootFrame;
mShell->GetRootFrame(&rootFrame);
if (rootFrame) {
- nsIStyleContext* rootStyleContext;
-
- rootFrame->GetStyleContext(&rootStyleContext);
- rootStyleContext->RemapStyle(this);
- NS_RELEASE(rootStyleContext);
-
// boxes know how to coelesce style changes. So if our root frame is a box
// then tell it to handle it. If its a block we are stuck with a full top to bottom
// reflow. -EDV
@@ -440,6 +440,14 @@ nsPresContext::RemapStyleAndReflow()
void
nsPresContext::PreferenceChanged(const char* aPrefName)
{
+ nsCOMPtr docShell(do_QueryInterface(mContainer));
+ if (docShell) {
+ PRInt32 docShellType;
+ docShell->GetItemType(&docShellType);
+ if (nsIDocShellTreeItem::typeChrome == docShellType)
+ return;
+ }
+
// XXX for WM_FONTCHANGE messages, only flush the font cache (bug=89493)
// because nsObjectFrame can't handle a reframe at this time
if (strcmp(aPrefName,"font.internaluseonly.changed") == 0) {
@@ -459,7 +467,7 @@ nsPresContext::PreferenceChanged(const char* aPrefName)
if (mDeviceContext) {
mDeviceContext->FlushFontCache();
- RemapStyleAndReflow();
+ ClearStyleDataAndReflow();
}
}
@@ -1551,7 +1559,7 @@ NS_IMETHODIMP nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow)
SetVisualMode(IsVisualCharset(mCharset) );
}
if (mShell && aForceReflow) {
- RemapStyleAndReflow();
+ ClearStyleDataAndReflow();
}
return NS_OK;
}
diff --git a/mozilla/layout/base/src/nsPresContext.h b/mozilla/layout/base/src/nsPresContext.h
index c6e38a15eca..afb295d46c7 100644
--- a/mozilla/layout/base/src/nsPresContext.h
+++ b/mozilla/layout/base/src/nsPresContext.h
@@ -63,7 +63,7 @@ public:
NS_IMETHOD GetLookAndFeel(nsILookAndFeel** aLookAndFeel);
NS_IMETHOD GetBaseURL(nsIURI** aURLResult);
NS_IMETHOD GetMedium(nsIAtom** aMediumResult) = 0;
- NS_IMETHOD RemapStyleAndReflow(void);
+ NS_IMETHOD ClearStyleDataAndReflow(void);
NS_IMETHOD ResolveStyleContextFor(nsIContent* aContent,
nsIStyleContext* aParentContext,
PRBool aForceUnique,
diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp
index bf82b036e9e..c82f7702de4 100644
--- a/mozilla/layout/html/base/src/nsFrameManager.cpp
+++ b/mozilla/layout/html/base/src/nsFrameManager.cpp
@@ -1700,7 +1700,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1735,7 +1736,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1769,7 +1771,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
NS_IF_RELEASE(pseudoTag);
if (undisplayedContext) {
if (undisplayedContext == undisplayed->mStyle) {
- undisplayedContext->RemapStyle(aPresContext);
+ // XXXdwh figure this out.
+ // undisplayedContext->RemapStyle(aPresContext);
}
const nsStyleDisplay* display =
(const nsStyleDisplay*)undisplayedContext->GetStyleData(eStyleStruct_Display);
@@ -1912,7 +1915,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1947,7 +1951,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
}
else {
- oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
+ // XXXdwh figure this out.
+ // oldExtraContext->RemapStyle(aPresContext, PR_FALSE);
if (aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
@@ -1981,7 +1986,8 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
NS_IF_RELEASE(pseudoTag);
if (undisplayedContext) {
if (undisplayedContext == undisplayed->mStyle) {
- undisplayedContext->RemapStyle(aPresContext);
+ // XXXdwh figure this out.
+ // undisplayedContext->RemapStyle(aPresContext);
}
const nsStyleDisplay* display =
(const nsStyleDisplay*)undisplayedContext->GetStyleData(eStyleStruct_Display);
diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp
index cb062f20866..3499d301728 100644
--- a/mozilla/layout/html/base/src/nsPresShell.cpp
+++ b/mozilla/layout/html/base/src/nsPresShell.cpp
@@ -5281,11 +5281,7 @@ PresShell::BidiStyleChangeReflow()
mFrameManager->GetRootFrame(&rootFrame);
if (rootFrame) {
- nsIStyleContext* rootStyleContext;
- rootFrame->GetStyleContext(&rootStyleContext);
- rootStyleContext->RemapStyle(mPresContext.get() );
- NS_RELEASE(rootStyleContext);
-
+ mStyleSet->ClearStyleData(mPresContext, nsnull, nsnull);
ReconstructFrames();
}
return NS_OK;
diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp
index a6425c2dc90..40deca6f626 100644
--- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp
+++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp
@@ -10020,25 +10020,9 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
}
else if (restyle) {
if (inlineStyle) {
- if (styleContext) {
- nsCOMPtr ruleNode;
- styleContext->GetRuleNode(getter_AddRefs(ruleNode));
- ruleNode->ClearCachedData(rule); // XXXdwh. If we're willing to *really* special case
- // inline style, we could only invalidate the struct data
- // that actually changed. For example, if someone changes
- // style.left, we really only need to blow away cached
- // data in the position struct.
- }
- else {
- // Ok, our only option left is to just crawl the entire rule
- // tree and blow away the data that way.
- nsCOMPtr set;
- shell->GetStyleSet(getter_AddRefs(set));
- nsCOMPtr rootNode;
- set->GetRuleTree(getter_AddRefs(rootNode));
- if (rootNode)
- rootNode->ClearCachedDataInSubtree(rule);
- }
+ nsCOMPtr set;
+ shell->GetStyleSet(getter_AddRefs(set));
+ set->ClearStyleData(aPresContext, rule, styleContext);
}
// If there is no frame then there is no point in re-styling it,
@@ -10164,10 +10148,9 @@ nsCSSFrameConstructor::StyleRuleChanged(nsIPresContext* aPresContext,
}
if (restyle) {
- nsIStyleContext* sc;
- frame->GetStyleContext(&sc);
- sc->RemapStyle(aPresContext);
- NS_RELEASE(sc);
+ nsCOMPtr set;
+ shell->GetStyleSet(getter_AddRefs(set));
+ set->ClearStyleData(aPresContext, aStyleRule, nsnull);
}
if (reframe) {
diff --git a/mozilla/layout/style/nsStyleContext.cpp b/mozilla/layout/style/nsStyleContext.cpp
index 50613a4117a..7e62deb7992 100644
--- a/mozilla/layout/style/nsStyleContext.cpp
+++ b/mozilla/layout/style/nsStyleContext.cpp
@@ -75,8 +75,6 @@ public:
virtual PRBool Equals(const nsIStyleContext* aOther) const;
virtual PRBool HasTextDecorations() { return mBits & NS_STYLE_HAS_TEXT_DECORATIONS; };
- NS_IMETHOD RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse = PR_TRUE);
-
NS_IMETHOD GetBorderPaddingFor(nsStyleBorderPadding& aBorderPadding);
NS_IMETHOD GetStyle(nsStyleStructID aSID, const nsStyleStruct** aStruct);
@@ -89,6 +87,8 @@ public:
virtual const nsStyleStruct* GetStyleData(nsStyleStructID aSID);
virtual nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID);
+ virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule);
+
virtual void ForceUnique(void);
NS_IMETHOD CalcStyleDifference(nsIStyleContext* aOther, PRInt32& aHint,PRBool aStopAtFirstDifference = PR_FALSE);
@@ -104,6 +104,8 @@ protected:
void AppendChild(nsStyleContext* aChild);
void RemoveChild(nsStyleContext* aChild);
+ void ApplyStyleFixups(nsIPresContext* aPresContext);
+
nsStyleContext* mParent;
nsStyleContext* mChild;
nsStyleContext* mEmptyChild;
@@ -140,33 +142,7 @@ nsStyleContext::nsStyleContext(nsIStyleContext* aParent,
mParent->AppendChild(this);
}
- // See if we have any text decorations.
- // First see if our parent has text decorations. If our parent does, then we inherit the bit.
- if (mParent && mParent->HasTextDecorations())
- mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
- else {
- // We might have defined a decoration.
- const nsStyleTextReset* text = (const nsStyleTextReset*)GetStyleData(eStyleStruct_TextReset);
- if (text->mTextDecoration != NS_STYLE_TEXT_DECORATION_NONE &&
- text->mTextDecoration != NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL)
- mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
- }
-
- // Correct tables.
- const nsStyleDisplay* disp = (const nsStyleDisplay*)GetStyleData(eStyleStruct_Display);
- if (disp->mDisplay == NS_STYLE_DISPLAY_TABLE) {
- // -moz-center and -moz-right are used for HTML's alignment
- // This is covering the case.
- // In this case, we don't want to inherit the text alignment into the table.
- const nsStyleText* text = (const nsStyleText*)GetStyleData(eStyleStruct_Text);
-
- if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
- text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
- {
- nsStyleText* uniqueText = (nsStyleText*)GetUniqueStyleData(aPresContext, eStyleStruct_Text);
- uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
- }
- }
+ ApplyStyleFixups(aPresContext);
}
nsStyleContext::~nsStyleContext()
@@ -545,30 +521,60 @@ nsStyleContext::SetStyle(nsStyleStructID aSID, const nsStyleStruct& aStruct)
return result;
}
-NS_IMETHODIMP
-nsStyleContext::RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse)
+void
+nsStyleContext::ApplyStyleFixups(nsIPresContext* aPresContext)
{
-#if 0 // Commenting out until we figure out why this crashes only on opt builds.
- // First we need to clear out all of our style data.
- if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData)
- mCachedStyleData.Destroy(mBits, aPresContext);
+ // See if we have any text decorations.
+ // First see if our parent has text decorations. If our parent does, then we inherit the bit.
+ if (mParent && mParent->HasTextDecorations())
+ mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
+ else {
+ // We might have defined a decoration.
+ const nsStyleTextReset* text = (const nsStyleTextReset*)GetStyleData(eStyleStruct_TextReset);
+ if (text->mTextDecoration != NS_STYLE_TEXT_DECORATION_NONE &&
+ text->mTextDecoration != NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL)
+ mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
+ }
- mBits &= ~NS_STYLE_INHERIT_MASK; // Clear out all data that indicates we should look for
- // style data in our parent.
+ // Correct tables.
+ const nsStyleDisplay* disp = (const nsStyleDisplay*)GetStyleData(eStyleStruct_Display);
+ if (disp->mDisplay == NS_STYLE_DISPLAY_TABLE) {
+ // -moz-center and -moz-right are used for HTML's alignment
+ // This is covering the case.
+ // In this case, we don't want to inherit the text alignment into the table.
+ const nsStyleText* text = (const nsStyleText*)GetStyleData(eStyleStruct_Text);
+
+ if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
+ text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
+ {
+ nsStyleText* uniqueText = (nsStyleText*)GetUniqueStyleData(aPresContext, eStyleStruct_Text);
+ uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
+ }
+ }
+}
- // Now we need to ensure that any cached data along the path from our
- // rule node back to the root is cleared out.
- mRuleNode->ClearPath();
+nsresult
+nsStyleContext::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule)
+{
+ PRBool matched = PR_TRUE;
+ if (aRule)
+ mRuleNode->PathContainsRule(aRule, &matched);
+
+ if (matched) {
+ // First we need to clear out all of our style data.
+ if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData)
+ mCachedStyleData.Destroy(mBits, aPresContext);
- // Now do the same for all of our children, but only if the recurse boolean
- // is set.
- if (!aRecurse)
- return NS_OK;
+ mBits = 0; // Clear all bits.
+ aRule = nsnull;
+ }
+
+ ApplyStyleFixups(aPresContext);
if (mChild) {
nsStyleContext* child = mChild;
do {
- child->RemapStyle(aPresContext);
+ child->ClearStyleData(aPresContext, aRule);
child = child->mNextSibling;
} while (mChild != child);
}
@@ -576,11 +582,11 @@ nsStyleContext::RemapStyle(nsIPresContext* aPresContext, PRBool aRecurse)
if (mEmptyChild) {
nsStyleContext* child = mEmptyChild;
do {
- child->RemapStyle(aPresContext);
+ child->ClearStyleData(aPresContext, aRule);
child = child->mNextSibling;
} while (mEmptyChild != child);
}
-#endif
+
return NS_OK;
}
diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp
index 2ed87c83f2a..44921c48b5e 100644
--- a/mozilla/layout/style/nsStyleSet.cpp
+++ b/mozilla/layout/style/nsStyleSet.cpp
@@ -115,6 +115,7 @@ public:
NS_IMETHOD Shutdown();
virtual nsresult GetRuleTree(nsIRuleNode** aResult);
+ virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsIStyleContext* aContext);
NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
@@ -985,6 +986,53 @@ StyleSetImpl::GetRuleTree(nsIRuleNode** aResult)
return NS_OK;
}
+nsresult
+StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsIStyleContext* aContext)
+{
+ // XXXdwh. If we're willing to *really* optimize this
+ // invalidation, we could only invalidate the struct data
+ // that actually changed. For example, if someone changes
+ // style.left, we really only need to blow away cached
+ // data in the position struct.
+ if (aContext) {
+ nsCOMPtr ruleNode;
+ aContext->GetRuleNode(getter_AddRefs(ruleNode));
+ ruleNode->ClearCachedData(aRule);
+
+ // We don't need to mess with the style tree in this case, since the act of
+ // changing inline style attributes automatically causes re-resolution to a new style context
+ // (with new descendant style contexts as well).
+ }
+ else {
+ // XXXdwh This is not terribly fast, but fortunately this case is rare (and often a full tree
+ // invalidation anyway). Improving performance here would involve a footprint
+ // increase. Mappings from rule nodes to their associated style contexts as well as
+ // mappings from rules to their associated rule nodes would enable us to avoid the two
+ // tree walks that occur here.
+
+ // Crawl the entire rule tree and blow away all data for rule nodes (and their descendants)
+ // that have the given rule.
+ if (mRuleTree)
+ mRuleTree->ClearCachedDataInSubtree(aRule);
+
+ // We need to crawl the entire style context tree, and for each style context we need
+ // to see if the specified rule is matched. If so, that context and all its descendant
+ // contexts must have their data wiped.
+ nsCOMPtr shell;
+ aPresContext->GetShell(getter_AddRefs(shell));
+ nsIFrame* rootFrame;
+ shell->GetRootFrame(&rootFrame);
+ if (rootFrame) {
+ nsCOMPtr rootContext;
+ rootFrame->GetStyleContext(getter_AddRefs(rootContext));
+ if (rootContext)
+ rootContext->ClearStyleData(aPresContext, aRule);
+ }
+ }
+
+ return NS_OK;
+}
+
NS_IMETHODIMP
StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,