From 75d3e8bd335d7b2ee78e72d04006ec45a394000c Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Thu, 23 Mar 2000 00:34:54 +0000 Subject: [PATCH] Adding back changes that were backed out because they broke the Win32 clobber build. The problem building TestAttributes.exe is fixed git-svn-id: svn://10.0.0.236/trunk@63795 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsIPresShell.h | 13 ++ mozilla/layout/base/nsPresShell.cpp | 122 +++++++++++++++++++ mozilla/layout/base/public/nsIPresShell.h | 13 ++ mozilla/layout/html/base/src/nsPresShell.cpp | 122 +++++++++++++++++++ 4 files changed, 270 insertions(+) diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 8c66dfdec97..a702406505c 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -29,6 +29,7 @@ #include "nsIReflowCommand.h" class nsIContent; +class nsIContentIterator; class nsIDocument; class nsIDocumentObserver; class nsIFrame; @@ -413,6 +414,18 @@ public: */ NS_IMETHOD IsReflowLocked(PRBool* aIsLocked) = 0; + /** + * Returns a content iterator to iterate the generated content nodes. + * You must specify whether you want to iterate the "before" generated + * content or the "after" generated content. If there is no generated + * content of the specified type for the promary frame associated with + * with the content object then NULL is returned + */ + enum GeneratedContentType {Before, After}; + NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent, + GeneratedContentType aType, + nsIContentIterator** aIterator) const = 0; + /** * See if reflow verification is enabled. To enable reflow verification add * "verifyreflow:1" to your NSPR_LOG_MODULES environment variable diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index f06f1e622fa..e4596669e8a 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -77,6 +77,7 @@ #include "nsTimer.h" #include "nsWeakPtr.h" #include "plarena.h" +#include "nsCSSAtoms.h" #ifdef MOZ_PERF_METRICS #include "nsITimeRecorder.h" #endif @@ -373,6 +374,10 @@ public: NS_IMETHOD GetReflowEventStatus(PRBool* aPending); NS_IMETHOD SetReflowEventStatus(PRBool aPending); + NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent, + GeneratedContentType aType, + nsIContentIterator** aIterator) const; + /** * Reflow batching */ @@ -2518,6 +2523,123 @@ PresShell::SetReflowEventStatus(PRBool aPending) mPendingReflowEvent = aPending; return NS_OK; } + +static PRBool +IsGeneratedContentFrame(nsIFrame* aFrame) +{ + nsFrameState frameState; + + aFrame->GetFrameState(&frameState); + return (frameState & NS_FRAME_GENERATED_CONTENT) != 0; +} + +static PRBool +IsPseudoFrame(nsIFrame* aFrame, nsIContent* aParentContent) +{ + nsCOMPtr content; + + aFrame->GetContent(getter_AddRefs(content)); + return content.get() == aParentContent; +} + +static nsIFrame* +GetFirstChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + nsIFrame* childFrame; + + // Get the first child frame + aFrame->FirstChild(aPresContext, nsnull, &childFrame); + + // If the child frame is a pseudo-frame, then return its first child + if (childFrame && IsPseudoFrame(childFrame, aContent)) { + return GetFirstChildFrame(aPresContext, childFrame, aContent); + } + + return childFrame; +} + +static nsIFrame* +GetLastChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + // Get the last in flow frame + nsIFrame* lastInFlow; + while (aFrame) { + lastInFlow = aFrame; + lastInFlow->GetNextInFlow(&aFrame); + } + + // Get the first child frame + nsIFrame* firstChildFrame; + lastInFlow->FirstChild(aPresContext, nsnull, &firstChildFrame); + if (firstChildFrame) { + nsFrameList frameList(firstChildFrame); + nsIFrame* lastChildFrame = frameList.LastChild(); + + NS_ASSERTION(lastChildFrame, "unexpected error"); + + // If the last child frame is a pseudo-frame, then return its last child + if (lastChildFrame && IsPseudoFrame(lastChildFrame, aContent)) { + return GetLastChildFrame(aPresContext, lastChildFrame, aContent); + } + + return lastChildFrame; + } + + return nsnull; +} + +NS_IMETHODIMP +PresShell::GetGeneratedContentIterator(nsIContent* aContent, + GeneratedContentType aType, + nsIContentIterator** aIterator) const +{ + nsIFrame* primaryFrame; + nsresult rv = NS_OK; + + // Initialize OUT parameter + *aIterator = nsnull; + + // Get the primary frame associated with the content object + GetPrimaryFrameFor(aContent, &primaryFrame); + if (primaryFrame) { + // See whether it's a request for the before or after generated content + if (Before == aType) { + // The most efficient thing to do is to get the first child frame, + // and see if it is associated with generated content + nsIFrame* firstChildFrame = GetFirstChildFrame(mPresContext, primaryFrame, aContent); + if (firstChildFrame && IsGeneratedContentFrame(firstChildFrame)) { + // Create an iterator + rv = NS_NewGeneratedContentIterator(mPresContext, firstChildFrame, aIterator); + } + + } else { + // Avoid finding the last child frame unless we need to. Instead probe + // for the existence of the pseudo-element + nsCOMPtr styleContext; + nsCOMPtr pseudoStyleContext; + + primaryFrame->GetStyleContext(getter_AddRefs(styleContext)); + mPresContext->ProbePseudoStyleContextFor(aContent, nsCSSAtoms::afterPseudo, + styleContext, PR_FALSE, + getter_AddRefs(pseudoStyleContext)); + if (pseudoStyleContext) { + nsIFrame* lastChildFrame = GetLastChildFrame(mPresContext, primaryFrame, aContent); + NS_ASSERTION(lastChildFrame && IsGeneratedContentFrame(lastChildFrame), + "can't find generated content frame"); + // Create an iterator + rv = NS_NewGeneratedContentIterator(mPresContext, lastChildFrame, aIterator); + } + } + } + + return rv; +} NS_IMETHODIMP PresShell::FlushPendingNotifications() diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index 8c66dfdec97..a702406505c 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -29,6 +29,7 @@ #include "nsIReflowCommand.h" class nsIContent; +class nsIContentIterator; class nsIDocument; class nsIDocumentObserver; class nsIFrame; @@ -413,6 +414,18 @@ public: */ NS_IMETHOD IsReflowLocked(PRBool* aIsLocked) = 0; + /** + * Returns a content iterator to iterate the generated content nodes. + * You must specify whether you want to iterate the "before" generated + * content or the "after" generated content. If there is no generated + * content of the specified type for the promary frame associated with + * with the content object then NULL is returned + */ + enum GeneratedContentType {Before, After}; + NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent, + GeneratedContentType aType, + nsIContentIterator** aIterator) const = 0; + /** * See if reflow verification is enabled. To enable reflow verification add * "verifyreflow:1" to your NSPR_LOG_MODULES environment variable diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index f06f1e622fa..e4596669e8a 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -77,6 +77,7 @@ #include "nsTimer.h" #include "nsWeakPtr.h" #include "plarena.h" +#include "nsCSSAtoms.h" #ifdef MOZ_PERF_METRICS #include "nsITimeRecorder.h" #endif @@ -373,6 +374,10 @@ public: NS_IMETHOD GetReflowEventStatus(PRBool* aPending); NS_IMETHOD SetReflowEventStatus(PRBool aPending); + NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent, + GeneratedContentType aType, + nsIContentIterator** aIterator) const; + /** * Reflow batching */ @@ -2518,6 +2523,123 @@ PresShell::SetReflowEventStatus(PRBool aPending) mPendingReflowEvent = aPending; return NS_OK; } + +static PRBool +IsGeneratedContentFrame(nsIFrame* aFrame) +{ + nsFrameState frameState; + + aFrame->GetFrameState(&frameState); + return (frameState & NS_FRAME_GENERATED_CONTENT) != 0; +} + +static PRBool +IsPseudoFrame(nsIFrame* aFrame, nsIContent* aParentContent) +{ + nsCOMPtr content; + + aFrame->GetContent(getter_AddRefs(content)); + return content.get() == aParentContent; +} + +static nsIFrame* +GetFirstChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + nsIFrame* childFrame; + + // Get the first child frame + aFrame->FirstChild(aPresContext, nsnull, &childFrame); + + // If the child frame is a pseudo-frame, then return its first child + if (childFrame && IsPseudoFrame(childFrame, aContent)) { + return GetFirstChildFrame(aPresContext, childFrame, aContent); + } + + return childFrame; +} + +static nsIFrame* +GetLastChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + // Get the last in flow frame + nsIFrame* lastInFlow; + while (aFrame) { + lastInFlow = aFrame; + lastInFlow->GetNextInFlow(&aFrame); + } + + // Get the first child frame + nsIFrame* firstChildFrame; + lastInFlow->FirstChild(aPresContext, nsnull, &firstChildFrame); + if (firstChildFrame) { + nsFrameList frameList(firstChildFrame); + nsIFrame* lastChildFrame = frameList.LastChild(); + + NS_ASSERTION(lastChildFrame, "unexpected error"); + + // If the last child frame is a pseudo-frame, then return its last child + if (lastChildFrame && IsPseudoFrame(lastChildFrame, aContent)) { + return GetLastChildFrame(aPresContext, lastChildFrame, aContent); + } + + return lastChildFrame; + } + + return nsnull; +} + +NS_IMETHODIMP +PresShell::GetGeneratedContentIterator(nsIContent* aContent, + GeneratedContentType aType, + nsIContentIterator** aIterator) const +{ + nsIFrame* primaryFrame; + nsresult rv = NS_OK; + + // Initialize OUT parameter + *aIterator = nsnull; + + // Get the primary frame associated with the content object + GetPrimaryFrameFor(aContent, &primaryFrame); + if (primaryFrame) { + // See whether it's a request for the before or after generated content + if (Before == aType) { + // The most efficient thing to do is to get the first child frame, + // and see if it is associated with generated content + nsIFrame* firstChildFrame = GetFirstChildFrame(mPresContext, primaryFrame, aContent); + if (firstChildFrame && IsGeneratedContentFrame(firstChildFrame)) { + // Create an iterator + rv = NS_NewGeneratedContentIterator(mPresContext, firstChildFrame, aIterator); + } + + } else { + // Avoid finding the last child frame unless we need to. Instead probe + // for the existence of the pseudo-element + nsCOMPtr styleContext; + nsCOMPtr pseudoStyleContext; + + primaryFrame->GetStyleContext(getter_AddRefs(styleContext)); + mPresContext->ProbePseudoStyleContextFor(aContent, nsCSSAtoms::afterPseudo, + styleContext, PR_FALSE, + getter_AddRefs(pseudoStyleContext)); + if (pseudoStyleContext) { + nsIFrame* lastChildFrame = GetLastChildFrame(mPresContext, primaryFrame, aContent); + NS_ASSERTION(lastChildFrame && IsGeneratedContentFrame(lastChildFrame), + "can't find generated content frame"); + // Create an iterator + rv = NS_NewGeneratedContentIterator(mPresContext, lastChildFrame, aIterator); + } + } + } + + return rv; +} NS_IMETHODIMP PresShell::FlushPendingNotifications()