diff --git a/content/base/public/nsIStyleSheet.h b/content/base/public/nsIStyleSheet.h index 193b565428e..bed48a53adb 100644 --- a/content/base/public/nsIStyleSheet.h +++ b/content/base/public/nsIStyleSheet.h @@ -66,6 +66,7 @@ public: NS_IMETHOD GetMediumCount(PRInt32& aCount) const = 0; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const = 0; NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0; + NS_IMETHOD_(PRBool) HasRules() const = 0; /** * Whether the sheet is applicable. A sheet that is not applicable diff --git a/content/base/src/nsStyleSet.cpp b/content/base/src/nsStyleSet.cpp index 69febce4fac..421f21c9920 100644 --- a/content/base/src/nsStyleSet.cpp +++ b/content/base/src/nsStyleSet.cpp @@ -174,20 +174,6 @@ public: NS_IMETHOD Shutdown(nsIPresContext* aPresContext); NS_IMETHOD NotifyStyleContextDestroyed(nsIPresContext* aPresContext, nsStyleContext* aStyleContext); - - // The following two methods can be used to tear down and reconstruct a rule tree. The idea - // is to first call BeginRuleTreeReconstruct, which will set aside the old rule - // tree. The entire frame tree should then have ReResolveStyleContext - // called on it. With the old rule tree hidden from view, the newly resolved style contexts will - // resolve to rule nodes in a fresh rule tree, and the re-resolve system will properly compute - // the visual impact of the changes. - // - // After re-resolution, call EndRuleTreeReconstruct() to finally discard the old rule tree. - // This trick can be used in lieu of a full frame reconstruction when drastic style changes - // happen (e.g., stylesheets being added/removed in the DOM, theme switching in the Mozilla app, - // etc. - virtual nsresult BeginRuleTreeReconstruct(); - virtual nsresult EndRuleTreeReconstruct(); // For getting the cached default data in case we hit out-of-memory. // To be used only by nsRuleNode. @@ -364,7 +350,6 @@ protected: nsRuleNode* mRuleTree; // This is the root of our rule tree. It is a lexicographic tree of // matched rules that style contexts use to look up properties. - nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction. nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used // to navigate through our tree. @@ -387,7 +372,6 @@ StyleSetImpl::StyleSetImpl() : mFrameConstructor(nsnull), mQuirkStyleSheet(nsnull), mRuleTree(nsnull), - mOldRuleTree(nsnull), mRuleWalker(nsnull), mInShutdown(PR_FALSE), mDestroyedCount(0) @@ -1462,26 +1446,6 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult) return NS_OK; } -nsresult -StyleSetImpl::BeginRuleTreeReconstruct() -{ - delete mRuleWalker; - mRuleWalker = nsnull; - mOldRuleTree = mRuleTree; - mRuleTree = nsnull; - return NS_OK; -} - -nsresult -StyleSetImpl::EndRuleTreeReconstruct() -{ - if (mOldRuleTree) { - mOldRuleTree->Destroy(); - mOldRuleTree = nsnull; - } - return NS_OK; -} - nsCachedStyleData* StyleSetImpl::GetDefaultStyleData() { diff --git a/content/html/style/src/nsCSSStyleSheet.cpp b/content/html/style/src/nsCSSStyleSheet.cpp index 88e5865ca53..832ce1bbabc 100644 --- a/content/html/style/src/nsCSSStyleSheet.cpp +++ b/content/html/style/src/nsCSSStyleSheet.cpp @@ -816,6 +816,7 @@ public: NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); + NS_IMETHOD_(PRBool) HasRules() const; NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex); NS_IMETHOD InsertRuleIntoGroup(const nsAString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval); NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew); @@ -1916,6 +1917,13 @@ CSSStyleSheetImpl::ClearMedia(void) return NS_OK; } +NS_IMETHODIMP_(PRBool) +CSSStyleSheetImpl::HasRules() const +{ + PRInt32 count; + StyleRuleCount(count); + return count != 0; +} NS_IMETHODIMP CSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const diff --git a/content/html/style/src/nsHTMLCSSStyleSheet.cpp b/content/html/style/src/nsHTMLCSSStyleSheet.cpp index 44f4559a596..fdd8175e74a 100644 --- a/content/html/style/src/nsHTMLCSSStyleSheet.cpp +++ b/content/html/style/src/nsHTMLCSSStyleSheet.cpp @@ -354,6 +354,7 @@ public: NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) HasRules() const; NS_IMETHOD GetApplicable(PRBool& aApplicable) const; @@ -590,6 +591,13 @@ HTMLCSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const return PR_TRUE; // works for all media } +NS_IMETHODIMP_(PRBool) +HTMLCSSStyleSheetImpl::HasRules() const +{ + return PR_TRUE; // We always have rules, since mFirstLineRule and + // mFirstLetterRule are created on request. +} + NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const { diff --git a/content/html/style/src/nsHTMLStyleSheet.cpp b/content/html/style/src/nsHTMLStyleSheet.cpp index 004e1b06258..96d93ff5ce9 100644 --- a/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/content/html/style/src/nsHTMLStyleSheet.cpp @@ -518,6 +518,7 @@ public: NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) HasRules() const; NS_IMETHOD GetApplicable(PRBool& aApplicable) const; @@ -947,6 +948,11 @@ HTMLStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const return PR_TRUE; // works for all media } +NS_IMETHODIMP_(PRBool) +HTMLStyleSheetImpl::HasRules() const +{ + return PR_TRUE; // We have rules at all reasonable times +} NS_IMETHODIMP HTMLStyleSheetImpl::GetApplicable(PRBool& aApplicable) const diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 2d70114a1ee..d157d621582 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -169,7 +169,7 @@ public: * all style data for a given pres shell without necessarily reconstructing * all of the frames. */ - NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree) = 0; + NS_IMETHOD ReconstructStyleData() = 0; /** Setup all style rules required to implement preferences * - used for background/text/link colors and link underlining diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index fe5a5ed8df3..4b17f010eb4 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1720,7 +1720,7 @@ nsPresContext::ThemeChanged() if (!mShell) return NS_OK; - return mShell->ReconstructStyleData(PR_FALSE); + return mShell->ReconstructStyleData(); } NS_IMETHODIMP diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 565de0d51d0..5171d6279ff 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1047,7 +1047,7 @@ public: NS_IMETHOD GetActiveAlternateStyleSheet(nsString& aSheetTitle); NS_IMETHOD SelectAlternateStyleSheet(const nsString& aSheetTitle); NS_IMETHOD ListAlternateStyleSheets(nsStringArray& aTitleList); - NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree); + NS_IMETHOD ReconstructStyleData(); NS_IMETHOD SetPreferenceStyleRules(PRBool aForceReflow); NS_IMETHOD EnablePrefStyleRules(PRBool aEnable, PRUint8 aPrefType=0xFF); NS_IMETHOD ArePrefStyleRulesEnabled(PRBool& aEnabled); @@ -2017,11 +2017,8 @@ PresShell::SelectAlternateStyleSheet(const nsString& aSheetTitle) } } } - // We don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. They can simply lurk in the tree - // until the stylesheet is enabled once more. - return ReconstructStyleData(PR_FALSE); + + return ReconstructStyleData(); } return NS_OK; } @@ -5418,106 +5415,8 @@ PresShell::ReconstructFrames(void) return rv; } -/* - * It's better to add stuff to the |DidSetStyleContext| method of the - * relevant frames than adding it here. These methods should (ideally, - * anyway) go away. - */ - -// Return value says whether to walk children. -typedef PRBool (* PR_CALLBACK frameWalkerFn)(nsIFrame *aFrame, void *aClosure); - -PR_STATIC_CALLBACK(PRBool) -BuildFramechangeList(nsIFrame *aFrame, void *aClosure) -{ - nsStyleChangeList *changeList = NS_STATIC_CAST(nsStyleChangeList*, aClosure); - - // Ok, get our binding information. - if (!aFrame->GetStyleDisplay()->mBinding.IsEmpty()) { - // We had a binding. - nsIContent* content = aFrame->GetContent(); - nsCOMPtr doc; - content->GetDocument(getter_AddRefs(doc)); - if (doc) { - nsCOMPtr bm; - doc->GetBindingManager(getter_AddRefs(bm)); - nsCOMPtr binding; - bm->GetBinding(content, getter_AddRefs(binding)); - PRBool marked = PR_FALSE; - binding->MarkedForDeath(&marked); - if (marked) { - // Add in a change to process, thus ensuring this binding gets rebuilt. - changeList->AppendChange(aFrame, content, NS_STYLE_HINT_FRAMECHANGE); - return PR_FALSE; - } - } - } - - return PR_TRUE; -} - -#ifdef MOZ_XUL -PR_STATIC_CALLBACK(PRBool) -ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure) -{ - // Trees have a special style cache that needs to be flushed when - // the theme changes. - nsCOMPtr treeBox(do_QueryInterface(aFrame)); - if (treeBox) - treeBox->ClearStyleAndImageCaches(); - - // We deliberately don't re-resolve style on a menu's popup - // sub-content, since doing so slows menus to a crawl. That means we - // have to special-case them on a skin switch, and ensure that the - // popup frames just get destroyed completely. - nsCOMPtr menuFrame(do_QueryInterface(aFrame)); - if (menuFrame) { - menuFrame->UngenerateMenu(); - menuFrame->OpenMenu(PR_FALSE); - } - return PR_TRUE; -} -#endif - -static void -WalkFramesThroughPlaceholders(nsIPresContext *aPresContext, nsIFrame *aFrame, - frameWalkerFn aFunc, void *aClosure) -{ - PRBool walkChildren = (*aFunc)(aFrame, aClosure); - if (!walkChildren) - return; - - PRInt32 listIndex = 0; - nsCOMPtr childList; - - do { - nsIFrame *child = nsnull; - aFrame->FirstChild(aPresContext, childList, &child); - while (child) { - if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { - // only do frames that are in flow - nsCOMPtr frameType; - child->GetFrameType(getter_AddRefs(frameType)); - if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder - // get out of flow frame and recur there - nsIFrame* outOfFlowFrame = - NS_STATIC_CAST(nsPlaceholderFrame*, child)->GetOutOfFlowFrame(); - NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); - WalkFramesThroughPlaceholders(aPresContext, outOfFlowFrame, - aFunc, aClosure); - } - else - WalkFramesThroughPlaceholders(aPresContext, child, aFunc, aClosure); - } - child = child->GetNextSibling(); - } - - aFrame->GetAdditionalChildListName(listIndex++, getter_AddRefs(childList)); - } while (childList); -} - NS_IMETHODIMP -PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) +PresShell::ReconstructStyleData() { nsIFrame* rootFrame; GetRootFrame(&rootFrame); @@ -5540,18 +5439,6 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) // Now handle some of our more problematic widgets (and also deal with // skin XBL changing). nsStyleChangeList changeList; - if (aRebuildRuleTree) { - // Handle those widgets that have special style contexts cached - // that will point to invalid rule nodes following a rule tree - // reconstruction. - WalkFramesThroughPlaceholders(mPresContext, rootFrame, - &BuildFramechangeList, &changeList); - cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext); - changeList.Clear(); - - // Now do a complete re-resolve of our style tree. - set->BeginRuleTreeReconstruct(); - } nsChangeHint frameChange = NS_STYLE_HINT_NONE; frameManager->ComputeStyleChangeFor(rootFrame, kNameSpaceID_Unknown, nsnull, @@ -5562,18 +5449,8 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) set->ReconstructDocElementHierarchy(mPresContext); else { cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext); -#ifdef MOZ_XUL - if (aRebuildRuleTree) { - GetRootFrame(&rootFrame); - WalkFramesThroughPlaceholders(mPresContext, rootFrame, - &ReResolveMenusAndTrees, nsnull); - } -#endif } - if (aRebuildRuleTree) - set->EndRuleTreeReconstruct(); - VERIFY_STYLE_TREE; return NS_OK; @@ -5587,14 +5464,12 @@ PresShell::StyleSheetAdded(nsIDocument *aDocument, NS_PRECONDITION(aStyleSheet, "Must have a style sheet!"); PRBool applicable; aStyleSheet->GetApplicable(applicable); - if (applicable) { - // If style information is being added, we don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. - return ReconstructStyleData(PR_FALSE); - } - return NS_OK; + if (!applicable || !aStyleSheet->HasRules()) { + return NS_OK; + } + + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5605,13 +5480,11 @@ PresShell::StyleSheetRemoved(nsIDocument *aDocument, NS_PRECONDITION(aStyleSheet, "Must have a style sheet!"); PRBool applicable; aStyleSheet->GetApplicable(applicable); - if (applicable) { - // XXXdwh We'd like to be able to use ReconstructStyleData in all the - // other style sheet calls, but it doesn't quite work because of HTML tables. - return ReconstructStyleData(PR_TRUE); + if (!applicable || !aStyleSheet->HasRules()) { + return NS_OK; } - - return NS_OK; + + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5626,11 +5499,11 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument, return rv; } - // We don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. They can simply lurk in the tree - // until the stylesheet is enabled once more. - return ReconstructStyleData(PR_FALSE); + if (!aStyleSheet->HasRules()) { + return NS_OK; + } + + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5639,7 +5512,7 @@ PresShell::StyleRuleChanged(nsIDocument *aDocument, nsIStyleRule* aOldStyleRule, nsIStyleRule* aNewStyleRule) { - return ReconstructStyleData(PR_FALSE); + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5647,7 +5520,7 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - return ReconstructStyleData(PR_FALSE); + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5655,7 +5528,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - return ReconstructStyleData(PR_FALSE); + return ReconstructStyleData(); } NS_IMETHODIMP diff --git a/layout/base/public/nsIPresShell.h b/layout/base/public/nsIPresShell.h index 2d70114a1ee..d157d621582 100644 --- a/layout/base/public/nsIPresShell.h +++ b/layout/base/public/nsIPresShell.h @@ -169,7 +169,7 @@ public: * all style data for a given pres shell without necessarily reconstructing * all of the frames. */ - NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree) = 0; + NS_IMETHOD ReconstructStyleData() = 0; /** Setup all style rules required to implement preferences * - used for background/text/link colors and link underlining diff --git a/layout/base/public/nsIStyleSet.h b/layout/base/public/nsIStyleSet.h index e237934b263..a98a4dc9252 100644 --- a/layout/base/public/nsIStyleSet.h +++ b/layout/base/public/nsIStyleSet.h @@ -111,20 +111,6 @@ public: virtual nsresult GetRuleTree(nsRuleNode** aResult) = 0; - // The following two methods can be used to tear down and reconstruct a rule tree. The idea - // is to first call BeginRuleTreeReconstruct, which will set aside the old rule - // tree. The entire frame tree should then have ReResolveStyleContext - // called on it. With the old rule tree hidden from view, the newly resolved style contexts will - // resolve to rule nodes in a fresh rule tree, and the re-resolve system will properly compute - // the visual impact of the changes. - // - // After re-resolution, call EndRuleTreeReconstruct() to finally discard the old rule tree. - // This trick can be used in lieu of a full frame reconstruction when drastic style changes - // happen (e.g., stylesheets being added/removed in the DOM, theme switching in the Mozilla app, - // etc. - virtual nsresult BeginRuleTreeReconstruct()=0; - virtual nsresult EndRuleTreeReconstruct()=0; - // For getting the cached default data in case we hit out-of-memory. // To be used only by nsRuleNode. virtual nsCachedStyleData* GetDefaultStyleData() = 0; diff --git a/layout/base/src/nsPresContext.cpp b/layout/base/src/nsPresContext.cpp index fe5a5ed8df3..4b17f010eb4 100644 --- a/layout/base/src/nsPresContext.cpp +++ b/layout/base/src/nsPresContext.cpp @@ -1720,7 +1720,7 @@ nsPresContext::ThemeChanged() if (!mShell) return NS_OK; - return mShell->ReconstructStyleData(PR_FALSE); + return mShell->ReconstructStyleData(); } NS_IMETHODIMP diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 565de0d51d0..5171d6279ff 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -1047,7 +1047,7 @@ public: NS_IMETHOD GetActiveAlternateStyleSheet(nsString& aSheetTitle); NS_IMETHOD SelectAlternateStyleSheet(const nsString& aSheetTitle); NS_IMETHOD ListAlternateStyleSheets(nsStringArray& aTitleList); - NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree); + NS_IMETHOD ReconstructStyleData(); NS_IMETHOD SetPreferenceStyleRules(PRBool aForceReflow); NS_IMETHOD EnablePrefStyleRules(PRBool aEnable, PRUint8 aPrefType=0xFF); NS_IMETHOD ArePrefStyleRulesEnabled(PRBool& aEnabled); @@ -2017,11 +2017,8 @@ PresShell::SelectAlternateStyleSheet(const nsString& aSheetTitle) } } } - // We don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. They can simply lurk in the tree - // until the stylesheet is enabled once more. - return ReconstructStyleData(PR_FALSE); + + return ReconstructStyleData(); } return NS_OK; } @@ -5418,106 +5415,8 @@ PresShell::ReconstructFrames(void) return rv; } -/* - * It's better to add stuff to the |DidSetStyleContext| method of the - * relevant frames than adding it here. These methods should (ideally, - * anyway) go away. - */ - -// Return value says whether to walk children. -typedef PRBool (* PR_CALLBACK frameWalkerFn)(nsIFrame *aFrame, void *aClosure); - -PR_STATIC_CALLBACK(PRBool) -BuildFramechangeList(nsIFrame *aFrame, void *aClosure) -{ - nsStyleChangeList *changeList = NS_STATIC_CAST(nsStyleChangeList*, aClosure); - - // Ok, get our binding information. - if (!aFrame->GetStyleDisplay()->mBinding.IsEmpty()) { - // We had a binding. - nsIContent* content = aFrame->GetContent(); - nsCOMPtr doc; - content->GetDocument(getter_AddRefs(doc)); - if (doc) { - nsCOMPtr bm; - doc->GetBindingManager(getter_AddRefs(bm)); - nsCOMPtr binding; - bm->GetBinding(content, getter_AddRefs(binding)); - PRBool marked = PR_FALSE; - binding->MarkedForDeath(&marked); - if (marked) { - // Add in a change to process, thus ensuring this binding gets rebuilt. - changeList->AppendChange(aFrame, content, NS_STYLE_HINT_FRAMECHANGE); - return PR_FALSE; - } - } - } - - return PR_TRUE; -} - -#ifdef MOZ_XUL -PR_STATIC_CALLBACK(PRBool) -ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure) -{ - // Trees have a special style cache that needs to be flushed when - // the theme changes. - nsCOMPtr treeBox(do_QueryInterface(aFrame)); - if (treeBox) - treeBox->ClearStyleAndImageCaches(); - - // We deliberately don't re-resolve style on a menu's popup - // sub-content, since doing so slows menus to a crawl. That means we - // have to special-case them on a skin switch, and ensure that the - // popup frames just get destroyed completely. - nsCOMPtr menuFrame(do_QueryInterface(aFrame)); - if (menuFrame) { - menuFrame->UngenerateMenu(); - menuFrame->OpenMenu(PR_FALSE); - } - return PR_TRUE; -} -#endif - -static void -WalkFramesThroughPlaceholders(nsIPresContext *aPresContext, nsIFrame *aFrame, - frameWalkerFn aFunc, void *aClosure) -{ - PRBool walkChildren = (*aFunc)(aFrame, aClosure); - if (!walkChildren) - return; - - PRInt32 listIndex = 0; - nsCOMPtr childList; - - do { - nsIFrame *child = nsnull; - aFrame->FirstChild(aPresContext, childList, &child); - while (child) { - if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { - // only do frames that are in flow - nsCOMPtr frameType; - child->GetFrameType(getter_AddRefs(frameType)); - if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder - // get out of flow frame and recur there - nsIFrame* outOfFlowFrame = - NS_STATIC_CAST(nsPlaceholderFrame*, child)->GetOutOfFlowFrame(); - NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); - WalkFramesThroughPlaceholders(aPresContext, outOfFlowFrame, - aFunc, aClosure); - } - else - WalkFramesThroughPlaceholders(aPresContext, child, aFunc, aClosure); - } - child = child->GetNextSibling(); - } - - aFrame->GetAdditionalChildListName(listIndex++, getter_AddRefs(childList)); - } while (childList); -} - NS_IMETHODIMP -PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) +PresShell::ReconstructStyleData() { nsIFrame* rootFrame; GetRootFrame(&rootFrame); @@ -5540,18 +5439,6 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) // Now handle some of our more problematic widgets (and also deal with // skin XBL changing). nsStyleChangeList changeList; - if (aRebuildRuleTree) { - // Handle those widgets that have special style contexts cached - // that will point to invalid rule nodes following a rule tree - // reconstruction. - WalkFramesThroughPlaceholders(mPresContext, rootFrame, - &BuildFramechangeList, &changeList); - cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext); - changeList.Clear(); - - // Now do a complete re-resolve of our style tree. - set->BeginRuleTreeReconstruct(); - } nsChangeHint frameChange = NS_STYLE_HINT_NONE; frameManager->ComputeStyleChangeFor(rootFrame, kNameSpaceID_Unknown, nsnull, @@ -5562,18 +5449,8 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) set->ReconstructDocElementHierarchy(mPresContext); else { cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext); -#ifdef MOZ_XUL - if (aRebuildRuleTree) { - GetRootFrame(&rootFrame); - WalkFramesThroughPlaceholders(mPresContext, rootFrame, - &ReResolveMenusAndTrees, nsnull); - } -#endif } - if (aRebuildRuleTree) - set->EndRuleTreeReconstruct(); - VERIFY_STYLE_TREE; return NS_OK; @@ -5587,14 +5464,12 @@ PresShell::StyleSheetAdded(nsIDocument *aDocument, NS_PRECONDITION(aStyleSheet, "Must have a style sheet!"); PRBool applicable; aStyleSheet->GetApplicable(applicable); - if (applicable) { - // If style information is being added, we don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. - return ReconstructStyleData(PR_FALSE); - } - return NS_OK; + if (!applicable || !aStyleSheet->HasRules()) { + return NS_OK; + } + + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5605,13 +5480,11 @@ PresShell::StyleSheetRemoved(nsIDocument *aDocument, NS_PRECONDITION(aStyleSheet, "Must have a style sheet!"); PRBool applicable; aStyleSheet->GetApplicable(applicable); - if (applicable) { - // XXXdwh We'd like to be able to use ReconstructStyleData in all the - // other style sheet calls, but it doesn't quite work because of HTML tables. - return ReconstructStyleData(PR_TRUE); + if (!applicable || !aStyleSheet->HasRules()) { + return NS_OK; } - - return NS_OK; + + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5626,11 +5499,11 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument, return rv; } - // We don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. They can simply lurk in the tree - // until the stylesheet is enabled once more. - return ReconstructStyleData(PR_FALSE); + if (!aStyleSheet->HasRules()) { + return NS_OK; + } + + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5639,7 +5512,7 @@ PresShell::StyleRuleChanged(nsIDocument *aDocument, nsIStyleRule* aOldStyleRule, nsIStyleRule* aNewStyleRule) { - return ReconstructStyleData(PR_FALSE); + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5647,7 +5520,7 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - return ReconstructStyleData(PR_FALSE); + return ReconstructStyleData(); } NS_IMETHODIMP @@ -5655,7 +5528,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - return ReconstructStyleData(PR_FALSE); + return ReconstructStyleData(); } NS_IMETHODIMP diff --git a/layout/style/nsCSSStyleSheet.cpp b/layout/style/nsCSSStyleSheet.cpp index 88e5865ca53..832ce1bbabc 100644 --- a/layout/style/nsCSSStyleSheet.cpp +++ b/layout/style/nsCSSStyleSheet.cpp @@ -816,6 +816,7 @@ public: NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; NS_IMETHOD AppendMedium(nsIAtom* aMedium); NS_IMETHOD ClearMedia(void); + NS_IMETHOD_(PRBool) HasRules() const; NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex); NS_IMETHOD InsertRuleIntoGroup(const nsAString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval); NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew); @@ -1916,6 +1917,13 @@ CSSStyleSheetImpl::ClearMedia(void) return NS_OK; } +NS_IMETHODIMP_(PRBool) +CSSStyleSheetImpl::HasRules() const +{ + PRInt32 count; + StyleRuleCount(count); + return count != 0; +} NS_IMETHODIMP CSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index 44f4559a596..fdd8175e74a 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -354,6 +354,7 @@ public: NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) HasRules() const; NS_IMETHOD GetApplicable(PRBool& aApplicable) const; @@ -590,6 +591,13 @@ HTMLCSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const return PR_TRUE; // works for all media } +NS_IMETHODIMP_(PRBool) +HTMLCSSStyleSheetImpl::HasRules() const +{ + return PR_TRUE; // We always have rules, since mFirstLineRule and + // mFirstLetterRule are created on request. +} + NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const { diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 004e1b06258..96d93ff5ce9 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -518,6 +518,7 @@ public: NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const; + NS_IMETHOD_(PRBool) HasRules() const; NS_IMETHOD GetApplicable(PRBool& aApplicable) const; @@ -947,6 +948,11 @@ HTMLStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const return PR_TRUE; // works for all media } +NS_IMETHODIMP_(PRBool) +HTMLStyleSheetImpl::HasRules() const +{ + return PR_TRUE; // We have rules at all reasonable times +} NS_IMETHODIMP HTMLStyleSheetImpl::GetApplicable(PRBool& aApplicable) const diff --git a/layout/style/nsIStyleSheet.h b/layout/style/nsIStyleSheet.h index 193b565428e..bed48a53adb 100644 --- a/layout/style/nsIStyleSheet.h +++ b/layout/style/nsIStyleSheet.h @@ -66,6 +66,7 @@ public: NS_IMETHOD GetMediumCount(PRInt32& aCount) const = 0; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const = 0; NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0; + NS_IMETHOD_(PRBool) HasRules() const = 0; /** * Whether the sheet is applicable. A sheet that is not applicable diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 69febce4fac..421f21c9920 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -174,20 +174,6 @@ public: NS_IMETHOD Shutdown(nsIPresContext* aPresContext); NS_IMETHOD NotifyStyleContextDestroyed(nsIPresContext* aPresContext, nsStyleContext* aStyleContext); - - // The following two methods can be used to tear down and reconstruct a rule tree. The idea - // is to first call BeginRuleTreeReconstruct, which will set aside the old rule - // tree. The entire frame tree should then have ReResolveStyleContext - // called on it. With the old rule tree hidden from view, the newly resolved style contexts will - // resolve to rule nodes in a fresh rule tree, and the re-resolve system will properly compute - // the visual impact of the changes. - // - // After re-resolution, call EndRuleTreeReconstruct() to finally discard the old rule tree. - // This trick can be used in lieu of a full frame reconstruction when drastic style changes - // happen (e.g., stylesheets being added/removed in the DOM, theme switching in the Mozilla app, - // etc. - virtual nsresult BeginRuleTreeReconstruct(); - virtual nsresult EndRuleTreeReconstruct(); // For getting the cached default data in case we hit out-of-memory. // To be used only by nsRuleNode. @@ -364,7 +350,6 @@ protected: nsRuleNode* mRuleTree; // This is the root of our rule tree. It is a lexicographic tree of // matched rules that style contexts use to look up properties. - nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction. nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used // to navigate through our tree. @@ -387,7 +372,6 @@ StyleSetImpl::StyleSetImpl() : mFrameConstructor(nsnull), mQuirkStyleSheet(nsnull), mRuleTree(nsnull), - mOldRuleTree(nsnull), mRuleWalker(nsnull), mInShutdown(PR_FALSE), mDestroyedCount(0) @@ -1462,26 +1446,6 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult) return NS_OK; } -nsresult -StyleSetImpl::BeginRuleTreeReconstruct() -{ - delete mRuleWalker; - mRuleWalker = nsnull; - mOldRuleTree = mRuleTree; - mRuleTree = nsnull; - return NS_OK; -} - -nsresult -StyleSetImpl::EndRuleTreeReconstruct() -{ - if (mOldRuleTree) { - mOldRuleTree->Destroy(); - mOldRuleTree = nsnull; - } - return NS_OK; -} - nsCachedStyleData* StyleSetImpl::GetDefaultStyleData() {