From 84edc3c7eb61e038343f08a81b73ea6ad854e71d Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Wed, 15 Aug 2007 23:20:26 +0000 Subject: [PATCH] Relanding bug 390425, with attempted performance regression fix. r+sr+a=roc git-svn-id: svn://10.0.0.236/trunk@232178 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsCSSFrameConstructor.cpp | 683 +++++++++--------- mozilla/layout/base/nsCSSFrameConstructor.h | 70 +- mozilla/layout/base/nsPresShell.cpp | 5 +- .../insert-into-split-inline-10-ref.html | 23 + .../ib-split/insert-into-split-inline-10.html | 29 + .../insert-into-split-inline-11-ref.html | 25 + .../ib-split/insert-into-split-inline-11.html | 31 + .../ib-split/insert-into-split-inline-8c.html | 24 + .../insert-into-split-inline-9-ref.html | 22 + .../ib-split/insert-into-split-inline-9.html | 28 + mozilla/layout/reftests/ib-split/reftest.list | 4 + mozilla/layout/reftests/reftest.list | 2 +- mozilla/layout/style/nsRuleNode.cpp | 3 + 13 files changed, 569 insertions(+), 380 deletions(-) create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-10-ref.html create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-10.html create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-11-ref.html create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-11.html create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-8c.html create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-9-ref.html create mode 100644 mozilla/layout/reftests/ib-split/insert-into-split-inline-9.html diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 92ce13e338d..c4431939166 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -451,23 +451,22 @@ IsFrameSpecial(nsIFrame* aFrame) return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) != 0; } -static void -GetSpecialSibling(nsFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame** aResult) +static nsIFrame* GetSpecialSibling(nsIFrame* aFrame) { // We only store the "special sibling" annotation with the first - // frame in the flow. Walk back to find that frame now. - aFrame = aFrame->GetFirstInFlow(); + // frame in the continuation chain. Walk back to find that frame now. + aFrame = aFrame->GetFirstContinuation(); void* value = aFrame->GetProperty(nsGkAtoms::IBSplitSpecialSibling); - *aResult = static_cast(value); + return static_cast(value); } static nsIFrame* -GetLastSpecialSibling(nsFrameManager* aFrameManager, nsIFrame* aFrame) +GetLastSpecialSibling(nsIFrame* aFrame) { for (nsIFrame *frame = aFrame, *next; ; frame = next) { - GetSpecialSibling(aFrameManager, frame, &next); + next = GetSpecialSibling(frame); if (!next) return frame; } @@ -537,10 +536,18 @@ IsInlineOutside(nsIFrame* aFrame) return aFrame->GetStyleDisplay()->IsInlineOutside(); } +/** + * True if aFrame is an actual inline frame in the sense of non-replaced + * display:inline CSS boxes. In other words, it can be affected by {ib} + * splitting and can contain first-letter frames. Basically, this is either an + * inline frame (positioned or otherwise) or an line frame (this last because + * it can contain first-letter and because inserting blocks in the middle of it + * needs to terminate it). + */ static PRBool -IsBlockOutside(nsIFrame* aFrame) +IsInlineFrame(const nsIFrame* aFrame) { - return aFrame->GetStyleDisplay()->IsBlockOutside(); + return aFrame->IsFrameOfType(nsIFrame::eLineParticipant); } //---------------------------------------------------------------------- @@ -1416,7 +1423,7 @@ nsFrameConstructorState::AddChild(nsIFrame* aNewFrame, // Now add the special siblings too. nsIFrame* specialSibling = aNewFrame; while (specialSibling && IsFrameSpecial(specialSibling)) { - GetSpecialSibling(mFrameManager, specialSibling, &specialSibling); + specialSibling = GetSpecialSibling(specialSibling); if (specialSibling) { NS_ASSERTION(frameItems == &aFrameItems, "IB split ending up in an out-of-flow childlist?"); @@ -1617,15 +1624,12 @@ AdjustFloatParentPtrs(nsIFrame* aFrame, } /** - * Moves frames to a new parent, updating the style context and - * propagating relevant frame state bits. |aNewParentSC| may be null, - * in which case the child frames' style contexts will remain - * untouched. |aState| may be null, in which case the parent + * Moves frames to a new parent, updating the style context and propagating + * relevant frame state bits. |aState| may be null, in which case the parent * pointers of out-of-flow frames will remain untouched. */ static void MoveChildrenTo(nsFrameManager* aFrameManager, - nsStyleContext* aNewParentSC, nsIFrame* aNewParent, nsIFrame* aFrameList, nsFrameConstructorState* aState, @@ -1649,24 +1653,15 @@ MoveChildrenTo(nsFrameManager* aFrameManager, AdjustFloatParentPtrs(aFrameList, *aState, *aOuterState); } -#if 0 - // XXX When this is used with {ib} frame hierarchies, it seems - // fine to leave the style contexts of the children of the - // anonymous block frame parented by the original inline - // frame. (In fact, one would expect some inheritance - // relationships to be broken if we reparented them to the - // anonymous block frame, but oddly they aren't -- need to - // investigate that...) - if (aNewParentSC) - aPresContext->FrameManager()->ReParentStyleContext(aFrameList, - aNewParentSC); -#endif - aFrameList = aFrameList->GetNextSibling(); } if (setHasChildWithView) { - aNewParent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW); + do { + aNewParent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW); + aNewParent = aNewParent->GetParent(); + } while (aNewParent && + !(aNewParent->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)); } } @@ -7876,10 +7871,10 @@ AdjustAppendParentForAfterContent(nsPresContext* aPresContext, * generated content. */ nsresult -nsCSSFrameConstructor::AppendFrames(const nsFrameConstructorState& aState, +nsCSSFrameConstructor::AppendFrames(nsFrameConstructorState& aState, nsIContent* aContainer, nsIFrame* aParentFrame, - nsIFrame* aFrameList, + nsFrameItems& aFrameList, nsIFrame* aAfterFrame) { #ifdef DEBUG @@ -7893,15 +7888,115 @@ nsCSSFrameConstructor::AppendFrames(const nsFrameConstructorState& aState, nsFrameManager* frameManager = aState.mFrameManager; if (aAfterFrame) { + NS_ASSERTION(!IsFrameSpecial(aParentFrame) || + IsInlineFrame(aParentFrame) || + !IsInlineOutside(aAfterFrame), + "Shouldn't have inline :after content on the block in an " + "{ib} split"); nsFrameList frames(aParentFrame->GetFirstChild(nsnull)); // Insert the frames before the :after pseudo-element. return frameManager->InsertFrames(aParentFrame, nsnull, frames.GetPrevSiblingFor(aAfterFrame), - aFrameList); + aFrameList.childList); } - return frameManager->AppendFrames(aParentFrame, nsnull, aFrameList); + if (IsFrameSpecial(aParentFrame) && + !IsInlineFrame(aParentFrame) && + IsInlineOutside(aFrameList.lastChild)) { + NS_ASSERTION(!aParentFrame->GetNextContinuation(), "Shouldn't happen"); + + // We want to put some of the frames into the following inline frame. + nsIFrame* lastBlock = FindLastBlock(aFrameList.childList); + nsIFrame* firstTrailingInline; + if (lastBlock) { + firstTrailingInline = lastBlock->GetNextSibling(); + lastBlock->SetNextSibling(nsnull); + aFrameList.lastChild = lastBlock; + } else { + firstTrailingInline = aFrameList.childList; + aFrameList = nsFrameItems(); + } + + NS_ASSERTION(firstTrailingInline, "How did that happen?"); + nsIFrame* parentFrame = aParentFrame; + + // Now we loop, because it might be the case that the parent of our special + // block is another special block, and that we're at the very end of it, + // and in that case if we create a new special inline we'll have to create + // a parent for it too. + do { + NS_ASSERTION(IsFrameSpecial(parentFrame) && !IsInlineFrame(parentFrame), + "Shouldn't be in this code"); + nsIFrame* inlineSibling = GetSpecialSibling(parentFrame); + PRBool isPositioned = PR_FALSE; + nsIContent* content = nsnull; + nsStyleContext* styleContext = nsnull; + if (!inlineSibling) { + nsIFrame* firstInline = + static_cast + (aState.mPresContext->PropertyTable()-> + GetProperty(parentFrame->GetFirstContinuation(), + nsGkAtoms::IBSplitSpecialPrevSibling)); + NS_ASSERTION(firstInline, "How did that happen?"); + + content = firstInline->GetContent(); + styleContext = firstInline->GetStyleContext(); + isPositioned = (styleContext->GetStyleDisplay()->mPosition == + NS_STYLE_POSITION_RELATIVE); + } + + nsIFrame* stateParent = + inlineSibling ? inlineSibling->GetParent() : parentFrame->GetParent(); + + nsFrameConstructorState + targetState(mPresShell, mFixedContainingBlock, + GetAbsoluteContainingBlock(stateParent), + GetFloatContainingBlock(stateParent)); + nsIFrame* newInlineSibling = + MoveFramesToEndOfIBSplit(aState, inlineSibling, + isPositioned, content, + styleContext, firstTrailingInline, + parentFrame, &targetState); + + if (inlineSibling) { + // we're all set -- we just moved things to a frame that was already + // there. + NS_ASSERTION(newInlineSibling == inlineSibling, "What happened?"); + break; + } + + SetFrameIsSpecial(parentFrame, newInlineSibling); + + // We had to create a frame for this new inline sibling. Figure out + // the right parentage for it. + // XXXbz add a test for this? + nsIFrame* newParentFrame = parentFrame->GetParent(); + NS_ASSERTION(!IsInlineFrame(newParentFrame), + "The block in an {ib} split shouldn't be living inside " + "an inline"); + if (!IsFrameSpecial(newParentFrame) || + newParentFrame->GetNextContinuation() || + parentFrame->GetNextSibling()) { + // Just insert after parentFrame + frameManager->InsertFrames(newParentFrame, nsnull, parentFrame, + newInlineSibling); + firstTrailingInline = nsnull; + } else { + // recurse up the tree + parentFrame = newParentFrame; + firstTrailingInline = newInlineSibling; + } + } while (firstTrailingInline); + } + + if (!aFrameList.childList) { + // It all got eaten by the special inline + return NS_OK; + } + + return frameManager->AppendFrames(aParentFrame, nsnull, + aFrameList.childList); } /** @@ -7958,8 +8053,7 @@ FindPreviousAnonymousSibling(nsIPresShell* aPresShell, // The frame may be a special frame (a split inline frame that // contains a block). Get the last part of that split. if (IsFrameSpecial(prevSibling)) { - prevSibling = GetLastSpecialSibling(aPresShell->FrameManager(), - prevSibling); + prevSibling = GetLastSpecialSibling(prevSibling); } // The frame may have a continuation. If so, we want the @@ -8144,8 +8238,7 @@ nsCSSFrameConstructor::FindPreviousSibling(nsIContent* aContainer, // The frame may be a special frame (a split inline frame that // contains a block). Get the last part of that split. if (IsFrameSpecial(prevSibling)) { - prevSibling = GetLastSpecialSibling(mPresShell->FrameManager(), - prevSibling); + prevSibling = GetLastSpecialSibling(prevSibling); } // The frame may have a continuation. Get the last continuation @@ -8418,7 +8511,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, if (item == child) // Call ContentInserted with this index. ContentInserted(aContainer, child, - iter.index(), mTempFrameTreeState, PR_FALSE); + iter.index(), mTempFrameTreeState); LAYOUT_PHASE_TEMP_REENTER(); } } @@ -8445,20 +8538,9 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, return NS_OK; } - // If the frame we are manipulating is a ``special'' frame (that - // is, one that's been created as a result of a block-in-inline - // situation) then do something different instead of just - // appending newly created frames. Note that only the - // first-in-flow is marked so we check before getting to the - // last-in-flow. - // - // We run into this situation occasionally while loading web - // pages, typically when some content generation tool has - // sprinkled invalid markup into the document. More often than - // not, we'll be able to just use the normal fast-path frame - // construction code, because the frames will be appended to the - // ``anonymous'' block that got created to parent the block - // children of the inline. + // If the frame we are manipulating is a ``special'' frame (that is, one + // that's been created as a result of a block-in-inline situation) then we + // need to append to the last special sibling, not to the frame itself. if (IsFrameSpecial(parentFrame)) { #ifdef DEBUG if (gNoisyContentUpdates) { @@ -8470,37 +8552,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, // Since we're appending, we'll walk to the last anonymous frame // that was created for the broken inline frame. - nsFrameManager *frameManager = mPresShell->FrameManager(); - - while (1) { - nsIFrame* sibling; - GetSpecialSibling(frameManager, parentFrame, &sibling); - if (! sibling) - break; - - parentFrame = sibling; - } - - // If this frame is the anonymous block frame, then all's well: - // just append frames as usual. - const nsStyleDisplay* display = parentFrame->GetStyleDisplay(); - - if (NS_STYLE_DISPLAY_BLOCK != display->mDisplay) { - // Nope, it's an inline, so just reframe the entire stinkin' mess if the - // content is a block. We _could_ do better here with a little more work... - // find out if the child is a block or inline, an inline means we don't have to reframe - nsIContent *child = aContainer->GetChildAt(aNewIndexInContainer); - PRBool needReframe = !child; - if (child && child->IsNodeOfType(nsINode::eELEMENT)) { - nsRefPtr styleContext; - styleContext = ResolveStyleContext(parentFrame, child); - // XXX since the block child goes in the last inline of the sacred triad, frames would - // need to be moved into the 2nd triad (block) but that is more work, for now bail. - needReframe = styleContext->GetStyleDisplay()->IsBlockOutside(); - } - if (needReframe) - return ReframeContainingBlock(parentFrame); - } + parentFrame = GetLastSpecialSibling(parentFrame); } // Get the parent frame's last continuation @@ -8520,7 +8572,6 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, // Create some new frames PRUint32 count; - nsIFrame* firstAppendedFrame = nsnull; nsFrameItems frameItems; nsFrameConstructorState state(mPresShell, mFixedContainingBlock, GetAbsoluteContainingBlock(parentFrame), @@ -8586,18 +8637,20 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, } nsresult result = NS_OK; - firstAppendedFrame = frameItems.childList; - if (!firstAppendedFrame) { - firstAppendedFrame = captionItems.childList; - } // Notify the parent frame passing it the list of new frames - if (NS_SUCCEEDED(result) && firstAppendedFrame) { + if (NS_SUCCEEDED(result) && + (frameItems.childList || captionItems.childList)) { // Perform special check for diddling around with the frames in // a special inline frame. - if (WipeContainingBlock(state, containingBlock, parentFrame, - frameItems.childList)) { + // We can't have a block ::after inside an inline, so it's safe to ignore + // the fact that we're not really appending if there's ::after content. + // Indeed, if we're inserting before the ::after content that means the + // ::after content is not the last child of the block in the {ib} split, + // which is the only case in which we care whether we're appending. + if (WipeContainingBlock(state, containingBlock, parentFrame, frameItems, + PR_TRUE, nsnull)) { return NS_OK; } @@ -8612,12 +8665,12 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, } } if (frameItems.childList) { // append children of the inner table - AppendFrames(state, aContainer, parentFrame, frameItems.childList, + AppendFrames(state, aContainer, parentFrame, frameItems, parentAfterFrame); } } else { - AppendFrames(state, aContainer, parentFrame, firstAppendedFrame, + AppendFrames(state, aContainer, parentFrame, frameItems, parentAfterFrame); } } @@ -8641,121 +8694,6 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, return NS_OK; } -// Return TRUE if the insertion of aChild into aParent1,2 should force a reframe. aParent1 is -// the special inline container which contains a block. aParentFrame is approximately aParent1's -// primary frame and will be set to the correct parent of aChild if a reframe is not necessary. -// aParent2 is aParentFrame's content. aPrevSibling will be set to the correct prev sibling of -// aChild if a reframe is not necessary. -PRBool -nsCSSFrameConstructor::NeedSpecialFrameReframe(nsIContent* aParent1, - nsIContent* aParent2, - nsIFrame*& aParentFrame, - nsIContent* aChild, - PRInt32 aIndexInContainer, - nsIFrame*& aPrevSibling, - nsIFrame* aNextSibling) -{ - // XXXbz aNextSibling is utterly unused. Why? - - if (IsBlockOutside(aParentFrame)) - return PR_FALSE; - - // find out if aChild is a block or inline - PRBool childIsBlock = PR_FALSE; - if (aChild->IsNodeOfType(nsINode::eELEMENT)) { - nsRefPtr styleContext; - styleContext = ResolveStyleContext(aParentFrame, aChild); - const nsStyleDisplay* display = styleContext->GetStyleDisplay(); - childIsBlock = display->IsBlockOutside(); - } - nsIFrame* prevParent; // parent of prev sibling - nsIFrame* nextParent; // parent of next sibling - - if (childIsBlock) { - if (aPrevSibling) { - prevParent = aPrevSibling->GetParent(); - NS_ASSERTION(prevParent, "program error - null parent frame"); - if (!IsBlockOutside(prevParent)) { // prevParent is an inline - // XXX we need to find out if prevParent is the 1st inline or the last. If it - // is the 1st, then aChild and the frames after aPrevSibling within the 1st inline - // need to be moved to the block(inline). If it is the last, then aChild and the - // frames before aPrevSibling within the last need to be moved to the block(inline). - return PR_TRUE; // For now, bail. - } - aParentFrame = prevParent; // prevParent is a block, put aChild there - } - else { - // XXXbz see comments in ContentInserted about this being wrong in many - // cases! Why doesn't this just use aNextSibling anyway? Why are we - // looking sometimes in aParent1 and sometimes in aParent2? - nsIFrame* nextSibling = (aIndexInContainer >= 0) - ? FindNextSibling(aParent2, aParentFrame, - aIndexInContainer) - : FindNextAnonymousSibling(mPresShell, mDocument, - aParent1, aChild); - if (nextSibling) { - nextParent = nextSibling->GetParent(); - NS_ASSERTION(nextParent, "program error - null parent frame"); - if (!IsBlockOutside(nextParent)) { - // XXX we need to move aChild, aNextSibling and all the frames after aNextSibling within - // the 1st inline to the block(inline). - return PR_TRUE; // for now, bail - } - // put aChild in nextParent which is the block(inline) and leave aPrevSibling null - aParentFrame = nextParent; - } - } - } - else { // aChild is an inline - if (aPrevSibling) { - prevParent = aPrevSibling->GetParent(); - NS_ASSERTION(prevParent, "program error - null parent frame"); - if (!IsBlockOutside(prevParent)) { // prevParent is an inline - // aChild goes into the same inline frame as aPrevSibling - aParentFrame = aPrevSibling->GetParent(); - NS_ASSERTION(aParentFrame, "program error - null parent frame"); - } - else { // prevParent is a block - // XXXbz see comments in ContentInserted about this being wrong in many - // cases! Why doesn't this just use aNextSibling anyway? Why are we - // looking sometimes in aParent1 and sometimes in aParent2? - nsIFrame* nextSibling = (aIndexInContainer >= 0) - ? FindNextSibling(aParent2, aParentFrame, - aIndexInContainer) - : FindNextAnonymousSibling(mPresShell, - mDocument, aParent1, - aChild); - if (nextSibling) { - nextParent = nextSibling->GetParent(); - NS_ASSERTION(nextParent, "program error - null parent frame"); - if (!IsBlockOutside(nextParent)) { - // nextParent is the ending inline frame. Put aChild there and - // set aPrevSibling to null so aChild is its first element. - aParentFrame = nextSibling->GetParent(); - NS_ASSERTION(aParentFrame, "program error - null parent frame"); - aPrevSibling = nsnull; - } - else { // nextParent is a block - // prevParent and nextParent should be the same, and aChild goes there - NS_ASSERTION(prevParent == nextParent, "special frame error"); - aParentFrame = prevParent; - } - } - else { - // The child has no next sibling, so we can't find the ending inline - // frame (which might not exist in this case anyway!), but aChild - // should go in there. Force a reframe. - // XXXbz wouldn't getting prevParent's special sibling work, with - // reframing only needed if that's null? - return PR_TRUE; - } - } - } - // else aChild goes into the 1st inline frame which is aParentFrame - } - return PR_FALSE; -} - #ifdef MOZ_XUL enum content_operation @@ -8828,8 +8766,7 @@ nsresult nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer, - nsILayoutHistoryState* aFrameState, - PRBool aInReinsertContent) + nsILayoutHistoryState* aFrameState) { AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC); // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and @@ -8955,18 +8892,14 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, : FindNextAnonymousSibling(mPresShell, mDocument, aContainer, aChild); } - PRBool handleSpecialFrame = IsFrameSpecial(parentFrame) && !aInReinsertContent; - // Now, find the geometric parent so that we can handle // continuations properly. Use the prev sibling if we have it; // otherwise use the next sibling. if (prevSibling) { - if (!handleSpecialFrame) - parentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); + parentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); } else if (nextSibling) { - if (!handleSpecialFrame) - parentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); + parentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); } else { // No previous or next sibling, so treat this like an appended frame. @@ -8991,26 +8924,6 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, return NS_OK; } - // If the frame we are manipulating is a special frame then see if we need to reframe - // NOTE: if we are in ReinsertContent, then don't reframe as we are already doing just that! - if (handleSpecialFrame) { - // a special inline frame has propagated some of its children upward to be children - // of the block and those frames may need to move around. Sometimes we may need to reframe -#ifdef DEBUG - if (gNoisyContentUpdates) { - printf("nsCSSFrameConstructor::ContentInserted: parentFrame="); - nsFrame::ListTag(stdout, parentFrame); - printf(" is special\n"); - } -#endif - // if we don't need to reframe then set parentFrame and prevSibling to the correct values - if (NeedSpecialFrameReframe(aContainer, container, parentFrame, - aChild, aIndexInContainer, prevSibling, - nextSibling)) { - return ReframeContainingBlock(parentFrame); - } - } - nsFrameConstructorState state(mPresShell, mFixedContainingBlock, GetAbsoluteContainingBlock(parentFrame), GetFloatContainingBlock(parentFrame), @@ -9023,8 +8936,6 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, // is not the normal structure and requires custom updating // logic. nsIFrame* containingBlock = state.mFloatedItems.containingBlock; - nsStyleContext* blockSC; - nsIContent* blockContent = nsnull; PRBool haveFirstLetterStyle = PR_FALSE; PRBool haveFirstLineStyle = PR_FALSE; @@ -9077,33 +8988,6 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, ? FindNextSibling(container, parentFrame, aIndexInContainer, aChild) : FindNextAnonymousSibling(mPresShell, mDocument, aContainer, aChild); } - - handleSpecialFrame = IsFrameSpecial(parentFrame) && !aInReinsertContent; - if (handleSpecialFrame && - NeedSpecialFrameReframe(aContainer, container, parentFrame, - aChild, aIndexInContainer, prevSibling, - nextSibling)) { -#ifdef DEBUG - nsIContent* parentContainer = blockContent->GetParent(); - if (gNoisyContentUpdates) { - printf("nsCSSFrameConstructor::ContentInserted: parentFrame="); - nsFrame::ListTag(stdout, parentFrame); - printf(" is special inline\n"); - printf(" ==> blockContent=%p, parentContainer=%p\n", - static_cast(blockContent), - static_cast(parentContainer)); - } -#endif - - NS_ASSERTION(GetFloatContainingBlock(parentFrame) == containingBlock, - "Unexpected block ancestor for parentFrame"); - - // Note that in this case we're guaranteed that the closest block - // containing parentFrame is |containingBlock|. So - // ReframeContainingBlock(parentFrame) will make sure to rebuild the - // first-letter stuff we just blew away. - return ReframeContainingBlock(parentFrame); - } } } @@ -9145,8 +9029,13 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, // Perform special check for diddling around with the frames in // a special inline frame. - if (WipeContainingBlock(state, containingBlock, parentFrame, - frameItems.childList)) + // We can't have a block ::after inside an inline, so it's safe to ignore + // the fact that we're not really appending if there's ::after content. + // Indeed, if we're inserting before the ::after content that means the + // ::after content is not the last child of the block in the {ib} split, + // which is the only case in which we care whether we're appending. + if (WipeContainingBlock(state, containingBlock, parentFrame, frameItems, + isAppend, prevSibling)) return NS_OK; if (haveFirstLineStyle && parentFrame == containingBlock) { @@ -9164,7 +9053,7 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, } } - nsIFrame* newFrame = frameItems.childList; + nsIFrame* const newFrame = frameItems.childList; if (NS_SUCCEEDED(rv) && newFrame) { NS_ASSERTION(!captionItems.childList, "leaking caption frames"); if (!prevSibling) { @@ -9194,7 +9083,8 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, // Notify the parent frame if (isAppend) { - AppendFrames(state, aContainer, parentFrame, newFrame, appendAfterFrame); + AppendFrames(state, aContainer, parentFrame, frameItems, + appendAfterFrame); } else { state.mFrameManager->InsertFrames(parentFrame, nsnull, prevSibling, newFrame); @@ -9264,7 +9154,7 @@ nsCSSFrameConstructor::ReinsertContent(nsIContent* aContainer, nsresult res = ContentRemoved(aContainer, aChild, ix, PR_TRUE); if (NS_SUCCEEDED(res)) { - res = ContentInserted(aContainer, aChild, ix, nsnull, PR_TRUE); + res = ContentInserted(aContainer, aChild, ix, nsnull); } return res; @@ -9487,21 +9377,9 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // frames. // NOTE: if we are in ReinsertContent, // then do not reframe as we are already doing just that! - if (IsFrameSpecial(childFrame) && !aInReinsertContent) { - // We are pretty harsh here (and definitely not optimal) -- we - // wipe out the entire containing block and recreate it from - // scratch. The reason is that because we know that a special - // inline frame has propagated some of its children upward to be - // children of the block and that those frames may need to move - // around. This logic guarantees a correct answer. -#ifdef DEBUG - if (gNoisyContentUpdates) { - printf("nsCSSFrameConstructor::ContentRemoved: childFrame="); - nsFrame::ListTag(stdout, childFrame); - printf(" is special\n"); - } -#endif - return ReframeContainingBlock(childFrame); + if (!aInReinsertContent && + MaybeRecreateContainerForIBSplitterFrame(childFrame, &rv)) { + return rv; } // Get the childFrame's parent frame @@ -10910,9 +10788,7 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsFrameManager* aFrameManager, // that's been split because it contained a block), we need to // follow the out-of-flow "special sibling" link, and search // *that* subtree as well. - nsIFrame* specialSibling = nsnull; - GetSpecialSibling(aFrameManager, parentFrame, &specialSibling); - parentFrame = specialSibling; + parentFrame = GetSpecialSibling(parentFrame); } else { break; @@ -11056,19 +10932,49 @@ nsCSSFrameConstructor::MaybeRecreateFramesForContent(nsIContent* aContent) } PRBool -nsCSSFrameConstructor::MaybeRecreateContainerForIBSplitterFrame(nsIFrame* aFrame, nsresult* aResult) +nsCSSFrameConstructor::MaybeRecreateContainerForIBSplitterFrame(nsIFrame* aFrame, + nsresult* aResult) { - if (!aFrame || !IsFrameSpecial(aFrame)) + NS_PRECONDITION(aFrame, "Must have a frame"); + NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root"); + NS_PRECONDITION(aResult, "Null out param?"); + NS_PRECONDITION(aFrame == aFrame->GetFirstContinuation(), + "aFrame not the result of GetPrimaryFrameFor()?"); + + if (IsFrameSpecial(aFrame)) { + // The removal functions can't handle removal of an {ib} split directly; we + // need to rebuild the containing block. +#ifdef DEBUG + if (gNoisyContentUpdates) { + printf("nsCSSFrameConstructor::MaybeRecreateContainerForIBSplitterFrame: " + "frame="); + nsFrame::ListTag(stdout, aFrame); + printf(" is special\n"); + } +#endif + + *aResult = ReframeContainingBlock(aFrame); + return PR_TRUE; + } + + // We might still need to reconstruct things if the parent of aFrame is + // special, since in that case the removal of aFrame might affect the + // splitting of its parent. + nsIFrame* parent = aFrame->GetParent(); + if (!IsFrameSpecial(parent)) { return PR_FALSE; + } #ifdef DEBUG - if (gNoisyContentUpdates) { - printf("nsCSSFrameConstructor::RecreateFramesForContent: frame="); - nsFrame::ListTag(stdout, aFrame); + if (gNoisyContentUpdates || 1) { + printf("nsCSSFrameConstructor::MaybeRecreateContainerForIBSplitterFrame: " + "frame="); + nsFrame::ListTag(stdout, parent); printf(" is special\n"); } #endif - *aResult = ReframeContainingBlock(aFrame); + + *aResult = ReframeContainingBlock(parent); return PR_TRUE; } @@ -11086,23 +10992,15 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent) // block *here*, rather than trying to remove and re-insert the // content (which would otherwise result in *two* nested reframe // containing block from ContentRemoved() and ContentInserted(), - // below!) + // below!). We'd really like to optimize away one of those + // containing block reframes, hence the code here. nsIFrame* frame = mPresShell->GetPrimaryFrameFor(aContent); nsresult rv = NS_OK; - if (frame) { - // If the frame is an anonymous frame created as part of inline-in-block - // splitting --- or if its parent is such an anonymous frame (i.e., this - // frame might have been the cause of such splitting), then recreate the - // containing block. Note that if |frame| is an inline, then it can't - // possibly have caused the splitting, and if the inline is changing to a - // block, any reframing that's needed will happen in ContentInserted. - if (MaybeRecreateContainerForIBSplitterFrame(frame, &rv) || - (!IsInlineOutside(frame) && - MaybeRecreateContainerForIBSplitterFrame(frame->GetParent(), &rv))) - return rv; + if (frame && MaybeRecreateContainerForIBSplitterFrame(frame, &rv)) { + return rv; } nsCOMPtr container = aContent->GetParent(); @@ -11121,7 +11019,7 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent) if (NS_SUCCEEDED(rv)) { // Now, recreate the frames associated with this content object. rv = ContentInserted(container, aContent, - indexInContainer, mTempFrameTreeState, PR_FALSE); + indexInContainer, mTempFrameTreeState); } } else { // The content is the root node, so just rebuild the world. @@ -11952,8 +11850,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame( while (frame) { nsIFrame* nextFrame = frame->GetNextSibling(); - nsIAtom* frameType = frame->GetType(); - if (nsGkAtoms::textFrame == frameType) { + if (nsGkAtoms::textFrame == frame->GetType()) { // Wrap up first-letter content in a letter frame nsIContent* textContent = frame->GetContent(); if (IsFirstLetterContent(textContent)) { @@ -11972,9 +11869,7 @@ nsCSSFrameConstructor::WrapFramesInFirstLetterFrame( return NS_OK; } } - else if ((nsGkAtoms::inlineFrame == frameType) || - (nsGkAtoms::lineFrame == frameType) || - (nsGkAtoms::positionedInlineFrame == frameType)) { + else if (IsInlineFrame(frame)) { nsIFrame* kids = frame->GetFirstChild(nsnull); WrapFramesInFirstLetterFrame(aState, aBlockFrame, frame, kids, aModifiedParent, aTextFrame, @@ -12127,8 +12022,7 @@ nsCSSFrameConstructor::RemoveFirstLetterFrames(nsPresContext* aPresContext, nsIFrame* kid = aFrame->GetFirstChild(nsnull); while (kid) { - nsIAtom* frameType = kid->GetType(); - if (nsGkAtoms::letterFrame == frameType) { + if (nsGkAtoms::letterFrame == kid->GetType()) { // Bingo. Found it. First steal away the text frame. nsIFrame* textFrame = kid->GetFirstChild(nsnull); if (!textFrame) { @@ -12162,9 +12056,7 @@ nsCSSFrameConstructor::RemoveFirstLetterFrames(nsPresContext* aPresContext, *aStopLooking = PR_TRUE; break; } - else if ((nsGkAtoms::inlineFrame == frameType) || - (nsGkAtoms::lineFrame == frameType) || - (nsGkAtoms::positionedInlineFrame == frameType)) { + else if (IsInlineFrame(kid)) { // Look inside child inline frame for the letter frame RemoveFirstLetterFrames(aPresContext, aPresShell, aFrameManager, kid, aStopLooking); @@ -12516,47 +12408,31 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState, // parent block of the inline, but its parent pointer will be the anonymous // block we create... AdjustFloatParentPtrs() deals with this by moving the // float from the outer state |aState| to the inner |state|. - MoveChildrenTo(state.mFrameManager, blockSC, blockFrame, list2, &state, &aState); + MoveChildrenTo(state.mFrameManager, blockFrame, list2, &state, &aState); // list3's frames belong to another inline frame nsIFrame* inlineFrame = nsnull; + // If we ever start constructing a second inline in the split even when + // list3 is null, the logic in MaybeRecreateContainerForIBSplitterFrame + // needs to be adjusted. Also, if you're changing this code also change + // AppendFrames(). if (list3) { - if (aIsPositioned) { - inlineFrame = NS_NewPositionedInlineFrame(mPresShell, aStyleContext); - } - else { - inlineFrame = NS_NewInlineFrame(mPresShell, aStyleContext); - } - - InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, inlineFrame, PR_FALSE); - - // Any frame might need a view - // XXXbz should we be passing in a non-null aContentParentFrame? - nsHTMLContainerFrame::CreateViewForFrame(inlineFrame, nsnull, PR_FALSE); - - if (inlineFrame->HasView() || aNewFrame->HasView()) { - // Move list3's frames into the new view - nsHTMLContainerFrame::ReparentFrameViewList(aState.mPresContext, list3, - list3->GetParent(), inlineFrame); - } - - // Reparent (cheaply) the frames in list3 - we don't have to futz - // with their style context because they already have the right one. - inlineFrame->SetInitialChildList(nsnull, list3); - MoveChildrenTo(aState.mFrameManager, nsnull, inlineFrame, list3, nsnull, nsnull); + inlineFrame = MoveFramesToEndOfIBSplit(aState, nsnull, + aIsPositioned, aContent, + aStyleContext, list3, + blockFrame, nsnull); + } - // Mark the 3 frames as special. That way if any of the - // append/insert/remove methods try to fiddle with the children, the - // containing block will be reframed instead. + // Mark the frames as special (note: marking for inlineFrame is handled by + // MoveFramesToEndOfIBSplit). That way if any of the append/insert/remove + // methods try to fiddle with the children, the containing block will be + // reframed instead. SetFrameIsSpecial(aNewFrame, blockFrame); SetFrameIsSpecial(blockFrame, inlineFrame); MarkIBSpecialPrevSibling(aState.mPresContext, blockFrame, aNewFrame); - if (inlineFrame) - SetFrameIsSpecial(inlineFrame, nsnull); - #ifdef DEBUG if (gNoisyInlineConstruction) { nsIFrameDebug* frameDebug; @@ -12581,6 +12457,58 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState, return rv; } +nsIFrame* +nsCSSFrameConstructor::MoveFramesToEndOfIBSplit(nsFrameConstructorState& aState, + nsIFrame* aExistingEndFrame, + PRBool aIsPositioned, + nsIContent* aContent, + nsStyleContext* aStyleContext, + nsIFrame* aFramesToMove, + nsIFrame* aBlockPart, + nsFrameConstructorState* aTargetState) +{ + NS_PRECONDITION(aFramesToMove, "Must have frames to move"); + NS_PRECONDITION(aBlockPart, "Must have a block part"); + + nsIFrame* inlineFrame = aExistingEndFrame; + if (!inlineFrame) { + if (aIsPositioned) { + inlineFrame = NS_NewPositionedInlineFrame(mPresShell, aStyleContext); + } + else { + inlineFrame = NS_NewInlineFrame(mPresShell, aStyleContext); + } + + InitAndRestoreFrame(aState, aContent, aBlockPart->GetParent(), nsnull, + inlineFrame, PR_FALSE); + + // Any frame might need a view + // XXXbz should we be passing in a non-null aContentParentFrame? + nsHTMLContainerFrame::CreateViewForFrame(inlineFrame, nsnull, PR_FALSE); + } + + if (inlineFrame->HasView() || aFramesToMove->GetParent()->HasView()) { + // Move list3's frames into the new view + nsHTMLContainerFrame::ReparentFrameViewList(aState.mPresContext, + aFramesToMove, + aFramesToMove->GetParent(), + inlineFrame); + } + + // Reparent (cheaply) the frames in list3 + if (!inlineFrame->GetFirstChild(nsnull) && + (inlineFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) { + inlineFrame->SetInitialChildList(nsnull, aFramesToMove); + } else { + inlineFrame->InsertFrames(nsnull, nsnull, aFramesToMove); + } + nsFrameConstructorState* startState = aTargetState ? &aState : nsnull; + MoveChildrenTo(aState.mFrameManager, inlineFrame, aFramesToMove, + aTargetState, startState); + SetFrameIsSpecial(inlineFrame, nsnull); + return inlineFrame; +} + nsresult nsCSSFrameConstructor::ProcessInlineChildren(nsFrameConstructorState& aState, nsIContent* aContent, @@ -12676,24 +12604,57 @@ PRBool nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, nsIFrame* aContainingBlock, nsIFrame* aFrame, - nsIFrame* aFrameList) + const nsFrameItems& aFrameList, + PRBool aIsAppend, + nsIFrame* aPrevSibling) { + if (!aFrameList.childList) { + return PR_FALSE; + } + // Before we go and append the frames, check for a special // situation: an inline frame that will now contain block // frames. This is a no-no and the frame construction logic knows - // how to fix this. + // how to fix this. See defition of IsInlineFrame() for what "an + // inline" is. Whether we have "a block" is tested for by + // AreAllKidsInline. - // If we don't have a block within an inline, just return false. Here - // "an inline" is an actual inline frame (positioned or not) or a lineframe - // (corresponding to :first-line), since the latter should stop at the first - // block it runs into and we might be inserting one in the middle of it. - // Whether we have "a block" is tested for by AreAllKidsInline. - nsIAtom* frameType = aFrame->GetType(); - if ((frameType != nsGkAtoms::inlineFrame && - frameType != nsGkAtoms::positionedInlineFrame && - frameType != nsGkAtoms::lineFrame) || - AreAllKidsInline(aFrameList)) + // We also need to check for an append of content ending in an + // inline to the block in an {ib} split or an insert of content + // starting with an inline to the start of that block. If that + // happens, we also need to reframe, since that content needs to go + // into the following or preceding inline in the split. + + if (IsInlineFrame(aFrame)) { + // Nothing to do if all kids are inline + if (AreAllKidsInline(aFrameList.childList)) { + return PR_FALSE; + } + } else if (!IsFrameSpecial(aFrame)) { return PR_FALSE; + } else { + // aFrame is the block in an {ib} split. Check that we're not + // messing up either end of it. + if (aIsAppend) { + // Will be handled in AppendFrames() + return PR_FALSE; + } + + if (aPrevSibling && !aPrevSibling->GetNextSibling()) { + // This is an append that won't go through AppendFrames. We can bail out + // if the last frame we're appending is not inline + if (!aFrameList.lastChild->GetStyleDisplay()->IsInlineOutside()) { + return PR_FALSE; + } + } else { + // We can bail out if we're not inserting at the beginning or if + // the first frame we're inserting is not inline. + if (aPrevSibling || + !aFrameList.childList->GetStyleDisplay()->IsInlineOutside()) { + return PR_FALSE; + } + } + } // Ok, reverse tracks: wipe out the frames we just created nsFrameManager *frameManager = aState.mFrameManager; @@ -12702,7 +12663,7 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, // or entries in the undisplayed content map are removed frameManager->ClearAllUndisplayedContentIn(aFrame->GetContent()); - CleanupFrameReferences(frameManager, aFrameList); + CleanupFrameReferences(frameManager, aFrameList.childList); if (aState.mAbsoluteItems.childList) { CleanupFrameReferences(frameManager, aState.mAbsoluteItems.childList); } @@ -12717,7 +12678,7 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, CleanupFrameReferences(frameManager, aState.mPopupItems.childList); } #endif - nsFrameList tmp(aFrameList); + nsFrameList tmp(aFrameList.childList); tmp.DestroyFrames(); tmp.SetFrames(aState.mAbsoluteItems.childList); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index a2288586619..b9371b80cbd 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -111,8 +111,7 @@ public: nsresult ContentInserted(nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer, - nsILayoutHistoryState* aFrameState, - PRBool aInReinsertContent); + nsILayoutHistoryState* aFrameState); nsresult ContentRemoved(nsIContent* aContainer, nsIContent* aChild, @@ -305,10 +304,13 @@ private: nsIAtom* aPseudoElement, nsIFrame** aResult); - nsresult AppendFrames(const nsFrameConstructorState& aState, + // This method can change aFrameList: it can chop off the end and + // put it in a special sibling of aParentFrame. It can also change + // aState by moving some floats out of it. + nsresult AppendFrames(nsFrameConstructorState& aState, nsIContent* aContainer, nsIFrame* aParentFrame, - nsIFrame* aFrameList, + nsFrameItems& aFrameList, nsIFrame* aAfterFrame); // BEGIN TABLE SECTION @@ -754,7 +756,16 @@ private: nsresult RecreateFramesForContent(nsIContent* aContent); - PRBool MaybeRecreateContainerForIBSplitterFrame(nsIFrame* aFrame, nsresult* aResult); + // If removal of aFrame from the frame tree requires reconstruction of some + // containing block (either of aFrame or of its parent) due to {ib} splits, + // recreate the relevant containing block. The return value indicates + // whether this happened. If this method returns true, *aResult is the + // return value of ReframeContainingBlock. If this method returns false, the + // value of *aResult is no affected. aFrame and aResult must not be null. + // aFrame must be the result of a GetPrimaryFrameFor() call (which means its + // parent is also not null). + PRBool MaybeRecreateContainerForIBSplitterFrame(nsIFrame* aFrame, + nsresult* aResult); nsresult CreateContinuingOuterTableFrame(nsIPresShell* aPresShell, nsPresContext* aPresContext, @@ -828,6 +839,34 @@ private: PRBool aIsPositioned, nsIFrame* aNewFrame); + /** + * Move an already-constructed framelist into the inline frame at + * the tail end of an {ib} split. Creates said inline if it doesn't + * already exist. + * + * @param aState the frame construction state we're using right now. + * @param aExistingEndFrame if non-null, the already-existing end frame. + * @param aIsPositioned Whether the end frame should be positioned. + * @param aContent the content node for this {ib} split. + * @param aStyleContext the style context to use for the new frame + * @param aFramesToMove The frame list to move over + * @param aBlockPart the block part of the {ib} split. + * @param aTargetState if non-null, the target state to pass to + * MoveChildrenTo for float reparenting. + * XXXbz test float reparenting? + * + * @note aIsPositioned, aContent, aStyleContext, are + * only used if aExistingEndFrame is null. + */ + nsIFrame* MoveFramesToEndOfIBSplit(nsFrameConstructorState& aState, + nsIFrame* aExistingEndFrame, + PRBool aIsPositioned, + nsIContent* aContent, + nsStyleContext* aStyleContext, + nsIFrame* aFramesToMove, + nsIFrame* aBlockPart, + nsFrameConstructorState* aTargetState); + nsresult ProcessInlineChildren(nsFrameConstructorState& aState, nsIContent* aContent, nsIFrame* aFrame, @@ -837,18 +876,19 @@ private: PRBool AreAllKidsInline(nsIFrame* aFrameList); + // Determine whether we need to wipe out what we just did and start over + // because we're doing something like adding block kids to an inline frame + // (and therefore need an {ib} split). If aIsAppend is true, aPrevSibling is + // ignored. Otherwise it may be used to determine whether to reframe when + // inserting into the block of an {ib} split. + // @return PR_TRUE if we reconstructed the containing block, PR_FALSE + // otherwise PRBool WipeContainingBlock(nsFrameConstructorState& aState, - nsIFrame* blockContent, + nsIFrame* aContainingBlock, nsIFrame* aFrame, - nsIFrame* aFrameList); - - PRBool NeedSpecialFrameReframe(nsIContent* aParent1, - nsIContent* aParent2, - nsIFrame*& aParentFrame, - nsIContent* aChild, - PRInt32 aIndexInContainer, - nsIFrame*& aPrevSibling, - nsIFrame* aNextSibling); + const nsFrameItems& aFrameList, + PRBool aIsAppend, + nsIFrame* aPrevSibling); nsresult ReframeContainingBlock(nsIFrame* aFrame); diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 78a0d542ae3..6cb2780bf6c 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -2366,8 +2366,7 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) // Have the style sheet processor construct frame for the root // content object down - mFrameConstructor->ContentInserted(nsnull, root, 0, - nsnull, PR_FALSE); + mFrameConstructor->ContentInserted(nsnull, root, 0, nsnull); VERIFY_STYLE_TREE; MOZ_TIMER_DEBUGLOG(("Stop: Frame Creation: PresShell::InitialReflow(), this=%p\n", (void*)this)); @@ -4539,7 +4538,7 @@ PresShell::ContentInserted(nsIDocument* aDocument, WillCauseReflow(); mFrameConstructor->ContentInserted(aContainer, aChild, - aIndexInContainer, nsnull, PR_FALSE); + aIndexInContainer, nsnull); VERIFY_STYLE_TREE; DidCauseReflow(); } diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-10-ref.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-10-ref.html new file mode 100644 index 00000000000..edfd76a8abc --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-10-ref.html @@ -0,0 +1,23 @@ + + + + + + + OneTwoThree
Four
Five
Six
Seven
Eight
NineTen
+ + diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-10.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-10.html new file mode 100644 index 00000000000..7623be82e4f --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-10.html @@ -0,0 +1,29 @@ + + + + + + + + OneTwoThree
Four
Five
Six
Seven
Eight
+ + diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-11-ref.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-11-ref.html new file mode 100644 index 00000000000..ac41e37a4da --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-11-ref.html @@ -0,0 +1,25 @@ + + + + + + + OneTwoThree
Four
Five
Six
Seven
Eight
Nine
Ten
+ + diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-11.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-11.html new file mode 100644 index 00000000000..b3fce6051cb --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-11.html @@ -0,0 +1,31 @@ + + + + + + + + OneTwoThree
Four
Five
Six
Seven
Eight
Ten
+ + diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-8c.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-8c.html new file mode 100644 index 00000000000..3ba55b45917 --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-8c.html @@ -0,0 +1,24 @@ + + + + + + + +
Two
Three
Four
Five
+ + diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-9-ref.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-9-ref.html new file mode 100644 index 00000000000..5b6360f8f09 --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-9-ref.html @@ -0,0 +1,22 @@ + + + + + + + OneTwoThree
Four
Five
Six
Seven
Eight
Nine
+ + diff --git a/mozilla/layout/reftests/ib-split/insert-into-split-inline-9.html b/mozilla/layout/reftests/ib-split/insert-into-split-inline-9.html new file mode 100644 index 00000000000..ea543e8cfb6 --- /dev/null +++ b/mozilla/layout/reftests/ib-split/insert-into-split-inline-9.html @@ -0,0 +1,28 @@ + + + + + + + + OneTwoThree
Four
Five
Six
Seven
Eight
+ + diff --git a/mozilla/layout/reftests/ib-split/reftest.list b/mozilla/layout/reftests/ib-split/reftest.list index f5c151a8b4a..a174d63cabd 100644 --- a/mozilla/layout/reftests/ib-split/reftest.list +++ b/mozilla/layout/reftests/ib-split/reftest.list @@ -32,3 +32,7 @@ == insert-into-split-inline-7.html insert-into-split-inline-7-ref.html == insert-into-split-inline-8a.html insert-into-split-inline-8-ref.html == insert-into-split-inline-8b.html insert-into-split-inline-8-ref.html +== insert-into-split-inline-8c.html insert-into-split-inline-8-ref.html +== insert-into-split-inline-9.html insert-into-split-inline-9-ref.html +== insert-into-split-inline-10.html insert-into-split-inline-10-ref.html +== insert-into-split-inline-11.html insert-into-split-inline-11-ref.html diff --git a/mozilla/layout/reftests/reftest.list b/mozilla/layout/reftests/reftest.list index 4a64f88f78c..31ca8782c6f 100644 --- a/mozilla/layout/reftests/reftest.list +++ b/mozilla/layout/reftests/reftest.list @@ -63,4 +63,4 @@ include columns/reftest.list include image-region/reftest.list # block-inside-inline splits -#include ib-split/reftest.list +include ib-split/reftest.list diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index 7b9c5c2d694..20a198e6c15 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -2991,6 +2991,9 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, // XXX These restrictions are no longer present in CSS2.1. We // should ensure that we support removing them before doing so, // though. + // XXXbz For example, the calls to WipeContainingBlock in the + // frame constructor will need to be changedif we allow + // block-level generated content inside inlines. if (display->mPosition != NS_STYLE_POSITION_STATIC) display->mPosition = NS_STYLE_POSITION_STATIC;