Don't bother reresolving style when empty stylesheets get added (eg from empty

<style> elements).  Also remove the methods for blowing away the ruletree
during a style reresolve, since ruletrees are now garbage-collected.  Bug
196557, r+sr=dbaron
This commit is contained in:
bzbarsky%mit.edu 2003-07-04 01:44:24 +00:00
parent e0c66a21b8
commit 0c5dc097d7
17 changed files with 92 additions and 386 deletions

View File

@ -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

View File

@ -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()
{

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -1720,7 +1720,7 @@ nsPresContext::ThemeChanged()
if (!mShell)
return NS_OK;
return mShell->ReconstructStyleData(PR_FALSE);
return mShell->ReconstructStyleData();
}
NS_IMETHODIMP

View File

@ -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<nsIDocument> doc;
content->GetDocument(getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIBindingManager> bm;
doc->GetBindingManager(getter_AddRefs(bm));
nsCOMPtr<nsIXBLBinding> 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<nsITreeBoxObject> 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<nsIMenuFrame> 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<nsIAtom> 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<nsIAtom> 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

View File

@ -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

View File

@ -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;

View File

@ -1720,7 +1720,7 @@ nsPresContext::ThemeChanged()
if (!mShell)
return NS_OK;
return mShell->ReconstructStyleData(PR_FALSE);
return mShell->ReconstructStyleData();
}
NS_IMETHODIMP

View File

@ -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<nsIDocument> doc;
content->GetDocument(getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIBindingManager> bm;
doc->GetBindingManager(getter_AddRefs(bm));
nsCOMPtr<nsIXBLBinding> 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<nsITreeBoxObject> 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<nsIMenuFrame> 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<nsIAtom> 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<nsIAtom> 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

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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()
{