From 809c099e337880f9250e4001011544c0d0963d37 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Mon, 29 Mar 2004 16:00:38 +0000 Subject: [PATCH] Fix bug 236921. This makes the root node's style context have no parent, makes computed style calculations properly parent the computed context, and fixes a but with "border-color: inherit" on the root. r=caillon, sr=dbaron, a=asa --- content/base/src/nsRuleNode.cpp | 33 ++++++++------- content/html/style/src/nsComputedDOMStyle.cpp | 22 ++++------ .../html/style/src/nsInspectorCSSUtils.cpp | 42 ++++++++++++------- content/html/style/src/nsInspectorCSSUtils.h | 8 ++-- layout/base/nsCSSFrameConstructor.cpp | 12 +----- layout/base/nsCSSFrameConstructor.h | 1 - layout/generic/nsFrame.cpp | 5 +++ layout/html/base/src/nsFrame.cpp | 5 +++ .../html/style/src/nsCSSFrameConstructor.cpp | 12 +----- layout/html/style/src/nsCSSFrameConstructor.h | 1 - layout/style/nsComputedDOMStyle.cpp | 22 ++++------ layout/style/nsInspectorCSSUtils.cpp | 42 ++++++++++++------- layout/style/nsInspectorCSSUtils.h | 8 ++-- layout/style/nsRuleNode.cpp | 33 ++++++++------- 14 files changed, 128 insertions(+), 118 deletions(-) diff --git a/content/base/src/nsRuleNode.cpp b/content/base/src/nsRuleNode.cpp index d621b2937f55..279ddb5590ac 100644 --- a/content/base/src/nsRuleNode.cpp +++ b/content/base/src/nsRuleNode.cpp @@ -3236,20 +3236,25 @@ nsRuleNode::ComputeBorderData(nsStyleStruct* aStartStruct, FOR_CSS_SIDES(side) { const nsCSSValue &value = ourBorderColor.*(nsCSSRect::sides[side]); if (eCSSUnit_Inherit == value.GetUnit()) { - inherited = PR_TRUE; - parentBorder->GetBorderColor(side, borderColor, - transparent, foreground); - if (transparent) - border->SetBorderTransparent(side); - else if (foreground) { - // We want to inherit the color from the parent, not use the - // color on the element where this chunk of style data will be - // used. We can ensure that the data for the parent are fully - // computed (unlike for the element where this will be used, for - // which the color could be specified on a more specific rule). - border->SetBorderColor(side, parentContext->GetStyleColor()->mColor); - } else - border->SetBorderColor(side, borderColor); + if (parentContext) { + inherited = PR_TRUE; + parentBorder->GetBorderColor(side, borderColor, + transparent, foreground); + if (transparent) + border->SetBorderTransparent(side); + else if (foreground) { + // We want to inherit the color from the parent, not use the + // color on the element where this chunk of style data will be + // used. We can ensure that the data for the parent are fully + // computed (unlike for the element where this will be used, for + // which the color could be specified on a more specific rule). + border->SetBorderColor(side, parentContext->GetStyleColor()->mColor); + } else + border->SetBorderColor(side, borderColor); + } else { + // We're the root + border->SetBorderToForeground(side); + } } else if (SetColor(value, unused, mPresContext, borderColor, inherited)) { border->SetBorderColor(side, borderColor); diff --git a/content/html/style/src/nsComputedDOMStyle.cpp b/content/html/style/src/nsComputedDOMStyle.cpp index c8414319a77b..ee0be0db0c4b 100644 --- a/content/html/style/src/nsComputedDOMStyle.cpp +++ b/content/html/style/src/nsComputedDOMStyle.cpp @@ -61,6 +61,7 @@ #include "nsCSSPseudoElements.h" #include "nsStyleSet.h" #include "imgIRequest.h" +#include "nsInspectorCSSUtils.h" #if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon) #define DEBUG_ComputedDOMStyle @@ -2909,21 +2910,12 @@ nsComputedDOMStyle::GetStyleData(nsStyleStructID aID, NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); - nsCOMPtr pctx; - presShell->GetPresContext(getter_AddRefs(pctx)); - if (pctx) { - nsStyleContext* sctx; - nsStyleSet *styleSet = presShell->StyleSet(); - if (!mPseudo) { - sctx = styleSet->ResolveStyleFor(mContent, nsnull).get(); - } else { - sctx = styleSet->ResolvePseudoStyleFor(mContent, mPseudo, - nsnull).get(); - } - if (sctx) { - aStyleStruct = sctx->GetStyleData(aID); - } - mStyleContextHolder = dont_AddRef(sctx); // transfer ref from sctx + mStyleContextHolder = + nsInspectorCSSUtils::GetStyleContextForContent(mContent, + mPseudo, + presShell); + if (mStyleContextHolder) { + aStyleStruct = mStyleContextHolder->GetStyleData(aID); } } NS_ASSERTION(aStyleStruct, "Failed to get a style struct"); diff --git a/content/html/style/src/nsInspectorCSSUtils.cpp b/content/html/style/src/nsInspectorCSSUtils.cpp index 20771ec20a6c..fdf7e62c5886 100644 --- a/content/html/style/src/nsInspectorCSSUtils.cpp +++ b/content/html/style/src/nsInspectorCSSUtils.cpp @@ -117,6 +117,7 @@ nsInspectorCSSUtils::AdjustRectForMargins(nsIFrame* aFrame, nsRect& aRect) return NS_OK; } +/* static */ nsStyleContext* nsInspectorCSSUtils::GetStyleContextForFrame(nsIFrame* aFrame) { @@ -135,25 +136,30 @@ nsInspectorCSSUtils::GetStyleContextForFrame(nsIFrame* aFrame) return styleContext; } +/* static */ already_AddRefed nsInspectorCSSUtils::GetStyleContextForContent(nsIContent* aContent, + nsIAtom* aPseudo, nsIPresShell* aPresShell) { - nsIFrame* frame = nsnull; - aPresShell->GetPrimaryFrameFor(aContent, &frame); - if (frame) { - nsStyleContext* result = GetStyleContextForFrame(frame); - // this function returns an addrefed style context - if (result) - result->AddRef(); - return result; + if (!aPseudo) { + nsIFrame* frame = nsnull; + aPresShell->GetPrimaryFrameFor(aContent, &frame); + if (frame) { + nsStyleContext* result = GetStyleContextForFrame(frame); + // this function returns an addrefed style context + if (result) + result->AddRef(); + return result; + } } - // No frame has been created, so resolve the style ourselves + // No frame has been created or we have a pseudo, so resolve the + // style ourselves nsRefPtr parentContext; - nsCOMPtr parent = aContent->GetParent(); + nsIContent* parent = aPseudo ? aContent : aContent->GetParent(); if (parent) - parentContext = GetStyleContextForContent(parent, aPresShell); + parentContext = GetStyleContextForContent(parent, nsnull, aPresShell); nsCOMPtr presContext; aPresShell->GetPresContext(getter_AddRefs(presContext)); @@ -162,10 +168,16 @@ nsInspectorCSSUtils::GetStyleContextForContent(nsIContent* aContent, nsStyleSet *styleSet = aPresShell->StyleSet(); - if (aContent->IsContentOfType(nsIContent::eELEMENT)) - return styleSet->ResolveStyleFor(aContent, parentContext); + if (!aContent->IsContentOfType(nsIContent::eELEMENT)) { + NS_ASSERTION(!aPseudo, "Shouldn't have a pseudo for a non-element!"); + return styleSet->ResolveStyleForNonElement(parentContext); + } - return styleSet->ResolveStyleForNonElement(parentContext); + if (aPseudo) { + return styleSet->ResolvePseudoStyleFor(aContent, aPseudo, parentContext); + } + + return styleSet->ResolveStyleFor(aContent, parentContext); } NS_IMETHODIMP @@ -181,7 +193,7 @@ nsInspectorCSSUtils::GetRuleNodeForContent(nsIContent* aContent, NS_ENSURE_TRUE(presShell, NS_ERROR_UNEXPECTED); nsRefPtr sContext = - GetStyleContextForContent(aContent, presShell); + GetStyleContextForContent(aContent, nsnull, presShell); *aRuleNode = sContext->GetRuleNode(); return NS_OK; } diff --git a/content/html/style/src/nsInspectorCSSUtils.h b/content/html/style/src/nsInspectorCSSUtils.h index 65158b2b7a35..207a04bc5cf0 100644 --- a/content/html/style/src/nsInspectorCSSUtils.h +++ b/content/html/style/src/nsInspectorCSSUtils.h @@ -63,12 +63,12 @@ public: NS_IMETHOD AdjustRectForMargins(nsIFrame* aFrame, nsRect& aRect); NS_IMETHOD GetRuleNodeForContent(nsIContent* aContent, nsRuleNode** aRuleNode); + static already_AddRefed + GetStyleContextForContent(nsIContent* aContent, nsIAtom* aPseudo, + nsIPresShell* aPresShell); private: - already_AddRefed - GetStyleContextForContent(nsIContent* aContent, nsIPresShell* aPresShell); - - nsStyleContext* GetStyleContextForFrame(nsIFrame* aFrame); + static nsStyleContext* GetStyleContextForFrame(nsIFrame* aFrame); }; #endif /* nsInspectorCSSUtils_h___ */ diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 10e42b2cba7b..cab28c363bf0 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -3233,7 +3233,6 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, nsFrameConstructorState& aState, nsIContent* aDocElement, nsIFrame* aParentFrame, - nsStyleContext* aParentStyleContext, nsIFrame*& aNewFrame) { // how the root frame hierarchy should look @@ -3293,7 +3292,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, // --------- CREATE AREA OR BOX FRAME ------- nsRefPtr styleContext; styleContext = aPresShell->StyleSet()->ResolveStyleFor(aDocElement, - aParentStyleContext); + nsnull); const nsStyleDisplay* display = styleContext->GetStyleDisplay(); @@ -7206,11 +7205,8 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchy(nsIPresContext* aPresConte if (NS_SUCCEEDED(rv)) { // Create the new document element hierarchy nsIFrame* newChild; - nsStyleContext* rootPseudoStyle = docParentFrame->GetStyleContext(); - rv = ConstructDocElementFrame(shell, aPresContext, state, rootContent, - docParentFrame, rootPseudoStyle, - newChild); + docParentFrame, newChild); if (NS_SUCCEEDED(rv)) { rv = state.mFrameManager->InsertFrames(docParentFrame, nsnull, @@ -8647,9 +8643,6 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, // just bail here because the root will really be built later during // InitialReflow. - // Get the style context of the containing block frame - nsStyleContext* containerStyle = mDocElementContainingBlock->GetStyleContext(); - // Create frames for the document element and its child elements nsIFrame* docElementFrame; nsFrameConstructorState state(aPresContext, mFixedContainingBlock, nsnull, nsnull, aFrameState); @@ -8657,7 +8650,6 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, state, docElement, mDocElementContainingBlock, - containerStyle, docElementFrame); // Set the initial child list for the parent diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 350a8e967af9..39feee870a2e 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -218,7 +218,6 @@ protected: nsFrameConstructorState& aState, nsIContent* aDocElement, nsIFrame* aParentFrame, - nsStyleContext* aParentStyleContext, nsIFrame*& aNewFrame); nsresult ConstructDocElementTableFrame(nsIPresShell* aPresShell, diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index bed61c30bfde..be2682643522 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4390,6 +4390,11 @@ nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext, { *aIsChild = PR_FALSE; *aProviderFrame = nsnull; + if (mContent && !mContent->GetParent()) { + // we're a frame for the root. We have no style context parent. + return NS_OK; + } + if (!(mState & NS_FRAME_OUT_OF_FLOW)) { /* * If this frame is the anonymous block created when an inline diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index bed61c30bfde..be2682643522 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -4390,6 +4390,11 @@ nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext, { *aIsChild = PR_FALSE; *aProviderFrame = nsnull; + if (mContent && !mContent->GetParent()) { + // we're a frame for the root. We have no style context parent. + return NS_OK; + } + if (!(mState & NS_FRAME_OUT_OF_FLOW)) { /* * If this frame is the anonymous block created when an inline diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 10e42b2cba7b..cab28c363bf0 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -3233,7 +3233,6 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, nsFrameConstructorState& aState, nsIContent* aDocElement, nsIFrame* aParentFrame, - nsStyleContext* aParentStyleContext, nsIFrame*& aNewFrame) { // how the root frame hierarchy should look @@ -3293,7 +3292,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, // --------- CREATE AREA OR BOX FRAME ------- nsRefPtr styleContext; styleContext = aPresShell->StyleSet()->ResolveStyleFor(aDocElement, - aParentStyleContext); + nsnull); const nsStyleDisplay* display = styleContext->GetStyleDisplay(); @@ -7206,11 +7205,8 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchy(nsIPresContext* aPresConte if (NS_SUCCEEDED(rv)) { // Create the new document element hierarchy nsIFrame* newChild; - nsStyleContext* rootPseudoStyle = docParentFrame->GetStyleContext(); - rv = ConstructDocElementFrame(shell, aPresContext, state, rootContent, - docParentFrame, rootPseudoStyle, - newChild); + docParentFrame, newChild); if (NS_SUCCEEDED(rv)) { rv = state.mFrameManager->InsertFrames(docParentFrame, nsnull, @@ -8647,9 +8643,6 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, // just bail here because the root will really be built later during // InitialReflow. - // Get the style context of the containing block frame - nsStyleContext* containerStyle = mDocElementContainingBlock->GetStyleContext(); - // Create frames for the document element and its child elements nsIFrame* docElementFrame; nsFrameConstructorState state(aPresContext, mFixedContainingBlock, nsnull, nsnull, aFrameState); @@ -8657,7 +8650,6 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, state, docElement, mDocElementContainingBlock, - containerStyle, docElementFrame); // Set the initial child list for the parent diff --git a/layout/html/style/src/nsCSSFrameConstructor.h b/layout/html/style/src/nsCSSFrameConstructor.h index 350a8e967af9..39feee870a2e 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.h +++ b/layout/html/style/src/nsCSSFrameConstructor.h @@ -218,7 +218,6 @@ protected: nsFrameConstructorState& aState, nsIContent* aDocElement, nsIFrame* aParentFrame, - nsStyleContext* aParentStyleContext, nsIFrame*& aNewFrame); nsresult ConstructDocElementTableFrame(nsIPresShell* aPresShell, diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index c8414319a77b..ee0be0db0c4b 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -61,6 +61,7 @@ #include "nsCSSPseudoElements.h" #include "nsStyleSet.h" #include "imgIRequest.h" +#include "nsInspectorCSSUtils.h" #if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon) #define DEBUG_ComputedDOMStyle @@ -2909,21 +2910,12 @@ nsComputedDOMStyle::GetStyleData(nsStyleStructID aID, NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); - nsCOMPtr pctx; - presShell->GetPresContext(getter_AddRefs(pctx)); - if (pctx) { - nsStyleContext* sctx; - nsStyleSet *styleSet = presShell->StyleSet(); - if (!mPseudo) { - sctx = styleSet->ResolveStyleFor(mContent, nsnull).get(); - } else { - sctx = styleSet->ResolvePseudoStyleFor(mContent, mPseudo, - nsnull).get(); - } - if (sctx) { - aStyleStruct = sctx->GetStyleData(aID); - } - mStyleContextHolder = dont_AddRef(sctx); // transfer ref from sctx + mStyleContextHolder = + nsInspectorCSSUtils::GetStyleContextForContent(mContent, + mPseudo, + presShell); + if (mStyleContextHolder) { + aStyleStruct = mStyleContextHolder->GetStyleData(aID); } } NS_ASSERTION(aStyleStruct, "Failed to get a style struct"); diff --git a/layout/style/nsInspectorCSSUtils.cpp b/layout/style/nsInspectorCSSUtils.cpp index 20771ec20a6c..fdf7e62c5886 100644 --- a/layout/style/nsInspectorCSSUtils.cpp +++ b/layout/style/nsInspectorCSSUtils.cpp @@ -117,6 +117,7 @@ nsInspectorCSSUtils::AdjustRectForMargins(nsIFrame* aFrame, nsRect& aRect) return NS_OK; } +/* static */ nsStyleContext* nsInspectorCSSUtils::GetStyleContextForFrame(nsIFrame* aFrame) { @@ -135,25 +136,30 @@ nsInspectorCSSUtils::GetStyleContextForFrame(nsIFrame* aFrame) return styleContext; } +/* static */ already_AddRefed nsInspectorCSSUtils::GetStyleContextForContent(nsIContent* aContent, + nsIAtom* aPseudo, nsIPresShell* aPresShell) { - nsIFrame* frame = nsnull; - aPresShell->GetPrimaryFrameFor(aContent, &frame); - if (frame) { - nsStyleContext* result = GetStyleContextForFrame(frame); - // this function returns an addrefed style context - if (result) - result->AddRef(); - return result; + if (!aPseudo) { + nsIFrame* frame = nsnull; + aPresShell->GetPrimaryFrameFor(aContent, &frame); + if (frame) { + nsStyleContext* result = GetStyleContextForFrame(frame); + // this function returns an addrefed style context + if (result) + result->AddRef(); + return result; + } } - // No frame has been created, so resolve the style ourselves + // No frame has been created or we have a pseudo, so resolve the + // style ourselves nsRefPtr parentContext; - nsCOMPtr parent = aContent->GetParent(); + nsIContent* parent = aPseudo ? aContent : aContent->GetParent(); if (parent) - parentContext = GetStyleContextForContent(parent, aPresShell); + parentContext = GetStyleContextForContent(parent, nsnull, aPresShell); nsCOMPtr presContext; aPresShell->GetPresContext(getter_AddRefs(presContext)); @@ -162,10 +168,16 @@ nsInspectorCSSUtils::GetStyleContextForContent(nsIContent* aContent, nsStyleSet *styleSet = aPresShell->StyleSet(); - if (aContent->IsContentOfType(nsIContent::eELEMENT)) - return styleSet->ResolveStyleFor(aContent, parentContext); + if (!aContent->IsContentOfType(nsIContent::eELEMENT)) { + NS_ASSERTION(!aPseudo, "Shouldn't have a pseudo for a non-element!"); + return styleSet->ResolveStyleForNonElement(parentContext); + } - return styleSet->ResolveStyleForNonElement(parentContext); + if (aPseudo) { + return styleSet->ResolvePseudoStyleFor(aContent, aPseudo, parentContext); + } + + return styleSet->ResolveStyleFor(aContent, parentContext); } NS_IMETHODIMP @@ -181,7 +193,7 @@ nsInspectorCSSUtils::GetRuleNodeForContent(nsIContent* aContent, NS_ENSURE_TRUE(presShell, NS_ERROR_UNEXPECTED); nsRefPtr sContext = - GetStyleContextForContent(aContent, presShell); + GetStyleContextForContent(aContent, nsnull, presShell); *aRuleNode = sContext->GetRuleNode(); return NS_OK; } diff --git a/layout/style/nsInspectorCSSUtils.h b/layout/style/nsInspectorCSSUtils.h index 65158b2b7a35..207a04bc5cf0 100644 --- a/layout/style/nsInspectorCSSUtils.h +++ b/layout/style/nsInspectorCSSUtils.h @@ -63,12 +63,12 @@ public: NS_IMETHOD AdjustRectForMargins(nsIFrame* aFrame, nsRect& aRect); NS_IMETHOD GetRuleNodeForContent(nsIContent* aContent, nsRuleNode** aRuleNode); + static already_AddRefed + GetStyleContextForContent(nsIContent* aContent, nsIAtom* aPseudo, + nsIPresShell* aPresShell); private: - already_AddRefed - GetStyleContextForContent(nsIContent* aContent, nsIPresShell* aPresShell); - - nsStyleContext* GetStyleContextForFrame(nsIFrame* aFrame); + static nsStyleContext* GetStyleContextForFrame(nsIFrame* aFrame); }; #endif /* nsInspectorCSSUtils_h___ */ diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index d621b2937f55..279ddb5590ac 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -3236,20 +3236,25 @@ nsRuleNode::ComputeBorderData(nsStyleStruct* aStartStruct, FOR_CSS_SIDES(side) { const nsCSSValue &value = ourBorderColor.*(nsCSSRect::sides[side]); if (eCSSUnit_Inherit == value.GetUnit()) { - inherited = PR_TRUE; - parentBorder->GetBorderColor(side, borderColor, - transparent, foreground); - if (transparent) - border->SetBorderTransparent(side); - else if (foreground) { - // We want to inherit the color from the parent, not use the - // color on the element where this chunk of style data will be - // used. We can ensure that the data for the parent are fully - // computed (unlike for the element where this will be used, for - // which the color could be specified on a more specific rule). - border->SetBorderColor(side, parentContext->GetStyleColor()->mColor); - } else - border->SetBorderColor(side, borderColor); + if (parentContext) { + inherited = PR_TRUE; + parentBorder->GetBorderColor(side, borderColor, + transparent, foreground); + if (transparent) + border->SetBorderTransparent(side); + else if (foreground) { + // We want to inherit the color from the parent, not use the + // color on the element where this chunk of style data will be + // used. We can ensure that the data for the parent are fully + // computed (unlike for the element where this will be used, for + // which the color could be specified on a more specific rule). + border->SetBorderColor(side, parentContext->GetStyleColor()->mColor); + } else + border->SetBorderColor(side, borderColor); + } else { + // We're the root + border->SetBorderToForeground(side); + } } else if (SetColor(value, unused, mPresContext, borderColor, inherited)) { border->SetBorderColor(side, borderColor);