From 2b59f901f7c61d9b94c67c436e1eb8929f88da5a Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Wed, 18 Jun 2003 21:54:51 +0000 Subject: [PATCH] Handle state and attribute changes on elements without frames more efficiently, and keep the undisplayed map up to date. b=209733 r+sr=bzbarsky --- layout/base/nsCSSFrameConstructor.cpp | 30 +++++++++++++++++-- layout/base/nsCSSFrameConstructor.h | 3 ++ layout/base/nsFrameManager.cpp | 27 +++++++++++++++++ layout/base/public/nsIFrameManager.h | 2 ++ layout/html/base/src/nsFrameManager.cpp | 27 +++++++++++++++++ .../html/style/src/nsCSSFrameConstructor.cpp | 30 +++++++++++++++++-- layout/html/style/src/nsCSSFrameConstructor.h | 3 ++ 7 files changed, 116 insertions(+), 6 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index c7dcf639adc3..be8e465be423 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -10377,10 +10377,10 @@ nsCSSFrameConstructor::ContentStatesChanged(nsIPresContext* aPresContext, // no frames, reconstruct for content if (!primaryFrame1 && aContent1) { - result = RecreateFramesForContent(aPresContext, aContent1); + result = MaybeRecreateFramesForContent(aPresContext, aContent1); } if (!primaryFrame2 && aContent2) { - result = RecreateFramesForContent(aPresContext, aContent2); + result = MaybeRecreateFramesForContent(aPresContext, aContent2); } } } @@ -10546,7 +10546,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, ProcessRestyledFrames(changeList, aPresContext); } else { // no frame now, possibly genetate one with new style data - result = RecreateFramesForContent(aPresContext, aContent); + result = MaybeRecreateFramesForContent(aPresContext, aContent); } } @@ -11784,6 +11784,30 @@ nsCSSFrameConstructor::CaptureStateFor(nsIPresContext* aPresContext, return rv; } +nsresult +nsCSSFrameConstructor::MaybeRecreateFramesForContent(nsIPresContext* aPresContext, + nsIContent* aContent) +{ + nsresult result = NS_OK; + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr frameManager; + shell->GetFrameManager(getter_AddRefs(frameManager)); + + nsStyleContext *oldContext = frameManager->GetUndisplayedContent(aContent); + if (oldContext) { + // The parent has a frame, so try resolving a new context. + nsRefPtr newContext = + aPresContext->ResolveStyleContextFor(aContent, + oldContext->GetParent()); + frameManager->ChangeUndisplayedContent(aContent, newContext); + if (newContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_NONE) { + result = RecreateFramesForContent(aPresContext, aContent); + } + } + return result; +} + nsresult nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, nsIContent* aContent) diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index eedc0488573e..d1a27ad54e7a 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -741,6 +741,9 @@ protected: // cache the "nglayout.debug.enable_xbl_forms" pref PRBool UseXBLForms(); + nsresult MaybeRecreateFramesForContent(nsIPresContext* aPresContext, + nsIContent* aContent); + nsresult RecreateFramesForContent(nsIPresContext* aPresContext, nsIContent* aContent); diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index 7ccd4981e2a6..ca7156ceaac6 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -304,6 +304,7 @@ public: // Undisplayed content functions virtual nsStyleContext* GetUndisplayedContent(nsIContent* aContent); virtual void SetUndisplayedContent(nsIContent* aContent, nsStyleContext* aStyleContext); + virtual void ChangeUndisplayedContent(nsIContent* aContent, nsStyleContext* aStyleContext); NS_IMETHOD ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent); NS_IMETHOD ClearAllUndisplayedContentIn(nsIContent* aParentContent); NS_IMETHOD ClearUndisplayedContentMap(); @@ -861,6 +862,32 @@ FrameManager::SetUndisplayedContent(nsIContent* aContent, } } +void +FrameManager::ChangeUndisplayedContent(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + if (!mPresShell) + return; + NS_ASSERTION(mUndisplayedMap, "no existing undisplayed content"); + +#ifdef DEBUG_UNDISPLAYED_MAP + static int i = 0; + printf("ChangeUndisplayedContent(%d): p=%p \n", i++, (void *)aContent); +#endif + + nsCOMPtr parent; + aContent->GetParent(getter_AddRefs(parent)); + for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(parent); + node; node = node->mNext) { + if (node->mContent == aContent) { + node->mStyle = aStyleContext; + return; + } + } + + NS_NOTREACHED("no existing undisplayed content"); +} + NS_IMETHODIMP FrameManager::ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent) { diff --git a/layout/base/public/nsIFrameManager.h b/layout/base/public/nsIFrameManager.h index 692edb805d74..413c33470207 100644 --- a/layout/base/public/nsIFrameManager.h +++ b/layout/base/public/nsIFrameManager.h @@ -110,6 +110,8 @@ public: virtual nsStyleContext* GetUndisplayedContent(nsIContent* aContent) = 0; virtual void SetUndisplayedContent(nsIContent* aContent, nsStyleContext* aStyleContext) = 0; + virtual void ChangeUndisplayedContent(nsIContent* aContent, + nsStyleContext* aStyleContext) = 0; NS_IMETHOD ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent) = 0; NS_IMETHOD ClearAllUndisplayedContentIn(nsIContent* aParentContent) = 0; NS_IMETHOD ClearUndisplayedContentMap() = 0; diff --git a/layout/html/base/src/nsFrameManager.cpp b/layout/html/base/src/nsFrameManager.cpp index 7ccd4981e2a6..ca7156ceaac6 100644 --- a/layout/html/base/src/nsFrameManager.cpp +++ b/layout/html/base/src/nsFrameManager.cpp @@ -304,6 +304,7 @@ public: // Undisplayed content functions virtual nsStyleContext* GetUndisplayedContent(nsIContent* aContent); virtual void SetUndisplayedContent(nsIContent* aContent, nsStyleContext* aStyleContext); + virtual void ChangeUndisplayedContent(nsIContent* aContent, nsStyleContext* aStyleContext); NS_IMETHOD ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent); NS_IMETHOD ClearAllUndisplayedContentIn(nsIContent* aParentContent); NS_IMETHOD ClearUndisplayedContentMap(); @@ -861,6 +862,32 @@ FrameManager::SetUndisplayedContent(nsIContent* aContent, } } +void +FrameManager::ChangeUndisplayedContent(nsIContent* aContent, + nsStyleContext* aStyleContext) +{ + if (!mPresShell) + return; + NS_ASSERTION(mUndisplayedMap, "no existing undisplayed content"); + +#ifdef DEBUG_UNDISPLAYED_MAP + static int i = 0; + printf("ChangeUndisplayedContent(%d): p=%p \n", i++, (void *)aContent); +#endif + + nsCOMPtr parent; + aContent->GetParent(getter_AddRefs(parent)); + for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(parent); + node; node = node->mNext) { + if (node->mContent == aContent) { + node->mStyle = aStyleContext; + return; + } + } + + NS_NOTREACHED("no existing undisplayed content"); +} + NS_IMETHODIMP FrameManager::ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent) { diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index c7dcf639adc3..be8e465be423 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -10377,10 +10377,10 @@ nsCSSFrameConstructor::ContentStatesChanged(nsIPresContext* aPresContext, // no frames, reconstruct for content if (!primaryFrame1 && aContent1) { - result = RecreateFramesForContent(aPresContext, aContent1); + result = MaybeRecreateFramesForContent(aPresContext, aContent1); } if (!primaryFrame2 && aContent2) { - result = RecreateFramesForContent(aPresContext, aContent2); + result = MaybeRecreateFramesForContent(aPresContext, aContent2); } } } @@ -10546,7 +10546,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, ProcessRestyledFrames(changeList, aPresContext); } else { // no frame now, possibly genetate one with new style data - result = RecreateFramesForContent(aPresContext, aContent); + result = MaybeRecreateFramesForContent(aPresContext, aContent); } } @@ -11784,6 +11784,30 @@ nsCSSFrameConstructor::CaptureStateFor(nsIPresContext* aPresContext, return rv; } +nsresult +nsCSSFrameConstructor::MaybeRecreateFramesForContent(nsIPresContext* aPresContext, + nsIContent* aContent) +{ + nsresult result = NS_OK; + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr frameManager; + shell->GetFrameManager(getter_AddRefs(frameManager)); + + nsStyleContext *oldContext = frameManager->GetUndisplayedContent(aContent); + if (oldContext) { + // The parent has a frame, so try resolving a new context. + nsRefPtr newContext = + aPresContext->ResolveStyleContextFor(aContent, + oldContext->GetParent()); + frameManager->ChangeUndisplayedContent(aContent, newContext); + if (newContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_NONE) { + result = RecreateFramesForContent(aPresContext, aContent); + } + } + return result; +} + nsresult nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, nsIContent* aContent) diff --git a/layout/html/style/src/nsCSSFrameConstructor.h b/layout/html/style/src/nsCSSFrameConstructor.h index eedc0488573e..d1a27ad54e7a 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.h +++ b/layout/html/style/src/nsCSSFrameConstructor.h @@ -741,6 +741,9 @@ protected: // cache the "nglayout.debug.enable_xbl_forms" pref PRBool UseXBLForms(); + nsresult MaybeRecreateFramesForContent(nsIPresContext* aPresContext, + nsIContent* aContent); + nsresult RecreateFramesForContent(nsIPresContext* aPresContext, nsIContent* aContent);