From 0b4effd4eaa6441e94f0b73a4dc007debccbe966 Mon Sep 17 00:00:00 2001 From: "dbaron%fas.harvard.edu" Date: Wed, 27 Mar 2002 02:38:13 +0000 Subject: [PATCH] Fix 2 cases where ReResolveStyleContext was broken, causing serious problems with dynamic style reresolution. Change nsIFrame::GetStyleContextProvider to GetParentStyleContextFrame, always use its result rather than using the parent frame in some cases, and move a bit of the complexity into the GetParentStyleContextFrame implementations. Fix block-within-inline case (bug 129350) using a special-previous-sibling frame property and ensuring that NS_FRAME_IS_SPECIAL is copied when frames are split. Fix out-of-flow frame case (bug 88154) by going to the placeholder map and by parenting the placeholder frame style contexts to the style context from their frame parent rather than the out-of-flow frame. b=129350 r=attinasi sr=hyatt a=asa git-svn-id: svn://10.0.0.236/trunk@117556 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsStyleSet.cpp | 4 +- .../content/html/content/src/nsHTMLAtomList.h | 1 + .../content/shared/public/nsHTMLAtomList.h | 1 + .../content/shared/public/nsLayoutAtomList.h | 3 +- mozilla/layout/base/nsCSSFrameConstructor.cpp | 72 +++++-- mozilla/layout/base/nsFrameManager.cpp | 186 +++++++----------- mozilla/layout/base/nsLayoutAtomList.h | 3 +- mozilla/layout/base/public/nsIFrame.h | 22 ++- mozilla/layout/generic/nsFrame.cpp | 118 ++++++++--- mozilla/layout/generic/nsFrame.h | 17 +- mozilla/layout/generic/nsIFrame.h | 22 ++- mozilla/layout/generic/nsSplittableFrame.cpp | 13 -- mozilla/layout/html/base/src/nsFrame.cpp | 118 ++++++++--- mozilla/layout/html/base/src/nsFrame.h | 17 +- .../layout/html/base/src/nsFrameManager.cpp | 186 +++++++----------- .../html/base/src/nsSplittableFrame.cpp | 13 -- .../html/style/src/nsCSSFrameConstructor.cpp | 72 +++++-- .../layout/html/table/src/nsTableFrame.cpp | 13 ++ mozilla/layout/html/table/src/nsTableFrame.h | 4 + .../html/table/src/nsTableOuterFrame.cpp | 32 +-- .../layout/html/table/src/nsTableOuterFrame.h | 5 +- mozilla/layout/style/nsStyleSet.cpp | 4 +- mozilla/layout/tables/nsTableFrame.cpp | 13 ++ mozilla/layout/tables/nsTableFrame.h | 4 + mozilla/layout/tables/nsTableOuterFrame.cpp | 32 +-- mozilla/layout/tables/nsTableOuterFrame.h | 5 +- 26 files changed, 606 insertions(+), 374 deletions(-) diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index 694bffd8c6f..51079f24435 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -58,6 +58,7 @@ #include "nsRuleWalker.h" #include "nsIHTMLDocument.h" #include "nsIDOMHTMLBodyElement.h" +#include "nsHTMLAtoms.h" #ifdef MOZ_PERF_METRICS #include "nsITimeRecorder.h" @@ -1109,7 +1110,8 @@ nsIStyleContext* StyleSetImpl::ResolveStyleForNonElement( mDocRuleProcessors || mOverrideRuleProcessors) { EnsureRuleWalker(aPresContext); - result = GetContext(aPresContext, aParentContext, nsnull, aForceUnique); + result = GetContext(aPresContext, aParentContext, + nsHTMLAtoms::mozNonElementPseudo, aForceUnique); NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root"); } } diff --git a/mozilla/content/html/content/src/nsHTMLAtomList.h b/mozilla/content/html/content/src/nsHTMLAtomList.h index 83289a1949b..d960cf90210 100644 --- a/mozilla/content/html/content/src/nsHTMLAtomList.h +++ b/mozilla/content/html/content/src/nsHTMLAtomList.h @@ -58,6 +58,7 @@ HTML_ATOM(mozFirstLineFixup, ":-moz-first-line-fixup") HTML_ATOM(mozLineFrame, ":-moz-line-frame") HTML_ATOM(mozListBulletPseudo, ":-moz-list-bullet") HTML_ATOM(mozListNumberPseudo, ":-moz-list-number") +HTML_ATOM(mozNonElementPseudo, ":-moz-non-element") HTML_ATOM(mozSingleLineTextControlFrame, ":-moz-singleline-textcontrol-frame") HTML_ATOM(mozFocusInnerPseudo, ":-moz-focus-inner") HTML_ATOM(mozFocusOuterPseudo, ":-moz-focus-outer") diff --git a/mozilla/content/shared/public/nsHTMLAtomList.h b/mozilla/content/shared/public/nsHTMLAtomList.h index 83289a1949b..d960cf90210 100644 --- a/mozilla/content/shared/public/nsHTMLAtomList.h +++ b/mozilla/content/shared/public/nsHTMLAtomList.h @@ -58,6 +58,7 @@ HTML_ATOM(mozFirstLineFixup, ":-moz-first-line-fixup") HTML_ATOM(mozLineFrame, ":-moz-line-frame") HTML_ATOM(mozListBulletPseudo, ":-moz-list-bullet") HTML_ATOM(mozListNumberPseudo, ":-moz-list-number") +HTML_ATOM(mozNonElementPseudo, ":-moz-non-element") HTML_ATOM(mozSingleLineTextControlFrame, ":-moz-singleline-textcontrol-frame") HTML_ATOM(mozFocusInnerPseudo, ":-moz-focus-inner") HTML_ATOM(mozFocusOuterPseudo, ":-moz-focus-outer") diff --git a/mozilla/content/shared/public/nsLayoutAtomList.h b/mozilla/content/shared/public/nsLayoutAtomList.h index da4ee21d396..3fb7ad63517 100644 --- a/mozilla/content/shared/public/nsLayoutAtomList.h +++ b/mozilla/content/shared/public/nsLayoutAtomList.h @@ -139,7 +139,8 @@ LAYOUT_ATOM(viewportFrame, "ViewportFrame") // Alphabetical list of frame property names LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* -LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL +LAYOUT_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame* +LAYOUT_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame* LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize* LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 91c09b7fee8..3122e75c47a 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -384,7 +384,7 @@ GetSpecialSibling(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame** a } void* value; - aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation, 0, &value); + aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::IBSplitSpecialSibling, 0, &value); *aResult = NS_STATIC_CAST(nsIFrame*, value); } @@ -412,7 +412,8 @@ SetFrameIsSpecial(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame* aS // Store the "special sibling" (if we were given one) with the // first frame in the flow. - aFrameManager->SetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation, + aFrameManager->SetFrameProperty(aFrame, + nsLayoutAtoms::IBSplitSpecialSibling, aSpecialSibling, nsnull); } } @@ -492,10 +493,7 @@ IsBlockFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) // don't we use display->IsBlockLevel() here? const nsStyleDisplay* display; aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); - if (NS_STYLE_DISPLAY_INLINE == display->mDisplay) { - return PR_FALSE; - } - return PR_TRUE; + return NS_STYLE_DISPLAY_INLINE != display->mDisplay; } static nsIFrame* @@ -527,6 +525,27 @@ FindLastBlock(nsIPresContext* aPresContext, nsIFrame* aKid) return lastBlock; } +/* + * Unlike the special (next) sibling, the special previous sibling + * property points only from the anonymous block to the original inline + * that preceded it. It is useful for finding the "special parent" of a + * frame (i.e., a frame from which a good parent style context can be + * obtained), one looks at the special previous sibling annotation of + * the real parent of the frame (if the real parent has + * NS_FRAME_IS_SPECIAL). + */ +inline void +MarkIBSpecialPrevSibling(nsIPresContext* aPresContext, + nsIFrameManager *aFrameManager, + nsIFrame *aAnonymousFrame, + nsIFrame *aSpecialParent) +{ + aFrameManager->SetFrameProperty(aAnonymousFrame, + nsLayoutAtoms::IBSplitSpecialPrevSibling, + aSpecialParent, + nsnull); +} + /** * Moves frames to a new parent, updating the style context and * propagating relevant frame state bits. |aNewParentSC| may be null, @@ -3803,7 +3822,9 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell, if (NS_SUCCEEDED(rv)) { // The placeholder frame gets a pseudo style context nsCOMPtr placeholderStyle; - aPresContext->ResolveStyleContextForNonElement(aStyleContext, PR_FALSE, + nsCOMPtr parentContext = + dont_AddRef(aStyleContext->GetParent()); + aPresContext->ResolveStyleContextForNonElement(parentContext, PR_FALSE, getter_AddRefs(placeholderStyle)); placeholderFrame->Init(aPresContext, aContent, aParentFrame, placeholderStyle, nsnull); @@ -9231,15 +9252,18 @@ DeletingFrameSubtree(nsIPresContext* aPresContext, if (aFrameManager) { nsAutoVoidArray destroyQueue; - while (aFrame) { - // If it's a "special" block-in-inline frame, then we need to - // remember to delete our special siblings, too. - if (IsFrameSpecial(aFrame)) { - nsIFrame* specialSibling; - GetSpecialSibling(aFrameManager, aFrame, &specialSibling); - DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, specialSibling); - } + // If it's a "special" block-in-inline frame, then we need to + // remember to delete our special siblings, too. Since every one of + // the next-in-flows has the same special sibling, just do this + // once, rather than in the loop below. + if (IsFrameSpecial(aFrame)) { + nsIFrame* specialSibling; + GetSpecialSibling(aFrameManager, aFrame, &specialSibling); + DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, + specialSibling); + } + while (aFrame) { DoDeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, destroyQueue, aFrame, aFrame); @@ -10483,9 +10507,15 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, nsIFrame* primaryFrame; shell->GetPrimaryFrameFor(aContent, &primaryFrame); // Get the frame associated with the content whose style context is highest in the style context tree - nsIFrame* primaryStyleFrame = nsnull; + nsIFrame* primaryStyleFrame = primaryFrame; if (primaryFrame) { - primaryFrame->GetStyleContextProvider(aPresContext, &primaryStyleFrame); + PRBool providerIsChild = PR_FALSE; + nsIFrame *styleContextProvider; + primaryFrame->GetParentStyleContextFrame(aPresContext, + &styleContextProvider, + &providerIsChild); + if (providerIsChild) + primaryStyleFrame = styleContextProvider; } PRBool reconstruct = PR_FALSE; @@ -11220,6 +11250,8 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell, lastBlock->SetNextSibling(nsnull); // Create "special" inline-block linkage between the frames + // XXXldb Do we really need to do this? It doesn't seem + // consistent with the use in ConstructInline. SetFrameIsSpecial(state.mFrameManager, list1, list2); SetFrameIsSpecial(state.mFrameManager, list2, list3); SetFrameIsSpecial(state.mFrameManager, list3, nsnull); @@ -13742,6 +13774,8 @@ nsCSSFrameConstructor::ConstructInline(nsIPresShell* aPresShell, // containing block will be reframed instead. SetFrameIsSpecial(aState.mFrameManager, aNewFrame, blockFrame); SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame); + MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager, + blockFrame, aNewFrame); if (inlineFrame) SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull); @@ -14169,6 +14203,7 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext, // Create an anonymous inline frame that will parent // aRightInlineChildFrame. The new frame won't have a parent yet: // the recursion will parent it. + // XXXldb Why bother if |aRightInlineChildFrame| is null? nsIFrame* inlineFrame = nsnull; NS_NewInlineFrame(shell, &inlineFrame); if (! inlineFrame) @@ -14196,6 +14231,9 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext, SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame); SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull); + MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager, + blockFrame, firstInFlow); + // If we have a continuation frame, then we need to break the // continuation. nsIFrame* nextInFlow; diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index 78509225b8d..6722328e9a5 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -417,7 +417,6 @@ private: void ReResolveStyleContext(nsIPresContext* aPresContext, nsIFrame* aFrame, - nsIStyleContext* aParentContext, nsIContent* aParentContent, PRInt32 aAttrNameSpaceID, nsIAtom* aAttribute, @@ -1275,8 +1274,6 @@ static void VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext* aContext, nsIStyleContext* aParentContext) { - nsIAtom* frameType; - // get the contexts not provided if (!aContext) { aFrame->GetStyleContext(&aContext); @@ -1289,24 +1286,15 @@ VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame, // Get the correct parent context from the frame // - if the frame is a placeholder, we get the out of flow frame's context // as the parent context instead of asking the frame - aFrame->GetFrameType(&frameType); - if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder - // get out of flow frame's context as the parent context - nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)aFrame)->GetOutOfFlowFrame(); - NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); - outOfFlowFrame->GetStyleContext(&aParentContext); - } else { - // get the parent context from the frame (indirectly) - nsIFrame* providerFrame = nsnull; - aFrame->GetStyleContextProvider(aPresContext, &providerFrame); - ENSURE_TRUE(providerFrame); - nsCOMPtr providerContext; - providerFrame->GetStyleContext(getter_AddRefs(providerContext)); - ENSURE_TRUE(providerContext); - aParentContext = providerContext->GetParent(); // released later - // aParentContext could still be null, since some contexts don't have parents - } - NS_IF_RELEASE(frameType); + + // get the parent context from the frame (indirectly) + nsIFrame* providerFrame = nsnull; + PRBool providerIsChild; + aFrame->GetParentStyleContextFrame(aPresContext, + &providerFrame, &providerIsChild); + if (providerFrame) + providerFrame->GetStyleContext(&aParentContext); + // aParentContext could still be null } else { // addref the parent context so we can release it at end NS_ADDREF(aParentContext); @@ -1351,7 +1339,7 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext* nsIStyleContext* context; aFrame->GetStyleContext(&context); - VerifyContextParent(aPresContext, aFrame, context, aParentContext); + VerifyContextParent(aPresContext, aFrame, context, nsnull); PRInt32 listIndex = 0; nsIAtom* childList = nsnull; @@ -1372,15 +1360,13 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext* // then verify the placeholder's context nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame(); NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); - nsIStyleContext* outOfFlowContext; // recurse to out of flow frame, letting the parent context get resolved VerifyStyleTree(aPresContext, outOfFlowFrame, nsnull); - // verify placeholder using the out of flow's context as parent context - outOfFlowFrame->GetStyleContext(&outOfFlowContext); - VerifyContextParent(aPresContext,child, nsnull, outOfFlowContext); - NS_IF_RELEASE(outOfFlowContext); + // verify placeholder using the parent frame's context as + // parent context + VerifyContextParent(aPresContext, child, nsnull, nsnull); } else { // regular frame VerifyStyleTree(aPresContext, child, nsnull); @@ -1585,7 +1571,6 @@ CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext, void FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, nsIFrame* aFrame, - nsIStyleContext* aParentContextIn, nsIContent* aParentContent, PRInt32 aAttrNameSpaceID, nsIAtom* aAttribute, @@ -1620,73 +1605,51 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, } nsCOMPtr parentContext; - nsIFrame* resolvedDescendant = nsnull; - // Get the frame providing the style context. If it differs from aFrame, then - // reslove the provider first, since the provider's context is the parent of aFrame's + nsIFrame* resolvedChild = nsnull; + // Get the frame providing the parent style context. If it is a + // child, then resolve the provider first. nsIFrame* providerFrame = nsnull; - aFrame->GetStyleContextProvider(aPresContext, &providerFrame); - ENSURE_TRUE(providerFrame); - if (providerFrame == aFrame) { - if (aParentContextIn) { - parentContext = aParentContextIn; - NOISY_TRACE_FRAME("non-null parent context provided: using it and assuming already resolved",aFrame); - } else { - nsIFrame* parentFrame; - aFrame->GetParent(&parentFrame); - if (parentFrame) { - parentFrame->GetStyleContext(getter_AddRefs(parentContext)); - } - } + PRBool providerIsChild = PR_FALSE; + aFrame->GetParentStyleContextFrame(aPresContext, + &providerFrame, &providerIsChild); + if (!providerIsChild) { + if (providerFrame) + providerFrame->GetStyleContext(getter_AddRefs(parentContext)); } else { -#ifdef DEBUG - // check to make sure that the provider is the child of aFrame - nsIFrame* providerFrameParent; - providerFrame->GetParent(&providerFrameParent); - NS_ASSERTION(providerFrameParent == aFrame, "invalid style context provider"); -#endif // resolve the provider here (before aFrame below) - nsCOMPtr providerContextParent; - nsIFrame* grandParentFrame; - aFrame->GetParent(&grandParentFrame); - if (grandParentFrame) { - grandParentFrame->GetStyleContext(getter_AddRefs(providerContextParent)); - } - ReResolveStyleContext(aPresContext, providerFrame, providerContextParent, content, - aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, aResultChange); - // the provider's new context becomes the parent context of aFrame's context + ReResolveStyleContext(aPresContext, providerFrame, content, + aAttrNameSpaceID, aAttribute, aChangeList, + aMinChange, aResultChange); + // The provider's new context becomes the parent context of + // aFrame's context. providerFrame->GetStyleContext(getter_AddRefs(parentContext)); - resolvedDescendant = providerFrame; // don't want to re-resolve the provider again + // Set |resolvedChild| so we don't bother resolving the + // provider again. + resolvedChild = providerFrame; } // do primary context nsIStyleContext* newContext = nsnull; - if (pseudoTag) { - nsIContent* pseudoContent = (aParentContent) ? aParentContent : localContent; - aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, parentContext, + if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) { + NS_ASSERTION(localContent, + "non pseudo-element frame without content node"); + aPresContext->ResolveStyleContextForNonElement(parentContext, + PR_TRUE, &newContext); + } + else if (pseudoTag) { + nsIContent* pseudoContent = + aParentContent ? aParentContent : localContent; + aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, + parentContext, PR_FALSE, &newContext); NS_RELEASE(pseudoTag); } else { NS_ASSERTION(localContent, "non pseudo-element frame without content node"); - // XXX This frame type check is a little ugly. However, it should - // be cheaper than doing useless style resolution on placeholder - // frames, and it should be able to go away if we make it so that - // placeholder frames don't have style contexts at all. - // - // XXX We also probably need to descend into the style contexts of - // the placeholder's out-of-flow frame. - nsCOMPtr frameType; - aFrame->GetFrameType(getter_AddRefs(frameType)); - if (content->IsContentOfType(nsIContent::eELEMENT) && - frameType != nsLayoutAtoms::placeholderFrame) { - aPresContext->ResolveStyleContextFor(content, parentContext, - PR_TRUE, &newContext); - } else { - aPresContext->ResolveStyleContextForNonElement(parentContext, - PR_TRUE, &newContext); - } + aPresContext->ResolveStyleContextFor(content, parentContext, + PR_TRUE, &newContext); } NS_ASSERTION(newContext, "failed to get new style context"); if (newContext) { @@ -1730,7 +1693,9 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (oldExtraContext) { nsIStyleContext* newExtraContext = nsnull; oldExtraContext->GetPseudoType(pseudoTag); - NS_ASSERTION(pseudoTag, "extra style context is not pseudo element"); + NS_ASSERTION(pseudoTag && + pseudoTag != nsHTMLAtoms::mozNonElementPseudo, + "extra style context is not pseudo element"); result = aPresContext->ResolvePseudoStyleContextFor(content, pseudoTag, newContext, PR_FALSE, &newExtraContext); NS_RELEASE(pseudoTag); @@ -1770,6 +1735,10 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, aPresContext->ResolveStyleContextFor(undisplayed->mContent, newContext, PR_TRUE, &undisplayedContext); } + else if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) { + aPresContext->ResolveStyleContextForNonElement(newContext, + PR_TRUE, &undisplayedContext); + } else { // pseudo element NS_ASSERTION(pseudoTag, "pseudo element without tag"); aPresContext->ResolvePseudoStyleContextFor(localContent, pseudoTag, newContext, PR_FALSE, @@ -1786,8 +1755,12 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (display->mDisplay != NS_STYLE_DISPLAY_NONE) { aChangeList.AppendChange(nsnull, ((undisplayed->mContent) ? undisplayed->mContent : localContent), NS_STYLE_HINT_FRAMECHANGE); + NS_RELEASE(undisplayedContext); + } else { + // update the undisplayed node with the new context + NS_RELEASE(undisplayed->mStyle); + undisplayed->mStyle = undisplayedContext; } - NS_RELEASE(undisplayedContext); } undisplayed = undisplayed->mNext; } @@ -1805,42 +1778,40 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, PRInt32 listIndex = 0; nsIAtom* childList = nsnull; PRInt32 childChange; - nsIFrame* child; do { - child = nsnull; + nsIFrame* child = nsnull; result = aFrame->FirstChild(aPresContext, childList, &child); - while ((NS_SUCCEEDED(result)) && (child)) { + while (NS_SUCCEEDED(result) && child) { nsFrameState state; child->GetFrameState(&state); - if (NS_FRAME_OUT_OF_FLOW != (state & NS_FRAME_OUT_OF_FLOW)) { + if (!(state & NS_FRAME_OUT_OF_FLOW)) { // only do frames that are in flow nsCOMPtr frameType; child->GetFrameType(getter_AddRefs(frameType)); - if (nsLayoutAtoms::placeholderFrame == frameType.get()) { // placeholder - // get out of flow frame and recurse there - nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame(); + if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder + // get out of flow frame and recur there + nsIFrame* outOfFlowFrame = + NS_STATIC_CAST(nsPlaceholderFrame*,child)->GetOutOfFlowFrame(); NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); + NS_ASSERTION(outOfFlowFrame != resolvedChild, + "out-of-flow frame not a true descendant"); - if (outOfFlowFrame != resolvedDescendant) { - ReResolveStyleContext(aPresContext, outOfFlowFrame, nsnull, content, - aAttrNameSpaceID, aAttribute, - aChangeList, aMinChange, childChange); - } else { - NOISY_TRACE("out of flow frame already resolved as descendent\n"); - } + // |nsFrame::GetParentStyleContextFrame| checks being out + // of flow so that this works correctly. + ReResolveStyleContext(aPresContext, outOfFlowFrame, content, + aAttrNameSpaceID, aAttribute, + aChangeList, aMinChange, childChange); - // reresolve placeholder's context under out of flow frame - nsIStyleContext* outOfFlowContext; - outOfFlowFrame->GetStyleContext(&outOfFlowContext); - ReResolveStyleContext(aPresContext, child, outOfFlowContext, content, + // reresolve placeholder's context under the same parent + // as the out-of-flow frame + ReResolveStyleContext(aPresContext, child, content, kNameSpaceID_Unknown, nsnull, aChangeList, aMinChange, childChange); - NS_RELEASE(outOfFlowContext); } else { // regular child frame - if (child != resolvedDescendant) { - ReResolveStyleContext(aPresContext, child, nsnull, content, + if (child != resolvedChild) { + ReResolveStyleContext(aPresContext, child, content, aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, childChange); } else { @@ -1884,18 +1855,13 @@ FrameManager::ComputeStyleChangeFor(nsIPresContext* aPresContext, #endif do { - nsIStyleContext* styleContext = nsnull; - frame->GetStyleContext(&styleContext); - nsIStyleContext* parentContext = styleContext->GetParent(); PRInt32 frameChange; - ReResolveStyleContext(aPresContext, frame, parentContext, nsnull, + ReResolveStyleContext(aPresContext, frame, nsnull, aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, frameChange); #ifdef NS_DEBUG - VerifyStyleTree(aPresContext, frame, parentContext); + VerifyStyleTree(aPresContext, frame, nsnull); #endif - NS_IF_RELEASE(parentContext); - NS_RELEASE(styleContext); if (aTopLevelChange < frameChange) { aTopLevelChange = frameChange; } diff --git a/mozilla/layout/base/nsLayoutAtomList.h b/mozilla/layout/base/nsLayoutAtomList.h index da4ee21d396..3fb7ad63517 100644 --- a/mozilla/layout/base/nsLayoutAtomList.h +++ b/mozilla/layout/base/nsLayoutAtomList.h @@ -139,7 +139,8 @@ LAYOUT_ATOM(viewportFrame, "ViewportFrame") // Alphabetical list of frame property names LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint* -LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL +LAYOUT_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame* +LAYOUT_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame* LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize* LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect* LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame* diff --git a/mozilla/layout/base/public/nsIFrame.h b/mozilla/layout/base/public/nsIFrame.h index 4a82a165182..b8c0a5ea433 100644 --- a/mozilla/layout/base/public/nsIFrame.h +++ b/mozilla/layout/base/public/nsIFrame.h @@ -1091,15 +1091,25 @@ public: PRBool aCommandAdded) = 0; /** - * Get the frame that is the primary frame associated with the content. - * aProviderFrame == this except in the case of an outer table, in - * which case it is the inner table. + * Get the frame whose style context should be the parent of this + * frame's style context (i.e., provide the parent style context). + * This frame must either be an ancestor of this frame or a child. If + * this frame returns a child frame, then the child frame must be sure + * to return a grandparent or higher! * * @param aPresContext: PresContext - * @param aProviderFrame: Set to the primary frame associated with the content + * @param aProviderFrame: The frame whose style context should be the + * parent of this frame's style context. Null + * is permitted, and means that this frame's + * style context should be the root of the + * style context tree. + * @param aIsChild: True if |aProviderFrame| is set to a child + * of this frame; false if it is an ancestor or + * null. */ - NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame) = 0; + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) = 0; /** * Determines whether a frame is visible for painting diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index e04c1561a9a..87999f68d0b 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -336,33 +336,28 @@ nsFrame::Init(nsIPresContext* aPresContext, mContent = aContent; NS_IF_ADDREF(mContent); mParent = aParent; - nsFrameState state; if (aPrevInFlow) { // Make sure the general flags bits are the same + nsFrameState state; aPrevInFlow->GetFrameState(&state); - if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) { - mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - } - if (state & NS_FRAME_REPLACED_ELEMENT) { - mState |= NS_FRAME_REPLACED_ELEMENT; - } - if (state & NS_FRAME_SELECTED_CONTENT) { - mState |= NS_FRAME_SELECTED_CONTENT; - } - if (state & NS_FRAME_INDEPENDENT_SELECTION) { - mState |= NS_FRAME_INDEPENDENT_SELECTION; - } + + // Make bits that are currently on (see constructor) the same: + mState &= state | ~(NS_FRAME_SYNC_FRAME_AND_VIEW); + + // Make bits that are currently off (see constructor) the same: + mState |= state & (NS_FRAME_REPLACED_ELEMENT | + NS_FRAME_SELECTED_CONTENT | + NS_FRAME_INDEPENDENT_SELECTION | + NS_FRAME_IS_SPECIAL); } - if(mParent) - { + if (mParent) { + nsFrameState state; mParent->GetFrameState(&state); - if (state & NS_FRAME_INDEPENDENT_SELECTION) { - mState |= NS_FRAME_INDEPENDENT_SELECTION; - } - if (state & NS_FRAME_GENERATED_CONTENT){ - mState |= NS_FRAME_GENERATED_CONTENT; - } + + // Make bits that are currently off (see constructor) the same: + mState |= state & (NS_FRAME_INDEPENDENT_SELECTION | + NS_FRAME_GENERATED_CONTENT); } return SetStyleContext(aPresContext, aContext); } @@ -4006,10 +4001,85 @@ nsFrame::ReflowCommandNotify(nsIPresShell* aShell, } NS_IMETHODIMP -nsFrame::GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame) +nsFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) { - *aProviderFrame = this; + return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild); +} + +nsresult +nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) +{ + *aIsChild = PR_FALSE; + if (!(mState & NS_FRAME_OUT_OF_FLOW)) { + // If this frame is one of the blocks that split an inline, we must + // return the "special" inline parent, i.e., the parent that this + // frame would have if we didn't mangle the frame structure. + return GetIBSpecialParent(aPresContext, aProviderFrame); + } + + // For out-of-flow frames, we must resolve underneath the + // placeholder's parent. + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + nsIFrame *placeholder; + frameManager->GetPlaceholderFrameFor(this, &placeholder); + if (!placeholder) { + NS_NOTREACHED("no placeholder frame for out-of-flow frame"); + GetIBSpecialParent(aPresContext, aProviderFrame); + return NS_ERROR_FAILURE; + } + return NS_STATIC_CAST(nsFrame*, placeholder)->GetParent(aProviderFrame); +} + +/** + * Get the parent, corrected for the mangled frame tree resulting from + * having a block within an inline. The result only differs from the + * result of |GetParent| when |GetParent| returns an anonymous block + * that was created for an element that was 'display: inline' because + * that element contained a block. + */ +nsresult +nsFrame::GetIBSpecialParent(nsIPresContext* aPresContext, + nsIFrame** aSpecialParent) +{ + *aSpecialParent = mParent; + if (mParent) { + nsFrameState parentState; + mParent->GetFrameState(&parentState); + if (parentState & NS_FRAME_IS_SPECIAL) { + // Find the first-in-flow of the parent. (Ugh. This ends up + // being O(N^2) when it is called O(N) times.) + nsIFrame *parentFIF = mParent; + for (;;) { + nsIFrame *prevInFlow; + parentFIF->GetPrevInFlow(&prevInFlow); + if (!prevInFlow) + break; + parentFIF = prevInFlow; + } + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + nsIFrame *specialParent; + nsresult rv = + frameManager->GetFrameProperty(parentFIF, + nsLayoutAtoms::IBSplitSpecialPrevSibling, + 0, (void**)&specialParent); + if (NS_OK == rv) { + NS_ASSERTION(specialParent, "null special parent"); + *aSpecialParent = specialParent; + } + } + } + return NS_OK; } diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h index 4261ba22558..46b4b44e0aa 100644 --- a/mozilla/layout/generic/nsFrame.h +++ b/mozilla/layout/generic/nsFrame.h @@ -282,8 +282,9 @@ public: NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); #endif - NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame); + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); // Check Style Visibility and mState for Selection (when printing) NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, @@ -375,6 +376,18 @@ public: nsIAtom* aAttribute, nsIAtom* aListName); + // Do the work for getting the parent style context frame so that + // other frame's |GetParentStyleContextFrame| methods can call this + // method on *another* frame. (This function handles out-of-flow + // frames by using the frame manager's placeholder map and it handles + // block-within-inline by calling |GetIBSpecialParent|.) + nsresult DoGetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); + + nsresult GetIBSpecialParent(nsIPresContext* aPresContext, + nsIFrame** aSpecialParent); + //Mouse Capturing code used by the frames to tell the view to capture all the following events NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents); PRBool IsMouseCaptured(nsIPresContext* aPresContext); diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index 4a82a165182..b8c0a5ea433 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -1091,15 +1091,25 @@ public: PRBool aCommandAdded) = 0; /** - * Get the frame that is the primary frame associated with the content. - * aProviderFrame == this except in the case of an outer table, in - * which case it is the inner table. + * Get the frame whose style context should be the parent of this + * frame's style context (i.e., provide the parent style context). + * This frame must either be an ancestor of this frame or a child. If + * this frame returns a child frame, then the child frame must be sure + * to return a grandparent or higher! * * @param aPresContext: PresContext - * @param aProviderFrame: Set to the primary frame associated with the content + * @param aProviderFrame: The frame whose style context should be the + * parent of this frame's style context. Null + * is permitted, and means that this frame's + * style context should be the root of the + * style context tree. + * @param aIsChild: True if |aProviderFrame| is set to a child + * of this frame; false if it is an ancestor or + * null. */ - NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame) = 0; + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) = 0; /** * Determines whether a frame is visible for painting diff --git a/mozilla/layout/generic/nsSplittableFrame.cpp b/mozilla/layout/generic/nsSplittableFrame.cpp index 72ddb3f9b64..6c143c6795a 100644 --- a/mozilla/layout/generic/nsSplittableFrame.cpp +++ b/mozilla/layout/generic/nsSplittableFrame.cpp @@ -55,19 +55,6 @@ nsSplittableFrame::Init(nsIPresContext* aPresContext, // Hook the frame into the flow mPrevInFlow = aPrevInFlow; aPrevInFlow->SetNextInFlow(this); - - // Make sure the general flags bits are the same - nsFrameState state; - aPrevInFlow->GetFrameState(&state); - if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) { - mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - } - if (state & NS_FRAME_REPLACED_ELEMENT) { - mState |= NS_FRAME_REPLACED_ELEMENT; - } - if (state & NS_FRAME_SELECTED_CONTENT) { - mState |= NS_FRAME_SELECTED_CONTENT; - } } return rv; diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp index e04c1561a9a..87999f68d0b 100644 --- a/mozilla/layout/html/base/src/nsFrame.cpp +++ b/mozilla/layout/html/base/src/nsFrame.cpp @@ -336,33 +336,28 @@ nsFrame::Init(nsIPresContext* aPresContext, mContent = aContent; NS_IF_ADDREF(mContent); mParent = aParent; - nsFrameState state; if (aPrevInFlow) { // Make sure the general flags bits are the same + nsFrameState state; aPrevInFlow->GetFrameState(&state); - if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) { - mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - } - if (state & NS_FRAME_REPLACED_ELEMENT) { - mState |= NS_FRAME_REPLACED_ELEMENT; - } - if (state & NS_FRAME_SELECTED_CONTENT) { - mState |= NS_FRAME_SELECTED_CONTENT; - } - if (state & NS_FRAME_INDEPENDENT_SELECTION) { - mState |= NS_FRAME_INDEPENDENT_SELECTION; - } + + // Make bits that are currently on (see constructor) the same: + mState &= state | ~(NS_FRAME_SYNC_FRAME_AND_VIEW); + + // Make bits that are currently off (see constructor) the same: + mState |= state & (NS_FRAME_REPLACED_ELEMENT | + NS_FRAME_SELECTED_CONTENT | + NS_FRAME_INDEPENDENT_SELECTION | + NS_FRAME_IS_SPECIAL); } - if(mParent) - { + if (mParent) { + nsFrameState state; mParent->GetFrameState(&state); - if (state & NS_FRAME_INDEPENDENT_SELECTION) { - mState |= NS_FRAME_INDEPENDENT_SELECTION; - } - if (state & NS_FRAME_GENERATED_CONTENT){ - mState |= NS_FRAME_GENERATED_CONTENT; - } + + // Make bits that are currently off (see constructor) the same: + mState |= state & (NS_FRAME_INDEPENDENT_SELECTION | + NS_FRAME_GENERATED_CONTENT); } return SetStyleContext(aPresContext, aContext); } @@ -4006,10 +4001,85 @@ nsFrame::ReflowCommandNotify(nsIPresShell* aShell, } NS_IMETHODIMP -nsFrame::GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame) +nsFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) { - *aProviderFrame = this; + return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild); +} + +nsresult +nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) +{ + *aIsChild = PR_FALSE; + if (!(mState & NS_FRAME_OUT_OF_FLOW)) { + // If this frame is one of the blocks that split an inline, we must + // return the "special" inline parent, i.e., the parent that this + // frame would have if we didn't mangle the frame structure. + return GetIBSpecialParent(aPresContext, aProviderFrame); + } + + // For out-of-flow frames, we must resolve underneath the + // placeholder's parent. + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + nsIFrame *placeholder; + frameManager->GetPlaceholderFrameFor(this, &placeholder); + if (!placeholder) { + NS_NOTREACHED("no placeholder frame for out-of-flow frame"); + GetIBSpecialParent(aPresContext, aProviderFrame); + return NS_ERROR_FAILURE; + } + return NS_STATIC_CAST(nsFrame*, placeholder)->GetParent(aProviderFrame); +} + +/** + * Get the parent, corrected for the mangled frame tree resulting from + * having a block within an inline. The result only differs from the + * result of |GetParent| when |GetParent| returns an anonymous block + * that was created for an element that was 'display: inline' because + * that element contained a block. + */ +nsresult +nsFrame::GetIBSpecialParent(nsIPresContext* aPresContext, + nsIFrame** aSpecialParent) +{ + *aSpecialParent = mParent; + if (mParent) { + nsFrameState parentState; + mParent->GetFrameState(&parentState); + if (parentState & NS_FRAME_IS_SPECIAL) { + // Find the first-in-flow of the parent. (Ugh. This ends up + // being O(N^2) when it is called O(N) times.) + nsIFrame *parentFIF = mParent; + for (;;) { + nsIFrame *prevInFlow; + parentFIF->GetPrevInFlow(&prevInFlow); + if (!prevInFlow) + break; + parentFIF = prevInFlow; + } + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager)); + nsIFrame *specialParent; + nsresult rv = + frameManager->GetFrameProperty(parentFIF, + nsLayoutAtoms::IBSplitSpecialPrevSibling, + 0, (void**)&specialParent); + if (NS_OK == rv) { + NS_ASSERTION(specialParent, "null special parent"); + *aSpecialParent = specialParent; + } + } + } + return NS_OK; } diff --git a/mozilla/layout/html/base/src/nsFrame.h b/mozilla/layout/html/base/src/nsFrame.h index 4261ba22558..46b4b44e0aa 100644 --- a/mozilla/layout/html/base/src/nsFrame.h +++ b/mozilla/layout/html/base/src/nsFrame.h @@ -282,8 +282,9 @@ public: NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); #endif - NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame); + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); // Check Style Visibility and mState for Selection (when printing) NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, @@ -375,6 +376,18 @@ public: nsIAtom* aAttribute, nsIAtom* aListName); + // Do the work for getting the parent style context frame so that + // other frame's |GetParentStyleContextFrame| methods can call this + // method on *another* frame. (This function handles out-of-flow + // frames by using the frame manager's placeholder map and it handles + // block-within-inline by calling |GetIBSpecialParent|.) + nsresult DoGetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); + + nsresult GetIBSpecialParent(nsIPresContext* aPresContext, + nsIFrame** aSpecialParent); + //Mouse Capturing code used by the frames to tell the view to capture all the following events NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents); PRBool IsMouseCaptured(nsIPresContext* aPresContext); diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index 78509225b8d..6722328e9a5 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -417,7 +417,6 @@ private: void ReResolveStyleContext(nsIPresContext* aPresContext, nsIFrame* aFrame, - nsIStyleContext* aParentContext, nsIContent* aParentContent, PRInt32 aAttrNameSpaceID, nsIAtom* aAttribute, @@ -1275,8 +1274,6 @@ static void VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext* aContext, nsIStyleContext* aParentContext) { - nsIAtom* frameType; - // get the contexts not provided if (!aContext) { aFrame->GetStyleContext(&aContext); @@ -1289,24 +1286,15 @@ VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame, // Get the correct parent context from the frame // - if the frame is a placeholder, we get the out of flow frame's context // as the parent context instead of asking the frame - aFrame->GetFrameType(&frameType); - if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder - // get out of flow frame's context as the parent context - nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)aFrame)->GetOutOfFlowFrame(); - NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); - outOfFlowFrame->GetStyleContext(&aParentContext); - } else { - // get the parent context from the frame (indirectly) - nsIFrame* providerFrame = nsnull; - aFrame->GetStyleContextProvider(aPresContext, &providerFrame); - ENSURE_TRUE(providerFrame); - nsCOMPtr providerContext; - providerFrame->GetStyleContext(getter_AddRefs(providerContext)); - ENSURE_TRUE(providerContext); - aParentContext = providerContext->GetParent(); // released later - // aParentContext could still be null, since some contexts don't have parents - } - NS_IF_RELEASE(frameType); + + // get the parent context from the frame (indirectly) + nsIFrame* providerFrame = nsnull; + PRBool providerIsChild; + aFrame->GetParentStyleContextFrame(aPresContext, + &providerFrame, &providerIsChild); + if (providerFrame) + providerFrame->GetStyleContext(&aParentContext); + // aParentContext could still be null } else { // addref the parent context so we can release it at end NS_ADDREF(aParentContext); @@ -1351,7 +1339,7 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext* nsIStyleContext* context; aFrame->GetStyleContext(&context); - VerifyContextParent(aPresContext, aFrame, context, aParentContext); + VerifyContextParent(aPresContext, aFrame, context, nsnull); PRInt32 listIndex = 0; nsIAtom* childList = nsnull; @@ -1372,15 +1360,13 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext* // then verify the placeholder's context nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame(); NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); - nsIStyleContext* outOfFlowContext; // recurse to out of flow frame, letting the parent context get resolved VerifyStyleTree(aPresContext, outOfFlowFrame, nsnull); - // verify placeholder using the out of flow's context as parent context - outOfFlowFrame->GetStyleContext(&outOfFlowContext); - VerifyContextParent(aPresContext,child, nsnull, outOfFlowContext); - NS_IF_RELEASE(outOfFlowContext); + // verify placeholder using the parent frame's context as + // parent context + VerifyContextParent(aPresContext, child, nsnull, nsnull); } else { // regular frame VerifyStyleTree(aPresContext, child, nsnull); @@ -1585,7 +1571,6 @@ CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext, void FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, nsIFrame* aFrame, - nsIStyleContext* aParentContextIn, nsIContent* aParentContent, PRInt32 aAttrNameSpaceID, nsIAtom* aAttribute, @@ -1620,73 +1605,51 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, } nsCOMPtr parentContext; - nsIFrame* resolvedDescendant = nsnull; - // Get the frame providing the style context. If it differs from aFrame, then - // reslove the provider first, since the provider's context is the parent of aFrame's + nsIFrame* resolvedChild = nsnull; + // Get the frame providing the parent style context. If it is a + // child, then resolve the provider first. nsIFrame* providerFrame = nsnull; - aFrame->GetStyleContextProvider(aPresContext, &providerFrame); - ENSURE_TRUE(providerFrame); - if (providerFrame == aFrame) { - if (aParentContextIn) { - parentContext = aParentContextIn; - NOISY_TRACE_FRAME("non-null parent context provided: using it and assuming already resolved",aFrame); - } else { - nsIFrame* parentFrame; - aFrame->GetParent(&parentFrame); - if (parentFrame) { - parentFrame->GetStyleContext(getter_AddRefs(parentContext)); - } - } + PRBool providerIsChild = PR_FALSE; + aFrame->GetParentStyleContextFrame(aPresContext, + &providerFrame, &providerIsChild); + if (!providerIsChild) { + if (providerFrame) + providerFrame->GetStyleContext(getter_AddRefs(parentContext)); } else { -#ifdef DEBUG - // check to make sure that the provider is the child of aFrame - nsIFrame* providerFrameParent; - providerFrame->GetParent(&providerFrameParent); - NS_ASSERTION(providerFrameParent == aFrame, "invalid style context provider"); -#endif // resolve the provider here (before aFrame below) - nsCOMPtr providerContextParent; - nsIFrame* grandParentFrame; - aFrame->GetParent(&grandParentFrame); - if (grandParentFrame) { - grandParentFrame->GetStyleContext(getter_AddRefs(providerContextParent)); - } - ReResolveStyleContext(aPresContext, providerFrame, providerContextParent, content, - aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, aResultChange); - // the provider's new context becomes the parent context of aFrame's context + ReResolveStyleContext(aPresContext, providerFrame, content, + aAttrNameSpaceID, aAttribute, aChangeList, + aMinChange, aResultChange); + // The provider's new context becomes the parent context of + // aFrame's context. providerFrame->GetStyleContext(getter_AddRefs(parentContext)); - resolvedDescendant = providerFrame; // don't want to re-resolve the provider again + // Set |resolvedChild| so we don't bother resolving the + // provider again. + resolvedChild = providerFrame; } // do primary context nsIStyleContext* newContext = nsnull; - if (pseudoTag) { - nsIContent* pseudoContent = (aParentContent) ? aParentContent : localContent; - aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, parentContext, + if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) { + NS_ASSERTION(localContent, + "non pseudo-element frame without content node"); + aPresContext->ResolveStyleContextForNonElement(parentContext, + PR_TRUE, &newContext); + } + else if (pseudoTag) { + nsIContent* pseudoContent = + aParentContent ? aParentContent : localContent; + aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, + parentContext, PR_FALSE, &newContext); NS_RELEASE(pseudoTag); } else { NS_ASSERTION(localContent, "non pseudo-element frame without content node"); - // XXX This frame type check is a little ugly. However, it should - // be cheaper than doing useless style resolution on placeholder - // frames, and it should be able to go away if we make it so that - // placeholder frames don't have style contexts at all. - // - // XXX We also probably need to descend into the style contexts of - // the placeholder's out-of-flow frame. - nsCOMPtr frameType; - aFrame->GetFrameType(getter_AddRefs(frameType)); - if (content->IsContentOfType(nsIContent::eELEMENT) && - frameType != nsLayoutAtoms::placeholderFrame) { - aPresContext->ResolveStyleContextFor(content, parentContext, - PR_TRUE, &newContext); - } else { - aPresContext->ResolveStyleContextForNonElement(parentContext, - PR_TRUE, &newContext); - } + aPresContext->ResolveStyleContextFor(content, parentContext, + PR_TRUE, &newContext); } NS_ASSERTION(newContext, "failed to get new style context"); if (newContext) { @@ -1730,7 +1693,9 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (oldExtraContext) { nsIStyleContext* newExtraContext = nsnull; oldExtraContext->GetPseudoType(pseudoTag); - NS_ASSERTION(pseudoTag, "extra style context is not pseudo element"); + NS_ASSERTION(pseudoTag && + pseudoTag != nsHTMLAtoms::mozNonElementPseudo, + "extra style context is not pseudo element"); result = aPresContext->ResolvePseudoStyleContextFor(content, pseudoTag, newContext, PR_FALSE, &newExtraContext); NS_RELEASE(pseudoTag); @@ -1770,6 +1735,10 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, aPresContext->ResolveStyleContextFor(undisplayed->mContent, newContext, PR_TRUE, &undisplayedContext); } + else if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) { + aPresContext->ResolveStyleContextForNonElement(newContext, + PR_TRUE, &undisplayedContext); + } else { // pseudo element NS_ASSERTION(pseudoTag, "pseudo element without tag"); aPresContext->ResolvePseudoStyleContextFor(localContent, pseudoTag, newContext, PR_FALSE, @@ -1786,8 +1755,12 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, if (display->mDisplay != NS_STYLE_DISPLAY_NONE) { aChangeList.AppendChange(nsnull, ((undisplayed->mContent) ? undisplayed->mContent : localContent), NS_STYLE_HINT_FRAMECHANGE); + NS_RELEASE(undisplayedContext); + } else { + // update the undisplayed node with the new context + NS_RELEASE(undisplayed->mStyle); + undisplayed->mStyle = undisplayedContext; } - NS_RELEASE(undisplayedContext); } undisplayed = undisplayed->mNext; } @@ -1805,42 +1778,40 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, PRInt32 listIndex = 0; nsIAtom* childList = nsnull; PRInt32 childChange; - nsIFrame* child; do { - child = nsnull; + nsIFrame* child = nsnull; result = aFrame->FirstChild(aPresContext, childList, &child); - while ((NS_SUCCEEDED(result)) && (child)) { + while (NS_SUCCEEDED(result) && child) { nsFrameState state; child->GetFrameState(&state); - if (NS_FRAME_OUT_OF_FLOW != (state & NS_FRAME_OUT_OF_FLOW)) { + if (!(state & NS_FRAME_OUT_OF_FLOW)) { // only do frames that are in flow nsCOMPtr frameType; child->GetFrameType(getter_AddRefs(frameType)); - if (nsLayoutAtoms::placeholderFrame == frameType.get()) { // placeholder - // get out of flow frame and recurse there - nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame(); + if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder + // get out of flow frame and recur there + nsIFrame* outOfFlowFrame = + NS_STATIC_CAST(nsPlaceholderFrame*,child)->GetOutOfFlowFrame(); NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame"); + NS_ASSERTION(outOfFlowFrame != resolvedChild, + "out-of-flow frame not a true descendant"); - if (outOfFlowFrame != resolvedDescendant) { - ReResolveStyleContext(aPresContext, outOfFlowFrame, nsnull, content, - aAttrNameSpaceID, aAttribute, - aChangeList, aMinChange, childChange); - } else { - NOISY_TRACE("out of flow frame already resolved as descendent\n"); - } + // |nsFrame::GetParentStyleContextFrame| checks being out + // of flow so that this works correctly. + ReResolveStyleContext(aPresContext, outOfFlowFrame, content, + aAttrNameSpaceID, aAttribute, + aChangeList, aMinChange, childChange); - // reresolve placeholder's context under out of flow frame - nsIStyleContext* outOfFlowContext; - outOfFlowFrame->GetStyleContext(&outOfFlowContext); - ReResolveStyleContext(aPresContext, child, outOfFlowContext, content, + // reresolve placeholder's context under the same parent + // as the out-of-flow frame + ReResolveStyleContext(aPresContext, child, content, kNameSpaceID_Unknown, nsnull, aChangeList, aMinChange, childChange); - NS_RELEASE(outOfFlowContext); } else { // regular child frame - if (child != resolvedDescendant) { - ReResolveStyleContext(aPresContext, child, nsnull, content, + if (child != resolvedChild) { + ReResolveStyleContext(aPresContext, child, content, aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, childChange); } else { @@ -1884,18 +1855,13 @@ FrameManager::ComputeStyleChangeFor(nsIPresContext* aPresContext, #endif do { - nsIStyleContext* styleContext = nsnull; - frame->GetStyleContext(&styleContext); - nsIStyleContext* parentContext = styleContext->GetParent(); PRInt32 frameChange; - ReResolveStyleContext(aPresContext, frame, parentContext, nsnull, + ReResolveStyleContext(aPresContext, frame, nsnull, aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, frameChange); #ifdef NS_DEBUG - VerifyStyleTree(aPresContext, frame, parentContext); + VerifyStyleTree(aPresContext, frame, nsnull); #endif - NS_IF_RELEASE(parentContext); - NS_RELEASE(styleContext); if (aTopLevelChange < frameChange) { aTopLevelChange = frameChange; } diff --git a/mozilla/layout/html/base/src/nsSplittableFrame.cpp b/mozilla/layout/html/base/src/nsSplittableFrame.cpp index 72ddb3f9b64..6c143c6795a 100644 --- a/mozilla/layout/html/base/src/nsSplittableFrame.cpp +++ b/mozilla/layout/html/base/src/nsSplittableFrame.cpp @@ -55,19 +55,6 @@ nsSplittableFrame::Init(nsIPresContext* aPresContext, // Hook the frame into the flow mPrevInFlow = aPrevInFlow; aPrevInFlow->SetNextInFlow(this); - - // Make sure the general flags bits are the same - nsFrameState state; - aPrevInFlow->GetFrameState(&state); - if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) { - mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - } - if (state & NS_FRAME_REPLACED_ELEMENT) { - mState |= NS_FRAME_REPLACED_ELEMENT; - } - if (state & NS_FRAME_SELECTED_CONTENT) { - mState |= NS_FRAME_SELECTED_CONTENT; - } } return rv; diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 91c09b7fee8..3122e75c47a 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -384,7 +384,7 @@ GetSpecialSibling(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame** a } void* value; - aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation, 0, &value); + aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::IBSplitSpecialSibling, 0, &value); *aResult = NS_STATIC_CAST(nsIFrame*, value); } @@ -412,7 +412,8 @@ SetFrameIsSpecial(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame* aS // Store the "special sibling" (if we were given one) with the // first frame in the flow. - aFrameManager->SetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation, + aFrameManager->SetFrameProperty(aFrame, + nsLayoutAtoms::IBSplitSpecialSibling, aSpecialSibling, nsnull); } } @@ -492,10 +493,7 @@ IsBlockFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) // don't we use display->IsBlockLevel() here? const nsStyleDisplay* display; aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); - if (NS_STYLE_DISPLAY_INLINE == display->mDisplay) { - return PR_FALSE; - } - return PR_TRUE; + return NS_STYLE_DISPLAY_INLINE != display->mDisplay; } static nsIFrame* @@ -527,6 +525,27 @@ FindLastBlock(nsIPresContext* aPresContext, nsIFrame* aKid) return lastBlock; } +/* + * Unlike the special (next) sibling, the special previous sibling + * property points only from the anonymous block to the original inline + * that preceded it. It is useful for finding the "special parent" of a + * frame (i.e., a frame from which a good parent style context can be + * obtained), one looks at the special previous sibling annotation of + * the real parent of the frame (if the real parent has + * NS_FRAME_IS_SPECIAL). + */ +inline void +MarkIBSpecialPrevSibling(nsIPresContext* aPresContext, + nsIFrameManager *aFrameManager, + nsIFrame *aAnonymousFrame, + nsIFrame *aSpecialParent) +{ + aFrameManager->SetFrameProperty(aAnonymousFrame, + nsLayoutAtoms::IBSplitSpecialPrevSibling, + aSpecialParent, + nsnull); +} + /** * Moves frames to a new parent, updating the style context and * propagating relevant frame state bits. |aNewParentSC| may be null, @@ -3803,7 +3822,9 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell, if (NS_SUCCEEDED(rv)) { // The placeholder frame gets a pseudo style context nsCOMPtr placeholderStyle; - aPresContext->ResolveStyleContextForNonElement(aStyleContext, PR_FALSE, + nsCOMPtr parentContext = + dont_AddRef(aStyleContext->GetParent()); + aPresContext->ResolveStyleContextForNonElement(parentContext, PR_FALSE, getter_AddRefs(placeholderStyle)); placeholderFrame->Init(aPresContext, aContent, aParentFrame, placeholderStyle, nsnull); @@ -9231,15 +9252,18 @@ DeletingFrameSubtree(nsIPresContext* aPresContext, if (aFrameManager) { nsAutoVoidArray destroyQueue; - while (aFrame) { - // If it's a "special" block-in-inline frame, then we need to - // remember to delete our special siblings, too. - if (IsFrameSpecial(aFrame)) { - nsIFrame* specialSibling; - GetSpecialSibling(aFrameManager, aFrame, &specialSibling); - DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, specialSibling); - } + // If it's a "special" block-in-inline frame, then we need to + // remember to delete our special siblings, too. Since every one of + // the next-in-flows has the same special sibling, just do this + // once, rather than in the loop below. + if (IsFrameSpecial(aFrame)) { + nsIFrame* specialSibling; + GetSpecialSibling(aFrameManager, aFrame, &specialSibling); + DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, + specialSibling); + } + while (aFrame) { DoDeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, destroyQueue, aFrame, aFrame); @@ -10483,9 +10507,15 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, nsIFrame* primaryFrame; shell->GetPrimaryFrameFor(aContent, &primaryFrame); // Get the frame associated with the content whose style context is highest in the style context tree - nsIFrame* primaryStyleFrame = nsnull; + nsIFrame* primaryStyleFrame = primaryFrame; if (primaryFrame) { - primaryFrame->GetStyleContextProvider(aPresContext, &primaryStyleFrame); + PRBool providerIsChild = PR_FALSE; + nsIFrame *styleContextProvider; + primaryFrame->GetParentStyleContextFrame(aPresContext, + &styleContextProvider, + &providerIsChild); + if (providerIsChild) + primaryStyleFrame = styleContextProvider; } PRBool reconstruct = PR_FALSE; @@ -11220,6 +11250,8 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell, lastBlock->SetNextSibling(nsnull); // Create "special" inline-block linkage between the frames + // XXXldb Do we really need to do this? It doesn't seem + // consistent with the use in ConstructInline. SetFrameIsSpecial(state.mFrameManager, list1, list2); SetFrameIsSpecial(state.mFrameManager, list2, list3); SetFrameIsSpecial(state.mFrameManager, list3, nsnull); @@ -13742,6 +13774,8 @@ nsCSSFrameConstructor::ConstructInline(nsIPresShell* aPresShell, // containing block will be reframed instead. SetFrameIsSpecial(aState.mFrameManager, aNewFrame, blockFrame); SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame); + MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager, + blockFrame, aNewFrame); if (inlineFrame) SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull); @@ -14169,6 +14203,7 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext, // Create an anonymous inline frame that will parent // aRightInlineChildFrame. The new frame won't have a parent yet: // the recursion will parent it. + // XXXldb Why bother if |aRightInlineChildFrame| is null? nsIFrame* inlineFrame = nsnull; NS_NewInlineFrame(shell, &inlineFrame); if (! inlineFrame) @@ -14196,6 +14231,9 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext, SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame); SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull); + MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager, + blockFrame, firstInFlow); + // If we have a continuation frame, then we need to break the // continuation. nsIFrame* nextInFlow; diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index 810fa2c64fc..9c593670d77 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -175,6 +175,19 @@ struct BCPropertyData PRUint8 mLeftBorderWidth; }; +NS_IMETHODIMP +nsTableFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) +{ + // Since our parent, the table outer frame, returned this frame, we + // must return whatever our parent would normally have returned. + + NS_PRECONDITION(mParent, "table constructed without outer table"); + return NS_STATIC_CAST(nsFrame*, mParent)-> + DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild); +} + NS_IMETHODIMP nsTableFrame::GetFrameType(nsIAtom** aType) const diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index 14de0c5fdf2..bb388eec171 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -381,6 +381,10 @@ public: nsFrameList& GetColGroups(); + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); + /** * Get the "type" of the frame * diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp index 412ed694fba..86536e5933a 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp @@ -414,20 +414,30 @@ NS_IMETHODIMP nsTableOuterFrame::SetSelected(nsIPresContext* aPresContext, return result; } -// GetStyleContextProvider: -// The innerTableFame is the style context provider, which is cached in a data member NS_IMETHODIMP -nsTableOuterFrame::GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame) +nsTableOuterFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) { - NS_ASSERTION(aProviderFrame && aPresContext, "null argument: aPresContext and-or aProviderFrame"); - if (aProviderFrame) { - if (mInnerTableFrame) - *aProviderFrame = mInnerTableFrame; - else - *aProviderFrame = this; + // The table outer frame and the (inner) table frame split the style + // data by giving the table frame the style context associated with + // the table content node and creating a style context for the outer + // frame that is a *child* of the table frame's style context, + // matching the :table-outer (should be :-moz-table-outer!) + // pseudo-element. html.css has a rule that causes that + // pseudo-element (and thus the outer table) to inherit *some* style + // properties from the table frame. The children of the table inherit + // directly from the inner table, and the outer table's style context + // is a leaf. + + if (!mInnerTableFrame) { + *aProviderFrame = this; + *aIsChild = PR_FALSE; + return NS_ERROR_FAILURE; } - return (aProviderFrame && mInnerTableFrame) ? NS_OK : NS_ERROR_FAILURE; + *aProviderFrame = mInnerTableFrame; + *aIsChild = PR_TRUE; + return NS_OK; } // INCREMENTAL REFLOW HELPER FUNCTIONS diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.h b/mozilla/layout/html/table/src/nsTableOuterFrame.h index b8a7aaf9a57..eb8e7c6a520 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.h +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.h @@ -171,8 +171,9 @@ public: */ nscoord GetMinCaptionWidth(); - NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame); + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); /*---------------- nsITableLayout methods ------------------------*/ diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index 694bffd8c6f..51079f24435 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -58,6 +58,7 @@ #include "nsRuleWalker.h" #include "nsIHTMLDocument.h" #include "nsIDOMHTMLBodyElement.h" +#include "nsHTMLAtoms.h" #ifdef MOZ_PERF_METRICS #include "nsITimeRecorder.h" @@ -1109,7 +1110,8 @@ nsIStyleContext* StyleSetImpl::ResolveStyleForNonElement( mDocRuleProcessors || mOverrideRuleProcessors) { EnsureRuleWalker(aPresContext); - result = GetContext(aPresContext, aParentContext, nsnull, aForceUnique); + result = GetContext(aPresContext, aParentContext, + nsHTMLAtoms::mozNonElementPseudo, aForceUnique); NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root"); } } diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index 810fa2c64fc..9c593670d77 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -175,6 +175,19 @@ struct BCPropertyData PRUint8 mLeftBorderWidth; }; +NS_IMETHODIMP +nsTableFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) +{ + // Since our parent, the table outer frame, returned this frame, we + // must return whatever our parent would normally have returned. + + NS_PRECONDITION(mParent, "table constructed without outer table"); + return NS_STATIC_CAST(nsFrame*, mParent)-> + DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild); +} + NS_IMETHODIMP nsTableFrame::GetFrameType(nsIAtom** aType) const diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index 14de0c5fdf2..bb388eec171 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -381,6 +381,10 @@ public: nsFrameList& GetColGroups(); + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); + /** * Get the "type" of the frame * diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp index 412ed694fba..86536e5933a 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.cpp +++ b/mozilla/layout/tables/nsTableOuterFrame.cpp @@ -414,20 +414,30 @@ NS_IMETHODIMP nsTableOuterFrame::SetSelected(nsIPresContext* aPresContext, return result; } -// GetStyleContextProvider: -// The innerTableFame is the style context provider, which is cached in a data member NS_IMETHODIMP -nsTableOuterFrame::GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame) +nsTableOuterFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild) { - NS_ASSERTION(aProviderFrame && aPresContext, "null argument: aPresContext and-or aProviderFrame"); - if (aProviderFrame) { - if (mInnerTableFrame) - *aProviderFrame = mInnerTableFrame; - else - *aProviderFrame = this; + // The table outer frame and the (inner) table frame split the style + // data by giving the table frame the style context associated with + // the table content node and creating a style context for the outer + // frame that is a *child* of the table frame's style context, + // matching the :table-outer (should be :-moz-table-outer!) + // pseudo-element. html.css has a rule that causes that + // pseudo-element (and thus the outer table) to inherit *some* style + // properties from the table frame. The children of the table inherit + // directly from the inner table, and the outer table's style context + // is a leaf. + + if (!mInnerTableFrame) { + *aProviderFrame = this; + *aIsChild = PR_FALSE; + return NS_ERROR_FAILURE; } - return (aProviderFrame && mInnerTableFrame) ? NS_OK : NS_ERROR_FAILURE; + *aProviderFrame = mInnerTableFrame; + *aIsChild = PR_TRUE; + return NS_OK; } // INCREMENTAL REFLOW HELPER FUNCTIONS diff --git a/mozilla/layout/tables/nsTableOuterFrame.h b/mozilla/layout/tables/nsTableOuterFrame.h index b8a7aaf9a57..eb8e7c6a520 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.h +++ b/mozilla/layout/tables/nsTableOuterFrame.h @@ -171,8 +171,9 @@ public: */ nscoord GetMinCaptionWidth(); - NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext, - nsIFrame** aProviderFrame); + NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext, + nsIFrame** aProviderFrame, + PRBool* aIsChild); /*---------------- nsITableLayout methods ------------------------*/