зеркало из https://github.com/mozilla/gecko-dev.git
Make nsCSSFrameConstructor::AppendFrames be smarter about looking for :after
pseudos. Move some utility functions into nsLayoutUtils; simplify some places that basically had copies of those functions. Improves perf a bit in bug 145425 and its dependencies, r+sr=roc+moz
This commit is contained in:
Родитель
3f1a59f26e
Коммит
f09182206c
|
@ -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<nsIContent> 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<nsIAtom> 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<nsStyleContext> 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
|
||||
|
|
|
@ -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<nsStyleContext> 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,27 +1905,22 @@ 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<nsStyleContext> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
if (content != aContent) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleContext* styleContext = aFrame->GetStyleContext();
|
||||
nsCOMPtr<nsIAtom> pseudoType = styleContext->GetPseudoType();
|
||||
return pseudoType == aPseudoElement;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<nsStyleContext> pseudoContext;
|
||||
if (aContent) {
|
||||
pseudoContext = aPresContext->ProbePseudoStyleContextFor(aContent,
|
||||
aPseudoElement,
|
||||
aStyleContext);
|
||||
}
|
||||
return pseudoContext != nsnull;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // nsLayoutUtils_h__
|
||||
|
|
|
@ -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<nsStyleContext> 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)
|
||||
|
|
|
@ -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<nsStyleContext> pseudoContext;
|
||||
if (aContent) {
|
||||
pseudoContext = aPresContext->ProbePseudoStyleContextFor(aContent,
|
||||
aPseudoElement,
|
||||
aStyleContext);
|
||||
}
|
||||
return pseudoContext != nsnull;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // nsLayoutUtils_h__
|
||||
|
|
|
@ -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<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
if (content != aContent) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleContext* styleContext = aFrame->GetStyleContext();
|
||||
nsCOMPtr<nsIAtom> pseudoType = styleContext->GetPseudoType();
|
||||
return pseudoType == aPseudoElement;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<nsStyleContext> 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,27 +1905,22 @@ 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<nsStyleContext> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<nsStyleContext> 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)
|
||||
|
|
|
@ -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<nsIContent> 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<nsIAtom> 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<nsStyleContext> 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
|
||||
|
|
Загрузка…
Ссылка в новой задаче