diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 001db31d0280..5da4e09930a1 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -113,6 +113,7 @@ #include "nsCSSRendering.h" #include "nsISelectElement.h" #include "nsLayoutErrors.h" +#include "nsLayoutUtils.h" #include "nsAutoPtr.h" #include "nsScrollPortFrame.h" #include "nsXULAtoms.h" @@ -7731,35 +7732,6 @@ nsCSSFrameConstructor::GetFloaterContainingBlock(nsIPresContext* aPresContext, return containingBlock; } -// Helper function to determine whether a given frame is generated content -// for the specified content object. Returns PR_TRUE if the frame is associated -// with generated content and PR_FALSE otherwise -static inline PRBool -IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, nsIAtom* aPseudoElement) -{ - NS_PRECONDITION(aFrame, "null frame pointer"); - nsFrameState state; - PRBool result = PR_FALSE; - - // First check the frame state bit - aFrame->GetFrameState(&state); - if (state & NS_FRAME_GENERATED_CONTENT) { - nsCOMPtr content; - - // Check that it has the same content pointer - aFrame->GetContent(getter_AddRefs(content)); - if (content == aContent) { - nsStyleContext* styleContext = aFrame->GetStyleContext(); - - // See if the pseudo element type matches - nsCOMPtr pseudoType = styleContext->GetPseudoType(); - result = (pseudoType == aPseudoElement); - } - } - - return result; -} - /** * This function is called by ContentAppended() and ContentInserted() * when appending flowed frames to a parent's principal child list. It @@ -7774,18 +7746,24 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext, nsIFrame* aParentFrame, nsIFrame* aFrameList) { - nsIFrame* firstChild; - aParentFrame->FirstChild(aPresContext, nsnull, &firstChild); - nsFrameList frames(firstChild); - nsIFrame* lastChild = frames.LastChild(); + // See if the parent has an :after pseudo-element. Check for the presence + // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive. + nsStyleContext* parentStyle = aParentFrame->GetStyleContext(); + if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle, + nsCSSPseudoElements::after, + aPresContext)) { + nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame, + aPresContext); + if (afterFrame) { + nsIFrame* firstChild; + aParentFrame->FirstChild(aPresContext, nsnull, &firstChild); + nsFrameList frames(firstChild); - // See if the parent has an :after pseudo-element - if (lastChild && IsGeneratedContentFor(aContainer, lastChild, - nsCSSPseudoElements::after)) { - // Insert the frames before the :after pseudo-element. - return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, - nsnull, frames.GetPrevSiblingFor(lastChild), + // Insert the frames before the :after pseudo-element. + return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, + nsnull, frames.GetPrevSiblingFor(afterFrame), aFrameList); + } } nsresult rv = NS_OK; @@ -9248,8 +9226,9 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, nsIFrame* firstChild; parentFrame->FirstChild(aPresContext, nsnull, &firstChild); - if (firstChild && IsGeneratedContentFor(aContainer, firstChild, - nsCSSPseudoElements::before)) { + if (firstChild && + nsLayoutUtils::IsGeneratedContentFor(aContainer, firstChild, + nsCSSPseudoElements::before)) { // Insert the new frames after the :before pseudo-element prevSibling = firstChild; } @@ -9570,21 +9549,6 @@ nsCSSFrameConstructor::RemoveMappingsForFrameSubtree(nsIPresContext* aPresContex return DeletingFrameSubtree(aPresContext, presShell, frameManager, aRemovedFrame); } -static PRBool -HasPseudoStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsStyleContext* aStyleContext, - nsIAtom* aPseudoElement) -{ - nsRefPtr pseudoStyleContext; - if (aContent) { - pseudoStyleContext = aPresContext->ProbePseudoStyleContextFor(aContent, - aPseudoElement, - aStyleContext); - } - return pseudoStyleContext != nsnull; -} - NS_IMETHODIMP nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -11694,8 +11658,8 @@ nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext, // next sibling. if (aContent->IsContentOfType(nsIContent::eELEMENT) && - IsGeneratedContentFor(aContent, kidFrame, - nsCSSPseudoElements::before)) { + nsLayoutUtils::IsGeneratedContentFor(aContent, kidFrame, + nsCSSPseudoElements::before)) { kidFrame->GetNextSibling(&kidFrame); #ifdef DEBUG NS_ASSERTION(kidFrame, ":before with no next sibling"); @@ -11707,8 +11671,8 @@ nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext, // make sure it's not the :after pseudo frame. NS_ASSERTION(nextSiblingContent.get() == aContent && - !IsGeneratedContentFor(aContent, kidFrame, - nsCSSPseudoElements::after), + !nsLayoutUtils::IsGeneratedContentFor(aContent, kidFrame, + nsCSSPseudoElements::after), ":before frame not followed by primary frame"); } #endif @@ -12136,8 +12100,9 @@ nsCSSFrameConstructor::HaveFirstLetterStyle(nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext) { - return HasPseudoStyle(aPresContext, aContent, aStyleContext, - nsCSSPseudoElements::firstLetter); + return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext, + nsCSSPseudoElements::firstLetter, + aPresContext); } PRBool @@ -12145,8 +12110,9 @@ nsCSSFrameConstructor::HaveFirstLineStyle(nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext) { - return HasPseudoStyle(aPresContext, aContent, aStyleContext, - nsCSSPseudoElements::firstLine); + return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext, + nsCSSPseudoElements::firstLine, + aPresContext); } void diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index 96fcfae8719e..a4fd6f2bd6a3 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -1889,19 +1889,14 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (!prevInFlow) { // Checking for a :before frame is cheaper than getting the // :before style context. - nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(aFrame, - aPresContext); - if (!beforeFrame) { - // Look for a new :before style context - nsRefPtr newBeforeContext = aPresContext->ProbePseudoStyleContextFor(localContent, - nsCSSPseudoElements::before, - newContext); - if (newBeforeContext) { - // Have to create the new :before frame - NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); - aChangeList.AppendChange(aFrame, content, - nsChangeHint_ReconstructFrame); - } + if (!nsLayoutUtils::GetBeforeFrame(aFrame, aPresContext) && + nsLayoutUtils::HasPseudoStyle(localContent, newContext, + nsCSSPseudoElements::before, + aPresContext)) { + // Have to create the new :before frame + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); } } } @@ -1910,29 +1905,24 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { if (localContent && localContent->IsContentOfType(nsIContent::eELEMENT)) { - // Check for new :after content, but only if the frame is the first-in-flow. + // Check for new :after content, but only if the frame is the + // first-in-flow. nsIFrame* nextInFlow = nsnull; aFrame->GetNextInFlow(&nextInFlow); if (!nextInFlow) { - // Getting the :after frame is - // more expensive than getting the pseudo context, so get the - // pseudo context first. - nsRefPtr newAfterContext = aPresContext->ProbePseudoStyleContextFor(localContent, - nsCSSPseudoElements::after, - newContext); - if (newAfterContext) { - // Check whether we already have an :after frame - nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aFrame, - aPresContext); - if (!afterFrame) { - // have to create one - NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); - aChangeList.AppendChange(aFrame, content, - nsChangeHint_ReconstructFrame); - } + // Getting the :after frame is more expensive than getting the pseudo + // context, so get the pseudo context first. + if (nsLayoutUtils::HasPseudoStyle(localContent, newContext, + nsCSSPseudoElements::after, + aPresContext) && + !nsLayoutUtils::GetAfterFrame(aFrame, aPresContext)) { + // have to create the new :after frame + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); } - } + } } } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index d846e136942c..a0f5ba371c61 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -41,6 +41,8 @@ #include "nsIContent.h" #include "nsFrameList.h" #include "nsLayoutAtoms.h" +#include "nsIAtom.h" +#include "nsCSSPseudoElements.h" /** * A namespace class for static layout utilities. @@ -139,7 +141,8 @@ nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) aFrame->GetContent(getter_AddRefs(content)); nsIFrame* firstFrame = GetFirstChildFrame(aPresContext, aFrame, content); - if (firstFrame && firstFrame->IsGeneratedContentFrame()) { + if (firstFrame && IsGeneratedContentFor(nsnull, firstFrame, + nsCSSPseudoElements::before)) { return firstFrame; } @@ -156,13 +159,15 @@ nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) aFrame->GetContent(getter_AddRefs(content)); nsIFrame* lastFrame = GetLastChildFrame(aPresContext, aFrame, content); - if (lastFrame && lastFrame->IsGeneratedContentFrame()) { + if (lastFrame && IsGeneratedContentFor(nsnull, lastFrame, + nsCSSPseudoElements::after)) { return lastFrame; } return nsnull; } +// static nsIFrame* nsLayoutUtils::GetPageFrame(nsIFrame* aFrame) { @@ -177,3 +182,30 @@ nsLayoutUtils::GetPageFrame(nsIFrame* aFrame) } return nsnull; } + +// static +PRBool +nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent, + nsIFrame* aFrame, + nsIAtom* aPseudoElement) +{ + NS_PRECONDITION(aFrame, "Must have a frame"); + NS_PRECONDITION(aPseudoElement, "Must have a pseudo name"); + + if (!aFrame->IsGeneratedContentFrame()) { + return PR_FALSE; + } + + if (aContent) { + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + if (content != aContent) { + return PR_FALSE; + } + } + + nsStyleContext* styleContext = aFrame->GetStyleContext(); + nsCOMPtr pseudoType = styleContext->GetPseudoType(); + return pseudoType == aPseudoElement; +} + diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 40e78783f6ac..5b65e44bf297 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -40,6 +40,12 @@ class nsIFrame; class nsIPresContext; +class nsIContent; +class nsIAtom; + +#include "prtypes.h" +#include "nsStyleContext.h" +#include "nsAutoPtr.h" /** * nsLayoutUtils is a namespace class used for various helper @@ -72,11 +78,58 @@ public: */ static nsIFrame* GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext); - /** --------------------------------------------------- - * Giving a child frame it searches "up" the tree until it - * finds a "Page" frame. + /** + * Given a frame, search up the frame tree until we find an + * ancestor "Page" frame, if any. + * + * @param the frame to start at + * @return a frame of type nsLayoutAtoms::pageFrame or nsnull if no + * such ancestor exists */ static nsIFrame* GetPageFrame(nsIFrame* aFrame); + + /** + * IsGeneratedContentFor returns PR_TRUE if aFrame is generated + * content of type aPseudoElement for aContent + * + * @param aContent the content node we're looking at. If this is + * null, then we just assume that aFrame has the right content + * pointer. + * @param aFrame the frame we're looking at + * @param aPseudoElement the pseudo type we're interested in + * @return whether aFrame is the generated aPseudoElement frame for aContent + */ + static PRBool IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, + nsIAtom* aPseudoElement); + + /** + * HasPseudoStyle returns PR_TRUE if aContent (whose primary style + * context is aStyleContext) has the aPseudoElement pseudo-style + * attached to it; returns PR_FALSE otherwise. + * + * @param aContent the content node we're looking at + * @param aStyleContext aContent's style context + * @param aPseudoElement the name of the pseudo style we care about + * @param aPresContext the presentation context + * @return whether aContent has aPseudoElement style attached to it + */ + static PRBool HasPseudoStyle(nsIContent* aContent, + nsStyleContext* aStyleContext, + nsIAtom* aPseudoElement, + nsIPresContext* aPresContext) + { + NS_PRECONDITION(aPresContext, "Must have a prescontext"); + NS_PRECONDITION(aPseudoElement, "Must have a pseudo name"); + + nsRefPtr pseudoContext; + if (aContent) { + pseudoContext = aPresContext->ProbePseudoStyleContextFor(aContent, + aPseudoElement, + aStyleContext); + } + return pseudoContext != nsnull; + } + }; #endif // nsLayoutUtils_h__ diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index ae33ff3022bf..00637c40a6cc 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -4718,13 +4718,11 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent, // Avoid finding the :after frame unless we need to (it's // expensive). Instead probe for the existence of the pseudo-element nsStyleContext *styleContext; - nsRefPtr pseudoStyleContext; styleContext = primaryFrame->GetStyleContext(); - pseudoStyleContext = mPresContext->ProbePseudoStyleContextFor(aContent, - nsCSSPseudoElements::after, - styleContext); - if (pseudoStyleContext) { + if (nsLayoutUtils::HasPseudoStyle(aContent, styleContext, + nsCSSPseudoElements::after, + mPresContext)) { nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(primaryFrame, mPresContext); if (afterFrame) diff --git a/layout/base/public/nsLayoutUtils.h b/layout/base/public/nsLayoutUtils.h index 40e78783f6ac..5b65e44bf297 100644 --- a/layout/base/public/nsLayoutUtils.h +++ b/layout/base/public/nsLayoutUtils.h @@ -40,6 +40,12 @@ class nsIFrame; class nsIPresContext; +class nsIContent; +class nsIAtom; + +#include "prtypes.h" +#include "nsStyleContext.h" +#include "nsAutoPtr.h" /** * nsLayoutUtils is a namespace class used for various helper @@ -72,11 +78,58 @@ public: */ static nsIFrame* GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext); - /** --------------------------------------------------- - * Giving a child frame it searches "up" the tree until it - * finds a "Page" frame. + /** + * Given a frame, search up the frame tree until we find an + * ancestor "Page" frame, if any. + * + * @param the frame to start at + * @return a frame of type nsLayoutAtoms::pageFrame or nsnull if no + * such ancestor exists */ static nsIFrame* GetPageFrame(nsIFrame* aFrame); + + /** + * IsGeneratedContentFor returns PR_TRUE if aFrame is generated + * content of type aPseudoElement for aContent + * + * @param aContent the content node we're looking at. If this is + * null, then we just assume that aFrame has the right content + * pointer. + * @param aFrame the frame we're looking at + * @param aPseudoElement the pseudo type we're interested in + * @return whether aFrame is the generated aPseudoElement frame for aContent + */ + static PRBool IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, + nsIAtom* aPseudoElement); + + /** + * HasPseudoStyle returns PR_TRUE if aContent (whose primary style + * context is aStyleContext) has the aPseudoElement pseudo-style + * attached to it; returns PR_FALSE otherwise. + * + * @param aContent the content node we're looking at + * @param aStyleContext aContent's style context + * @param aPseudoElement the name of the pseudo style we care about + * @param aPresContext the presentation context + * @return whether aContent has aPseudoElement style attached to it + */ + static PRBool HasPseudoStyle(nsIContent* aContent, + nsStyleContext* aStyleContext, + nsIAtom* aPseudoElement, + nsIPresContext* aPresContext) + { + NS_PRECONDITION(aPresContext, "Must have a prescontext"); + NS_PRECONDITION(aPseudoElement, "Must have a pseudo name"); + + nsRefPtr pseudoContext; + if (aContent) { + pseudoContext = aPresContext->ProbePseudoStyleContextFor(aContent, + aPseudoElement, + aStyleContext); + } + return pseudoContext != nsnull; + } + }; #endif // nsLayoutUtils_h__ diff --git a/layout/base/src/nsLayoutUtils.cpp b/layout/base/src/nsLayoutUtils.cpp index d846e136942c..a0f5ba371c61 100644 --- a/layout/base/src/nsLayoutUtils.cpp +++ b/layout/base/src/nsLayoutUtils.cpp @@ -41,6 +41,8 @@ #include "nsIContent.h" #include "nsFrameList.h" #include "nsLayoutAtoms.h" +#include "nsIAtom.h" +#include "nsCSSPseudoElements.h" /** * A namespace class for static layout utilities. @@ -139,7 +141,8 @@ nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) aFrame->GetContent(getter_AddRefs(content)); nsIFrame* firstFrame = GetFirstChildFrame(aPresContext, aFrame, content); - if (firstFrame && firstFrame->IsGeneratedContentFrame()) { + if (firstFrame && IsGeneratedContentFor(nsnull, firstFrame, + nsCSSPseudoElements::before)) { return firstFrame; } @@ -156,13 +159,15 @@ nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) aFrame->GetContent(getter_AddRefs(content)); nsIFrame* lastFrame = GetLastChildFrame(aPresContext, aFrame, content); - if (lastFrame && lastFrame->IsGeneratedContentFrame()) { + if (lastFrame && IsGeneratedContentFor(nsnull, lastFrame, + nsCSSPseudoElements::after)) { return lastFrame; } return nsnull; } +// static nsIFrame* nsLayoutUtils::GetPageFrame(nsIFrame* aFrame) { @@ -177,3 +182,30 @@ nsLayoutUtils::GetPageFrame(nsIFrame* aFrame) } return nsnull; } + +// static +PRBool +nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent, + nsIFrame* aFrame, + nsIAtom* aPseudoElement) +{ + NS_PRECONDITION(aFrame, "Must have a frame"); + NS_PRECONDITION(aPseudoElement, "Must have a pseudo name"); + + if (!aFrame->IsGeneratedContentFrame()) { + return PR_FALSE; + } + + if (aContent) { + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + if (content != aContent) { + return PR_FALSE; + } + } + + nsStyleContext* styleContext = aFrame->GetStyleContext(); + nsCOMPtr pseudoType = styleContext->GetPseudoType(); + return pseudoType == aPseudoElement; +} + diff --git a/layout/html/base/src/nsFrameManager.cpp b/layout/html/base/src/nsFrameManager.cpp index 96fcfae8719e..a4fd6f2bd6a3 100644 --- a/layout/html/base/src/nsFrameManager.cpp +++ b/layout/html/base/src/nsFrameManager.cpp @@ -1889,19 +1889,14 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (!prevInFlow) { // Checking for a :before frame is cheaper than getting the // :before style context. - nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(aFrame, - aPresContext); - if (!beforeFrame) { - // Look for a new :before style context - nsRefPtr newBeforeContext = aPresContext->ProbePseudoStyleContextFor(localContent, - nsCSSPseudoElements::before, - newContext); - if (newBeforeContext) { - // Have to create the new :before frame - NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); - aChangeList.AppendChange(aFrame, content, - nsChangeHint_ReconstructFrame); - } + if (!nsLayoutUtils::GetBeforeFrame(aFrame, aPresContext) && + nsLayoutUtils::HasPseudoStyle(localContent, newContext, + nsCSSPseudoElements::before, + aPresContext)) { + // Have to create the new :before frame + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); } } } @@ -1910,29 +1905,24 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { if (localContent && localContent->IsContentOfType(nsIContent::eELEMENT)) { - // Check for new :after content, but only if the frame is the first-in-flow. + // Check for new :after content, but only if the frame is the + // first-in-flow. nsIFrame* nextInFlow = nsnull; aFrame->GetNextInFlow(&nextInFlow); if (!nextInFlow) { - // Getting the :after frame is - // more expensive than getting the pseudo context, so get the - // pseudo context first. - nsRefPtr newAfterContext = aPresContext->ProbePseudoStyleContextFor(localContent, - nsCSSPseudoElements::after, - newContext); - if (newAfterContext) { - // Check whether we already have an :after frame - nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aFrame, - aPresContext); - if (!afterFrame) { - // have to create one - NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); - aChangeList.AppendChange(aFrame, content, - nsChangeHint_ReconstructFrame); - } + // Getting the :after frame is more expensive than getting the pseudo + // context, so get the pseudo context first. + if (nsLayoutUtils::HasPseudoStyle(localContent, newContext, + nsCSSPseudoElements::after, + aPresContext) && + !nsLayoutUtils::GetAfterFrame(aFrame, aPresContext)) { + // have to create the new :after frame + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); } - } + } } } diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index ae33ff3022bf..00637c40a6cc 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -4718,13 +4718,11 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent, // Avoid finding the :after frame unless we need to (it's // expensive). Instead probe for the existence of the pseudo-element nsStyleContext *styleContext; - nsRefPtr pseudoStyleContext; styleContext = primaryFrame->GetStyleContext(); - pseudoStyleContext = mPresContext->ProbePseudoStyleContextFor(aContent, - nsCSSPseudoElements::after, - styleContext); - if (pseudoStyleContext) { + if (nsLayoutUtils::HasPseudoStyle(aContent, styleContext, + nsCSSPseudoElements::after, + mPresContext)) { nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(primaryFrame, mPresContext); if (afterFrame) diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 001db31d0280..5da4e09930a1 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -113,6 +113,7 @@ #include "nsCSSRendering.h" #include "nsISelectElement.h" #include "nsLayoutErrors.h" +#include "nsLayoutUtils.h" #include "nsAutoPtr.h" #include "nsScrollPortFrame.h" #include "nsXULAtoms.h" @@ -7731,35 +7732,6 @@ nsCSSFrameConstructor::GetFloaterContainingBlock(nsIPresContext* aPresContext, return containingBlock; } -// Helper function to determine whether a given frame is generated content -// for the specified content object. Returns PR_TRUE if the frame is associated -// with generated content and PR_FALSE otherwise -static inline PRBool -IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, nsIAtom* aPseudoElement) -{ - NS_PRECONDITION(aFrame, "null frame pointer"); - nsFrameState state; - PRBool result = PR_FALSE; - - // First check the frame state bit - aFrame->GetFrameState(&state); - if (state & NS_FRAME_GENERATED_CONTENT) { - nsCOMPtr content; - - // Check that it has the same content pointer - aFrame->GetContent(getter_AddRefs(content)); - if (content == aContent) { - nsStyleContext* styleContext = aFrame->GetStyleContext(); - - // See if the pseudo element type matches - nsCOMPtr pseudoType = styleContext->GetPseudoType(); - result = (pseudoType == aPseudoElement); - } - } - - return result; -} - /** * This function is called by ContentAppended() and ContentInserted() * when appending flowed frames to a parent's principal child list. It @@ -7774,18 +7746,24 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext, nsIFrame* aParentFrame, nsIFrame* aFrameList) { - nsIFrame* firstChild; - aParentFrame->FirstChild(aPresContext, nsnull, &firstChild); - nsFrameList frames(firstChild); - nsIFrame* lastChild = frames.LastChild(); + // See if the parent has an :after pseudo-element. Check for the presence + // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive. + nsStyleContext* parentStyle = aParentFrame->GetStyleContext(); + if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle, + nsCSSPseudoElements::after, + aPresContext)) { + nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame, + aPresContext); + if (afterFrame) { + nsIFrame* firstChild; + aParentFrame->FirstChild(aPresContext, nsnull, &firstChild); + nsFrameList frames(firstChild); - // See if the parent has an :after pseudo-element - if (lastChild && IsGeneratedContentFor(aContainer, lastChild, - nsCSSPseudoElements::after)) { - // Insert the frames before the :after pseudo-element. - return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, - nsnull, frames.GetPrevSiblingFor(lastChild), + // Insert the frames before the :after pseudo-element. + return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, + nsnull, frames.GetPrevSiblingFor(afterFrame), aFrameList); + } } nsresult rv = NS_OK; @@ -9248,8 +9226,9 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, nsIFrame* firstChild; parentFrame->FirstChild(aPresContext, nsnull, &firstChild); - if (firstChild && IsGeneratedContentFor(aContainer, firstChild, - nsCSSPseudoElements::before)) { + if (firstChild && + nsLayoutUtils::IsGeneratedContentFor(aContainer, firstChild, + nsCSSPseudoElements::before)) { // Insert the new frames after the :before pseudo-element prevSibling = firstChild; } @@ -9570,21 +9549,6 @@ nsCSSFrameConstructor::RemoveMappingsForFrameSubtree(nsIPresContext* aPresContex return DeletingFrameSubtree(aPresContext, presShell, frameManager, aRemovedFrame); } -static PRBool -HasPseudoStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsStyleContext* aStyleContext, - nsIAtom* aPseudoElement) -{ - nsRefPtr pseudoStyleContext; - if (aContent) { - pseudoStyleContext = aPresContext->ProbePseudoStyleContextFor(aContent, - aPseudoElement, - aStyleContext); - } - return pseudoStyleContext != nsnull; -} - NS_IMETHODIMP nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -11694,8 +11658,8 @@ nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext, // next sibling. if (aContent->IsContentOfType(nsIContent::eELEMENT) && - IsGeneratedContentFor(aContent, kidFrame, - nsCSSPseudoElements::before)) { + nsLayoutUtils::IsGeneratedContentFor(aContent, kidFrame, + nsCSSPseudoElements::before)) { kidFrame->GetNextSibling(&kidFrame); #ifdef DEBUG NS_ASSERTION(kidFrame, ":before with no next sibling"); @@ -11707,8 +11671,8 @@ nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext, // make sure it's not the :after pseudo frame. NS_ASSERTION(nextSiblingContent.get() == aContent && - !IsGeneratedContentFor(aContent, kidFrame, - nsCSSPseudoElements::after), + !nsLayoutUtils::IsGeneratedContentFor(aContent, kidFrame, + nsCSSPseudoElements::after), ":before frame not followed by primary frame"); } #endif @@ -12136,8 +12100,9 @@ nsCSSFrameConstructor::HaveFirstLetterStyle(nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext) { - return HasPseudoStyle(aPresContext, aContent, aStyleContext, - nsCSSPseudoElements::firstLetter); + return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext, + nsCSSPseudoElements::firstLetter, + aPresContext); } PRBool @@ -12145,8 +12110,9 @@ nsCSSFrameConstructor::HaveFirstLineStyle(nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext) { - return HasPseudoStyle(aPresContext, aContent, aStyleContext, - nsCSSPseudoElements::firstLine); + return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext, + nsCSSPseudoElements::firstLine, + aPresContext); } void