From 1d38d9f9537c0a6856e52034a20bc6b1930c5baa Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Sun, 23 Feb 2003 17:28:25 +0000 Subject: [PATCH] Make ProbePseudoStyleFor return null whenever :before and :after aren't displayed so that we don't try to reframe constantly in certain cases, preventing link clicking from working. b=188525 r+sr=bzbarsky --- content/base/src/nsStyleSet.cpp | 19 +++ layout/base/nsCSSFrameConstructor.cpp | 150 +++++++++--------- .../html/style/src/nsCSSFrameConstructor.cpp | 150 +++++++++--------- layout/style/nsStyleSet.cpp | 19 +++ 4 files changed, 180 insertions(+), 158 deletions(-) diff --git a/content/base/src/nsStyleSet.cpp b/content/base/src/nsStyleSet.cpp index e10ac083e9f..860121e179a 100644 --- a/content/base/src/nsStyleSet.cpp +++ b/content/base/src/nsStyleSet.cpp @@ -50,6 +50,7 @@ #include "nsIDocument.h" #include "nsIStyleFrameConstruction.h" #include "nsCSSAnonBoxes.h" +#include "nsCSSPseudoElements.h" #include "nsTimer.h" #include "nsICSSStyleSheet.h" #include "nsNetUtil.h" @@ -1326,6 +1327,24 @@ StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, mRuleWalker->Reset(); } } + + // For :before and :after pseudo-elements, having display: none or no + // 'content' property is equivalent to not having the pseudo-element + // at all. + if (result && + (aPseudoTag == nsCSSPseudoElements::before || + aPseudoTag == nsCSSPseudoElements::after)) { + const nsStyleDisplay *display; + const nsStyleContent *content; + ::GetStyleData(result, &display); + ::GetStyleData(result, &content); + // XXXldb What is contentCount for |content: ""|? + if (display->mDisplay == NS_STYLE_DISPLAY_NONE || + content->ContentCount() == 0) { + result->Release(); + result = nsnull; + } + } MOZ_TIMER_DEBUGLOG(("Stop: StyleSetImpl::ProbePseudoStyleFor(), this=%p\n", this)); STYLESET_STOP_TIMER(NS_TIMER_STYLE_RESOLUTION); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 77177307059..c1f8e1a42f5 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1586,94 +1586,86 @@ nsCSSFrameConstructor::CreateGeneratedContentFrame(nsIPresShell* aPresShe aStyleContext); if (pseudoStyleContext) { - const nsStyleDisplay* display; - - // See whether the generated content should be displayed. - display = (const nsStyleDisplay*)pseudoStyleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // See if there was any content specified - const nsStyleContent* styleContent = - (const nsStyleContent*)pseudoStyleContext->GetStyleData(eStyleStruct_Content); - PRUint32 contentCount = styleContent->ContentCount(); - - // XXXldb What is contentCount for |content: ""|? - if (contentCount > 0) { - if (aWrapperFrame) { - if (!*aWrapperFrame) { - const nsStyleDisplay *display; - ::GetStyleData(aStyleContext, &display); - nsIAtom *wrapperPseudo; - if (display->IsBlockLevel()) { - NS_NewBlockFrame(aPresShell, aWrapperFrame); - wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperBlock; - } else { - NS_NewInlineFrame(aPresShell, aWrapperFrame); - wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperInline; - } - nsStyleContext* parentSC = aStyleContext->GetParent(); - nsRefPtr wrapperSC; - wrapperSC = aPresContext->ResolvePseudoStyleContextFor(nsnull, - wrapperPseudo, - parentSC); - // |aFrame| is already the correct parent. - InitAndRestoreFrame(aPresContext, aState, aContent, aFrame, - wrapperSC, nsnull, *aWrapperFrame); - } - // Use the wrapper as the parent. - aFrame = *aWrapperFrame; - } - // Create a block box or an inline box depending on the value of - // the 'display' property - nsIFrame* containerFrame; - nsFrameItems childFrames; - - if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) { - NS_NewBlockFrame(aPresShell, &containerFrame); + // |ProbePseudoStyleContext| checks the 'display' property and the + // |ContentCount()| of the 'content' property for us. + if (aWrapperFrame) { + if (!*aWrapperFrame) { + const nsStyleDisplay *display; + ::GetStyleData(aStyleContext, &display); + nsIAtom *wrapperPseudo; + if (display->IsBlockLevel()) { + NS_NewBlockFrame(aPresShell, aWrapperFrame); + wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperBlock; } else { - NS_NewInlineFrame(aPresShell, &containerFrame); + NS_NewInlineFrame(aPresShell, aWrapperFrame); + wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperInline; } - InitAndRestoreFrame(aPresContext, aState, aContent, - aFrame, pseudoStyleContext, nsnull, containerFrame); - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, - pseudoStyleContext, nsnull, PR_FALSE); + nsStyleContext* parentSC = aStyleContext->GetParent(); + nsRefPtr wrapperSC; + wrapperSC = aPresContext->ResolvePseudoStyleContextFor(nsnull, + wrapperPseudo, + parentSC); + // |aFrame| is already the correct parent. + InitAndRestoreFrame(aPresContext, aState, aContent, aFrame, + wrapperSC, nsnull, *aWrapperFrame); + } + // Use the wrapper as the parent. + aFrame = *aWrapperFrame; + } + // Create a block box or an inline box depending on the value of + // the 'display' property + nsIFrame* containerFrame; + nsFrameItems childFrames; - // Mark the frame as being associated with generated content - nsFrameState frameState; - containerFrame->GetFrameState(&frameState); - frameState |= NS_FRAME_GENERATED_CONTENT; - containerFrame->SetFrameState(frameState); + const nsStyleDisplay *display; + ::GetStyleData(pseudoStyleContext.get(), &display); + if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) { + NS_NewBlockFrame(aPresShell, &containerFrame); + } else { + NS_NewInlineFrame(aPresShell, &containerFrame); + } + InitAndRestoreFrame(aPresContext, aState, aContent, + aFrame, pseudoStyleContext, nsnull, containerFrame); + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, + pseudoStyleContext, nsnull, PR_FALSE); - // Create another pseudo style context to use for all the generated child - // frames - nsRefPtr textStyleContext; - textStyleContext = aPresContext->ResolveStyleContextForNonElement(pseudoStyleContext); + // Mark the frame as being associated with generated content + nsFrameState frameState; + containerFrame->GetFrameState(&frameState); + frameState |= NS_FRAME_GENERATED_CONTENT; + containerFrame->SetFrameState(frameState); - // Now create content objects (and child frames) for each value of the - // 'content' property + // Create another pseudo style context to use for all the generated child + // frames + nsRefPtr textStyleContext; + textStyleContext = aPresContext->ResolveStyleContextForNonElement(pseudoStyleContext); - for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) { - nsIFrame* frame; + // Now create content objects (and child frames) for each value of the + // 'content' property - // Create a frame - nsresult result; - result = CreateGeneratedFrameFor(aPresContext, mDocument, containerFrame, - aContent, textStyleContext, - styleContent, contentIndex, &frame); - // Non-elements can't possibly have a view, so don't bother checking - if (NS_SUCCEEDED(result) && frame) { - // Add it to the list of child frames - childFrames.AddChild(frame); - } - } - - if (childFrames.childList) { - containerFrame->SetInitialChildList(aPresContext, nsnull, childFrames.childList); - } - *aResult = containerFrame; - return PR_TRUE; + const nsStyleContent *styleContent; + ::GetStyleData(pseudoStyleContext.get(), &styleContent); + PRUint32 contentCount = styleContent->ContentCount(); + for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) { + nsIFrame* frame; + + // Create a frame + nsresult result; + result = CreateGeneratedFrameFor(aPresContext, mDocument, containerFrame, + aContent, textStyleContext, + styleContent, contentIndex, &frame); + // Non-elements can't possibly have a view, so don't bother checking + if (NS_SUCCEEDED(result) && frame) { + // Add it to the list of child frames + childFrames.AddChild(frame); } } + + if (childFrames.childList) { + containerFrame->SetInitialChildList(aPresContext, nsnull, childFrames.childList); + } + *aResult = containerFrame; + return PR_TRUE; } return PR_FALSE; diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 77177307059..c1f8e1a42f5 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -1586,94 +1586,86 @@ nsCSSFrameConstructor::CreateGeneratedContentFrame(nsIPresShell* aPresShe aStyleContext); if (pseudoStyleContext) { - const nsStyleDisplay* display; - - // See whether the generated content should be displayed. - display = (const nsStyleDisplay*)pseudoStyleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // See if there was any content specified - const nsStyleContent* styleContent = - (const nsStyleContent*)pseudoStyleContext->GetStyleData(eStyleStruct_Content); - PRUint32 contentCount = styleContent->ContentCount(); - - // XXXldb What is contentCount for |content: ""|? - if (contentCount > 0) { - if (aWrapperFrame) { - if (!*aWrapperFrame) { - const nsStyleDisplay *display; - ::GetStyleData(aStyleContext, &display); - nsIAtom *wrapperPseudo; - if (display->IsBlockLevel()) { - NS_NewBlockFrame(aPresShell, aWrapperFrame); - wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperBlock; - } else { - NS_NewInlineFrame(aPresShell, aWrapperFrame); - wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperInline; - } - nsStyleContext* parentSC = aStyleContext->GetParent(); - nsRefPtr wrapperSC; - wrapperSC = aPresContext->ResolvePseudoStyleContextFor(nsnull, - wrapperPseudo, - parentSC); - // |aFrame| is already the correct parent. - InitAndRestoreFrame(aPresContext, aState, aContent, aFrame, - wrapperSC, nsnull, *aWrapperFrame); - } - // Use the wrapper as the parent. - aFrame = *aWrapperFrame; - } - // Create a block box or an inline box depending on the value of - // the 'display' property - nsIFrame* containerFrame; - nsFrameItems childFrames; - - if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) { - NS_NewBlockFrame(aPresShell, &containerFrame); + // |ProbePseudoStyleContext| checks the 'display' property and the + // |ContentCount()| of the 'content' property for us. + if (aWrapperFrame) { + if (!*aWrapperFrame) { + const nsStyleDisplay *display; + ::GetStyleData(aStyleContext, &display); + nsIAtom *wrapperPseudo; + if (display->IsBlockLevel()) { + NS_NewBlockFrame(aPresShell, aWrapperFrame); + wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperBlock; } else { - NS_NewInlineFrame(aPresShell, &containerFrame); + NS_NewInlineFrame(aPresShell, aWrapperFrame); + wrapperPseudo = nsCSSAnonBoxes::mozGCWrapperInline; } - InitAndRestoreFrame(aPresContext, aState, aContent, - aFrame, pseudoStyleContext, nsnull, containerFrame); - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, - pseudoStyleContext, nsnull, PR_FALSE); + nsStyleContext* parentSC = aStyleContext->GetParent(); + nsRefPtr wrapperSC; + wrapperSC = aPresContext->ResolvePseudoStyleContextFor(nsnull, + wrapperPseudo, + parentSC); + // |aFrame| is already the correct parent. + InitAndRestoreFrame(aPresContext, aState, aContent, aFrame, + wrapperSC, nsnull, *aWrapperFrame); + } + // Use the wrapper as the parent. + aFrame = *aWrapperFrame; + } + // Create a block box or an inline box depending on the value of + // the 'display' property + nsIFrame* containerFrame; + nsFrameItems childFrames; - // Mark the frame as being associated with generated content - nsFrameState frameState; - containerFrame->GetFrameState(&frameState); - frameState |= NS_FRAME_GENERATED_CONTENT; - containerFrame->SetFrameState(frameState); + const nsStyleDisplay *display; + ::GetStyleData(pseudoStyleContext.get(), &display); + if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) { + NS_NewBlockFrame(aPresShell, &containerFrame); + } else { + NS_NewInlineFrame(aPresShell, &containerFrame); + } + InitAndRestoreFrame(aPresContext, aState, aContent, + aFrame, pseudoStyleContext, nsnull, containerFrame); + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, + pseudoStyleContext, nsnull, PR_FALSE); - // Create another pseudo style context to use for all the generated child - // frames - nsRefPtr textStyleContext; - textStyleContext = aPresContext->ResolveStyleContextForNonElement(pseudoStyleContext); + // Mark the frame as being associated with generated content + nsFrameState frameState; + containerFrame->GetFrameState(&frameState); + frameState |= NS_FRAME_GENERATED_CONTENT; + containerFrame->SetFrameState(frameState); - // Now create content objects (and child frames) for each value of the - // 'content' property + // Create another pseudo style context to use for all the generated child + // frames + nsRefPtr textStyleContext; + textStyleContext = aPresContext->ResolveStyleContextForNonElement(pseudoStyleContext); - for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) { - nsIFrame* frame; + // Now create content objects (and child frames) for each value of the + // 'content' property - // Create a frame - nsresult result; - result = CreateGeneratedFrameFor(aPresContext, mDocument, containerFrame, - aContent, textStyleContext, - styleContent, contentIndex, &frame); - // Non-elements can't possibly have a view, so don't bother checking - if (NS_SUCCEEDED(result) && frame) { - // Add it to the list of child frames - childFrames.AddChild(frame); - } - } - - if (childFrames.childList) { - containerFrame->SetInitialChildList(aPresContext, nsnull, childFrames.childList); - } - *aResult = containerFrame; - return PR_TRUE; + const nsStyleContent *styleContent; + ::GetStyleData(pseudoStyleContext.get(), &styleContent); + PRUint32 contentCount = styleContent->ContentCount(); + for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) { + nsIFrame* frame; + + // Create a frame + nsresult result; + result = CreateGeneratedFrameFor(aPresContext, mDocument, containerFrame, + aContent, textStyleContext, + styleContent, contentIndex, &frame); + // Non-elements can't possibly have a view, so don't bother checking + if (NS_SUCCEEDED(result) && frame) { + // Add it to the list of child frames + childFrames.AddChild(frame); } } + + if (childFrames.childList) { + containerFrame->SetInitialChildList(aPresContext, nsnull, childFrames.childList); + } + *aResult = containerFrame; + return PR_TRUE; } return PR_FALSE; diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index e10ac083e9f..860121e179a 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -50,6 +50,7 @@ #include "nsIDocument.h" #include "nsIStyleFrameConstruction.h" #include "nsCSSAnonBoxes.h" +#include "nsCSSPseudoElements.h" #include "nsTimer.h" #include "nsICSSStyleSheet.h" #include "nsNetUtil.h" @@ -1326,6 +1327,24 @@ StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, mRuleWalker->Reset(); } } + + // For :before and :after pseudo-elements, having display: none or no + // 'content' property is equivalent to not having the pseudo-element + // at all. + if (result && + (aPseudoTag == nsCSSPseudoElements::before || + aPseudoTag == nsCSSPseudoElements::after)) { + const nsStyleDisplay *display; + const nsStyleContent *content; + ::GetStyleData(result, &display); + ::GetStyleData(result, &content); + // XXXldb What is contentCount for |content: ""|? + if (display->mDisplay == NS_STYLE_DISPLAY_NONE || + content->ContentCount() == 0) { + result->Release(); + result = nsnull; + } + } MOZ_TIMER_DEBUGLOG(("Stop: StyleSetImpl::ProbePseudoStyleFor(), this=%p\n", this)); STYLESET_STOP_TIMER(NS_TIMER_STYLE_RESOLUTION);