diff --git a/content/base/src/nsStyleSet.cpp b/content/base/src/nsStyleSet.cpp index 694bffd8c6f..51079f24435 100644 --- a/content/base/src/nsStyleSet.cpp +++ b/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/content/html/content/src/nsHTMLAtomList.h b/content/html/content/src/nsHTMLAtomList.h index 83289a1949b..d960cf90210 100644 --- a/content/html/content/src/nsHTMLAtomList.h +++ b/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/content/shared/public/nsHTMLAtomList.h b/content/shared/public/nsHTMLAtomList.h index 83289a1949b..d960cf90210 100644 --- a/content/shared/public/nsHTMLAtomList.h +++ b/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/content/shared/public/nsLayoutAtomList.h b/content/shared/public/nsLayoutAtomList.h index da4ee21d396..3fb7ad63517 100644 --- a/content/shared/public/nsLayoutAtomList.h +++ b/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/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 91c09b7fee8..3122e75c47a 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/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/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index 78509225b8d..6722328e9a5 100644 --- a/layout/base/nsFrameManager.cpp +++ b/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/layout/base/nsLayoutAtomList.h b/layout/base/nsLayoutAtomList.h index da4ee21d396..3fb7ad63517 100644 --- a/layout/base/nsLayoutAtomList.h +++ b/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/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index 4a82a165182..b8c0a5ea433 100644 --- a/layout/base/public/nsIFrame.h +++ b/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/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e04c1561a9a..87999f68d0b 100644 --- a/layout/generic/nsFrame.cpp +++ b/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/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 4261ba22558..46b4b44e0aa 100644 --- a/layout/generic/nsFrame.h +++ b/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/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 4a82a165182..b8c0a5ea433 100644 --- a/layout/generic/nsIFrame.h +++ b/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/layout/generic/nsSplittableFrame.cpp b/layout/generic/nsSplittableFrame.cpp index 72ddb3f9b64..6c143c6795a 100644 --- a/layout/generic/nsSplittableFrame.cpp +++ b/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/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index e04c1561a9a..87999f68d0b 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/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/layout/html/base/src/nsFrame.h b/layout/html/base/src/nsFrame.h index 4261ba22558..46b4b44e0aa 100644 --- a/layout/html/base/src/nsFrame.h +++ b/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/layout/html/base/src/nsFrameManager.cpp b/layout/html/base/src/nsFrameManager.cpp index 78509225b8d..6722328e9a5 100644 --- a/layout/html/base/src/nsFrameManager.cpp +++ b/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/layout/html/base/src/nsSplittableFrame.cpp b/layout/html/base/src/nsSplittableFrame.cpp index 72ddb3f9b64..6c143c6795a 100644 --- a/layout/html/base/src/nsSplittableFrame.cpp +++ b/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/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 91c09b7fee8..3122e75c47a 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/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/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index 810fa2c64fc..9c593670d77 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/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/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index 14de0c5fdf2..bb388eec171 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/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/layout/html/table/src/nsTableOuterFrame.cpp b/layout/html/table/src/nsTableOuterFrame.cpp index 412ed694fba..86536e5933a 100644 --- a/layout/html/table/src/nsTableOuterFrame.cpp +++ b/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/layout/html/table/src/nsTableOuterFrame.h b/layout/html/table/src/nsTableOuterFrame.h index b8a7aaf9a57..eb8e7c6a520 100644 --- a/layout/html/table/src/nsTableOuterFrame.h +++ b/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/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 694bffd8c6f..51079f24435 100644 --- a/layout/style/nsStyleSet.cpp +++ b/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/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 810fa2c64fc..9c593670d77 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/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/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 14de0c5fdf2..bb388eec171 100644 --- a/layout/tables/nsTableFrame.h +++ b/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/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index 412ed694fba..86536e5933a 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/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/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index b8a7aaf9a57..eb8e7c6a520 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/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 ------------------------*/