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,