diff --git a/mozilla/layout/base/nsBidiPresUtils.cpp b/mozilla/layout/base/nsBidiPresUtils.cpp index 2f2f014c917..121efd3664b 100644 --- a/mozilla/layout/base/nsBidiPresUtils.cpp +++ b/mozilla/layout/base/nsBidiPresUtils.cpp @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Uri Bernstein * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -47,6 +48,7 @@ #include "nsFrameManager.h" #include "nsBidiFrames.h" #include "nsBidiUtils.h" +#include "nsCSSFrameConstructor.h" static const PRUnichar kSpace = 0x0020; static const PRUnichar kLineSeparator = 0x2028; @@ -61,8 +63,6 @@ static const PRUnichar ALEF = 0x05D0; #define CHAR_IS_HEBREW(c) ((0x0590 <= (c)) && ((c)<= 0x05FF)) // Note: The above code are moved from gfx/src/windows/nsRenderingContextWin.cpp -nsIFrame* -NS_NewContinuingTextFrame(nsIPresShell* aPresShell); nsIFrame* NS_NewDirectionalFrame(nsIPresShell* aPresShell, PRUnichar aChar); @@ -97,40 +97,82 @@ nsBidiPresUtils::IsSuccessful() const /* Some helper methods for Resolve() */ +static nsresult +SplitInlineAncestors(nsPresContext* aPresContext, + nsIFrame* aFrame) +{ + nsIPresShell *presShell = aPresContext->PresShell(); + nsIFrame* frame = aFrame; + nsIFrame* parent = aFrame->GetParent(); + nsIFrame* newFrame = aFrame->GetNextSibling(); + nsIFrame* newParent; + + while (nsLayoutAtoms::inlineFrame == parent->GetType() || + nsLayoutAtoms::positionedInlineFrame == parent->GetType()) { + + nsIFrame* grandparent = parent->GetParent(); + NS_ASSERTION(grandparent, "Couldn't get parent's parent in nsBidiPresUtils::SplitInlineAncestors"); + + nsresult rv = presShell->FrameConstructor()-> + CreateContinuingFrame(aPresContext, parent, grandparent, &newParent, PR_FALSE); + if (NS_FAILED(rv)) { + return rv; + } + + // The new parent adopts the new frame + frame->SetNextSibling(nsnull); + rv = newParent->InsertFrames(nsLayoutAtoms::nextBidi, nsnull, newFrame); + if (NS_FAILED(rv)) { + return rv; + } + + // The list name nsLayoutAtoms::nextBidi would indicate we don't want reflow + rv = grandparent->InsertFrames(nsLayoutAtoms::nextBidi, parent, newParent); + if (NS_FAILED(rv)) { + return rv; + } + + frame = parent; + newFrame = newParent; + parent = grandparent; + } + + return NS_OK; +} + static nsresult CreateBidiContinuation(nsPresContext* aPresContext, - nsIContent* aContent, nsIFrame* aFrame, nsIFrame** aNewFrame) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); + NS_PRECONDITION(aFrame, "null ptr"); *aNewFrame = nsnull; - NS_PRECONDITION(aFrame, "null ptr"); - nsIPresShell *presShell = aPresContext->PresShell(); - NS_ASSERTION(presShell, "PresShell must be set on PresContext before calling nsBidiPresUtils::CreateBidiContinuation"); - *aNewFrame = NS_NewContinuingTextFrame(presShell); - if (!(*aNewFrame) ) { - return NS_ERROR_OUT_OF_MEMORY; - } - nsStyleContext* styleContext = aFrame->GetStyleContext(); - - NS_ASSERTION(styleContext, "Frame has no styleContext in nsBidiPresUtils::CreateBidiContinuation"); - nsIFrame* parent = aFrame->GetParent(); NS_ASSERTION(parent, "Couldn't get frame parent in nsBidiPresUtils::CreateBidiContinuation"); - - (*aNewFrame)->Init(aPresContext, aContent, parent, styleContext, nsnull); - - // XXX: TODO: Instead, create and insert entire frame list - (*aNewFrame)->SetNextSibling(nsnull); - + + nsresult rv = presShell->FrameConstructor()-> + CreateContinuingFrame(aPresContext, aFrame, parent, aNewFrame, PR_FALSE); + if (NS_FAILED(rv)) { + return rv; + } + // The list name nsLayoutAtoms::nextBidi would indicate we don't want reflow - parent->InsertFrames(nsLayoutAtoms::nextBidi, aFrame, *aNewFrame); + rv = parent->InsertFrames(nsLayoutAtoms::nextBidi, aFrame, *aNewFrame); + if (NS_FAILED(rv)) { + return rv; + } + + // Split inline ancestor frames + rv = SplitInlineAncestors(aPresContext, aFrame); + if (NS_FAILED(rv)) { + return rv; + } return NS_OK; } @@ -309,6 +351,7 @@ nsBidiPresUtils::Resolve(nsPresContext* aPresContext, if (nsLayoutAtoms::directionalFrame == frameType) { frame->Destroy(aPresContext); + frame = nsnull; ++lineOffset; } else { @@ -356,10 +399,40 @@ nsBidiPresUtils::Resolve(nsPresContext* aPresContext, temp = runLength; runLength -= fragmentLength; fragmentLength -= temp; + + // If the frame is at the end of a run, split all ancestor inlines that need splitting. + if (frame && fragmentLength <= 0 && runLength <= 0) { + // As long as we're on the last sibling, the parent doesn't have to be split. + nsIFrame* child = frame; + nsIFrame* parent = frame->GetParent(); + while (parent && + (nsLayoutAtoms::inlineFrame == parent->GetType() || + nsLayoutAtoms::positionedInlineFrame == parent->GetType()) && + !child->GetNextSibling()) { + child = parent; + parent = child->GetParent(); + } + if (parent && + (nsLayoutAtoms::inlineFrame == parent->GetType() || + nsLayoutAtoms::positionedInlineFrame == parent->GetType())) + SplitInlineAncestors(aPresContext, child); + } } // for return mSuccess; } +// Should this frame be treated as a leaf (e.g. when building mLogicalArray)? +PRBool IsBidiLeaf(nsIFrame* aFrame) { + nsIAtom* frameType = aFrame->GetType(); + nsIFrame* kid = aFrame->GetFirstChild(nsnull); + return !kid + || aFrame->GetStyleDisplay()->IsBlockLevel() + || !(nsLayoutAtoms::inlineFrame == frameType + || nsLayoutAtoms::positionedInlineFrame == frameType + || nsLayoutAtoms::letterFrame == frameType + || nsLayoutAtoms::blockFrame == frameType); +} + nsresult nsBidiPresUtils::InitLogicalArray(nsPresContext* aPresContext, nsIFrame* aCurrentFrame, @@ -402,22 +475,14 @@ nsBidiPresUtils::InitLogicalArray(nsPresContext* aPresContext, break; } - if (directionalFrame) { + // Create a directional frame before the first frame of an + // element specifying embedding or override + if (directionalFrame && !frame->GetPrevContinuation()) { mLogicalFrames.AppendElement(directionalFrame); } } - nsIAtom* frameType = frame->GetType(); - - if ( (!display->IsBlockLevel() ) - && ( (nsLayoutAtoms::inlineFrame == frameType) - || (nsLayoutAtoms::positionedInlineFrame == frameType) - || (nsLayoutAtoms::letterFrame == frameType) - || (nsLayoutAtoms::blockFrame == frameType) ) ) { - nsIFrame* kid = frame->GetFirstChild(nsnull); - res = InitLogicalArray(aPresContext, kid, aNextInFlow, aAddMarkers); - } - else { + if (IsBidiLeaf(frame)) { /* Bidi leaf frame: add the frame to the mLogicalFrames array, * and add its index to the mContentToFrameIndex hashtable. This * will be used in RemoveBidiContinuation() to identify the last @@ -429,12 +494,18 @@ nsBidiPresUtils::InitLogicalArray(nsPresContext* aPresContext, } mLogicalFrames.AppendElement(frame); } + else { + nsIFrame* kid = frame->GetFirstChild(nsnull); + res = InitLogicalArray(aPresContext, kid, aNextInFlow, aAddMarkers); + } // If the element is attributed by dir, indicate direction pop (add PDF frame) if (directionalFrame) { directionalFrame = NS_NewDirectionalFrame(shell, kPDF); - if (directionalFrame) { + // Create a directional frame after the last frame of an + // element specifying embedding or override + if (directionalFrame && !frame->GetNextContinuation()) { mLogicalFrames.AppendElement(directionalFrame); } } @@ -497,27 +568,25 @@ void nsBidiPresUtils::ReorderFrames(nsPresContext* aPresContext, nsIRenderingContext* aRendContext, nsIFrame* aFirstChild, - nsIFrame* aNextInFlow, - PRInt32 aChildCount) + nsIFrame* aNextInFlow) { mLogicalFrames.Clear(); - if (NS_SUCCEEDED(InitLogicalArray(aPresContext, aFirstChild, aNextInFlow)) - && (mLogicalFrames.Count() > 1)) { - PRBool bidiEnabled; - // Set bidiEnabled to true if the line is reordered - Reorder(aPresContext, bidiEnabled); - if (bidiEnabled) { - RepositionInlineFrames(aPresContext, aRendContext, aFirstChild, aChildCount); - } + for (nsIFrame* frame = aFirstChild; + frame && frame != aNextInFlow; + frame = frame->GetNextSibling()) { + mLogicalFrames.AppendElement(frame); } + + PRBool reordered; + Reorder(reordered); + RepositionInlineFrames(aPresContext, aRendContext, aFirstChild, reordered); } nsresult -nsBidiPresUtils::Reorder(nsPresContext* aPresContext, - PRBool& aBidiEnabled) +nsBidiPresUtils::Reorder(PRBool& aReordered) { - aBidiEnabled = PR_FALSE; + aReordered = PR_FALSE; PRInt32 count = mLogicalFrames.Count(); if (mArraySize < count) { @@ -544,7 +613,11 @@ nsBidiPresUtils::Reorder(nsPresContext* aPresContext, for (i = 0; i < count; i++) { frame = (nsIFrame*) (mLogicalFrames[i]); - mLevels[i] = NS_GET_EMBEDDING_LEVEL(frame); + nsIFrame* firstLeaf = frame; + while (!IsBidiLeaf(firstLeaf)) { + firstLeaf = firstLeaf->GetFirstChild(nsnull); + } + mLevels[i] = NS_GET_EMBEDDING_LEVEL(firstLeaf); } if (!mIndexMap) { mIndexMap = new PRInt32[mArraySize]; @@ -563,166 +636,59 @@ nsBidiPresUtils::Reorder(nsPresContext* aPresContext, for (i = 0; i < count; i++) { mVisualFrames.AppendElement(mLogicalFrames[mIndexMap[i]]); if (i != mIndexMap[i]) { - aBidiEnabled = PR_TRUE; + aReordered = PR_TRUE; } } } // NS_SUCCEEDED(mSuccess) } // indexMap if (NS_FAILED(mSuccess) ) { - aBidiEnabled = PR_FALSE; + aReordered = PR_FALSE; } return mSuccess; } -void -nsBidiPresUtils::RepositionInlineFrames(nsPresContext* aPresContext, - nsIRenderingContext* aRendContext, - nsIFrame* aFirstChild, - PRInt32 aChildCount) const +static void +ReverseChildFramesPositioning(nsIFrame* aFirstChild) { - PRInt32 count = mVisualFrames.Count(); - if (count < 2) { + if (!aFirstChild) return; - } - nsIFrame* frame = (nsIFrame*) (mVisualFrames[0]); - PRInt32 i; - - PRInt32 ch; - PRInt32 charType; - nscoord width, dWidth, alefWidth, dx; - PRUnichar buf[2] = {ALEF, 0x0000}; - - PRBool isBidiSystem; - PRUint32 hints = 0; - - dWidth = alefWidth = dx = 0; - aRendContext->GetHints(hints); - isBidiSystem = (hints & NS_RENDERING_HINT_BIDI_REORDERING); - - nsRect rect = frame->GetRect(); - - if (frame != aFirstChild) { - rect.x = aFirstChild->GetPosition().x; - frame->SetPosition(nsPoint(rect.x, rect.y)); - } - - nsPropertyTable *propTable = aPresContext->PropertyTable(); - - for (i = 1; i < count; i++) { - - ch = 0; - charType = NS_PTR_TO_INT32(propTable->GetProperty((nsIFrame*)mVisualFrames[i], nsLayoutAtoms::charType)); - if (CHARTYPE_IS_RTL(charType) ) { - ch = NS_PTR_TO_INT32(propTable->GetProperty(frame, - nsLayoutAtoms::endsInDiacritic)); - if (ch) { - if (!alefWidth) { - aRendContext->GetWidth(buf, 1, alefWidth, nsnull); - } - dWidth = 0; - if (isBidiSystem) { - buf[1] = (PRUnichar) ch; - aRendContext->GetWidth(buf, 2, width, nsnull); - dWidth = width - alefWidth; - } - if (dWidth <= 0) { - frame->SetPosition(nsPoint(rect.x + (nscoord)((float)width/8), rect.y)); - } - } - } - frame = (nsIFrame*) (mVisualFrames[i]); - if (ch) { - dx += (rect.width - dWidth); - frame->SetPosition(nsPoint(rect.x + dWidth, frame->GetPosition().y)); - } else - frame->SetPosition(nsPoint(rect.XMost(), frame->GetPosition().y)); - rect = frame->GetRect(); - } // for - - if (dx > 0) { - PRInt32 alignRight = NS_GET_BASE_LEVEL(frame); - if (0 == (alignRight & 1) ) { - const nsStyleText* styleText = frame->GetStyleText(); - - if (NS_STYLE_TEXT_ALIGN_RIGHT == styleText->mTextAlign - || NS_STYLE_TEXT_ALIGN_MOZ_RIGHT == styleText->mTextAlign) { - alignRight = 1; - } - } - if (alignRight & 1) { - for (i = 0; i < count; i++) { - frame = (nsIFrame*) (mVisualFrames[i]); - frame->SetPosition(frame->GetPosition() + nsPoint(dx, 0)); - } - } - } - // Now adjust inline container frames. - // Example: LTR paragraph - //

english HEBREW 123

- // should be displayed as - //

english 123 WERBEH

- - // We assume that rectangle takes all the room from "english" left edge to - // "WERBEH" right edge. - - frame = aFirstChild; - for (i = 0; i < aChildCount; i++) { - nsIAtom* frameType = frame->GetType(); - if ( (nsLayoutAtoms::inlineFrame == frameType) - || (nsLayoutAtoms::positionedInlineFrame == frameType) - || (nsLayoutAtoms::letterFrame == frameType) - || (nsLayoutAtoms::blockFrame == frameType) ) { - PRInt32 minX = 0x7FFFFFFF; - PRInt32 maxX = 0; - RepositionContainerFrame(aPresContext, frame, minX, maxX); - } - frame = frame->GetNextSibling(); - } // for + // Get the right edge of the last sibling + nsIFrame* lastSibling; + for (lastSibling = aFirstChild; lastSibling->GetNextSibling(); lastSibling = lastSibling->GetNextSibling()) + ; + nscoord right = lastSibling->GetRect().XMost(); + + nsIFrame* frame; + for (frame = aFirstChild; frame; frame = frame->GetNextSibling()) { + right -= frame->GetRect().width; + frame->SetPosition(nsPoint(right, frame->GetPosition().y)); + if (!IsBidiLeaf(frame)) + ReverseChildFramesPositioning(frame->GetFirstChild(nsnull)); + } } void -nsBidiPresUtils::RepositionContainerFrame(nsPresContext* aPresContext, - nsIFrame* aContainer, - PRInt32& aMinX, - PRInt32& aMaxX) const +nsBidiPresUtils::RepositionInlineFrames(nsPresContext* aPresContext, + nsIRenderingContext* aRendContext, + nsIFrame* aFirstChild, + PRBool aReordered) const { + PRInt32 count = mVisualFrames.Count(); + nscoord left = aFirstChild->GetPosition().x; nsIFrame* frame; - PRInt32 minX = 0x7FFFFFFF; - PRInt32 maxX = 0; + + for (PRInt32 i = 0; i < count; i++) { + frame = (nsIFrame*) (mVisualFrames[i]); + if (aReordered) // Don't touch positioning if no reordering was done, to avoid killing margins. + frame->SetPosition(nsPoint(left, frame->GetPosition().y)); + left += frame->GetRect().width; - nsIFrame* firstChild = aContainer->GetFirstChild(nsnull); - - for (frame = firstChild; frame; frame = frame->GetNextSibling()) { - nsIAtom* frameType = frame->GetType(); - if ( (nsLayoutAtoms::inlineFrame == frameType) - || (nsLayoutAtoms::positionedInlineFrame == frameType) - || (nsLayoutAtoms::letterFrame == frameType) - || (nsLayoutAtoms::blockFrame == frameType) ) { - RepositionContainerFrame(aPresContext, frame, minX, maxX); - } - else { - nsRect rect = frame->GetRect(); - minX = PR_MIN(minX, rect.x); - maxX = PR_MAX(maxX, rect.XMost()); - } - } - - aMinX = PR_MIN(minX, aMinX); - aMaxX = PR_MAX(maxX, aMaxX); - - if (minX < maxX) { - nsRect rect = aContainer->GetRect(); - rect.x = minX; - rect.width = maxX - minX; - aContainer->SetRect(rect); - } - - // Now adjust all the kids (kid's coordinates are relative to the parent's) - for (frame = firstChild; frame; frame = frame->GetNextSibling()) { - frame->SetPosition(frame->GetPosition() - nsPoint(minX, 0)); - } + // If this is an odd-level frame, reverse the positioning of its childern + if ((mLevels[mIndexMap[i]] & 1) && !IsBidiLeaf(frame)) + ReverseChildFramesPositioning(frame->GetFirstChild(nsnull)); + } // for } PRBool @@ -746,19 +712,30 @@ nsBidiPresUtils::EnsureBidiContinuation(nsPresContext* aPresContext, if (frame->GetContent() == aContent) { *aNewFrame = frame; ++aFrameIndex; - aFrame->SetNextInFlow(nsnull); - frame->SetPrevInFlow(nsnull); + aFrame->SetNextContinuation(frame); + frame->SetPrevContinuation(aFrame); + + // Make existing parent continuations non-fluid + nsIFrame* parent = frame->GetParent(); + while (parent && + (nsLayoutAtoms::inlineFrame == parent->GetType() || + nsLayoutAtoms::positionedInlineFrame == parent->GetType())) { + nsIFrame* prevContinuation = parent->GetPrevContinuation(); + if (prevContinuation) { + parent->SetPrevContinuation(prevContinuation); + prevContinuation->SetNextContinuation(parent); + } + parent = parent->GetParent(); + } } } - if (nsnull == *aNewFrame) { - mSuccess = CreateBidiContinuation(aPresContext, aContent, aFrame, aNewFrame); + if (!*aNewFrame) { + mSuccess = CreateBidiContinuation(aPresContext, aFrame, aNewFrame); if (NS_FAILED(mSuccess) ) { return PR_FALSE; } } - aPresContext->PropertyTable()->SetProperty(aFrame, nsLayoutAtoms::nextBidi, - (void*) *aNewFrame, - nsnull, nsnull); + return PR_TRUE; } @@ -771,7 +748,6 @@ nsBidiPresUtils::RemoveBidiContinuation(nsPresContext* aPresContext, { nsIFrame* frame; PRInt32 index; - nsIFrame* parent = aFrame->GetParent(); aOffset = 0; @@ -784,37 +760,23 @@ nsBidiPresUtils::RemoveBidiContinuation(nsPresContext* aPresContext, else { if (frame->GetStateBits() & NS_FRAME_IS_BIDI) { // only delete Bidi frames - if (parent) { - parent->RemoveFrame(nsLayoutAtoms::nextBidi, frame); - } - else { - frame->Destroy(aPresContext); + nsIFrame* parent = frame->GetParent(); + parent->RemoveFrame(nsLayoutAtoms::nextBidi, frame); + // Make parent continuations fluid, so they can be + // reused or deleted by inline reflow code + while (parent) { + nsIFrame* parentPrev = parent->GetPrevContinuation(); + if (parentPrev) { + parent->SetPrevInFlow(parentPrev); + parentPrev->SetNextInFlow(parent); + parent = parent->GetParent(); + } else { + break; + } } } } } - nsIFrame* thisFramesNextBidiFrame; - nsIFrame* previousFramesNextBidiFrame; - - nsPropertyTable *propTable = aPresContext->PropertyTable(); - thisFramesNextBidiFrame = NS_STATIC_CAST(nsIFrame*, - propTable->GetProperty(aFrame, nsLayoutAtoms::nextBidi)); - - if (thisFramesNextBidiFrame) { - // Remove nextBidi property, associated with the current frame - // and with all of its prev-in-flow. - frame = aFrame; - do { - propTable->DeleteProperty(frame, nsLayoutAtoms::nextBidi); - frame = frame->GetPrevInFlow(); - if (!frame) { - break; - } - previousFramesNextBidiFrame = - NS_STATIC_CAST(nsIFrame*, propTable->GetProperty(frame, - nsLayoutAtoms::nextBidi)); - } while (thisFramesNextBidiFrame == previousFramesNextBidiFrame); - } // if (thisFramesNextBidiFrame) } nsresult diff --git a/mozilla/layout/base/nsBidiPresUtils.h b/mozilla/layout/base/nsBidiPresUtils.h index 226848a1108..7d0d050c117 100644 --- a/mozilla/layout/base/nsBidiPresUtils.h +++ b/mozilla/layout/base/nsBidiPresUtils.h @@ -102,8 +102,7 @@ public: void ReorderFrames(nsPresContext* aPresContext, nsIRenderingContext* aRendContext, nsIFrame* aFirstChild, - nsIFrame* aNextInFlow, - PRInt32 aChildCount); + nsIFrame* aNextInFlow); /** * Format Unicode text, taking into account bidi capabilities @@ -180,13 +179,11 @@ private: PRBool aAddMarkers = PR_FALSE); /** * Reorder the frame array from logical to visual order - * - * @param aPresContext the presentation context - * @param aBidiEnabled TRUE on return if the visual order is different from - * the logical order + * + * @param aReordered TRUE on return if the visual order is different from + * the logical order */ - nsresult Reorder(nsPresContext* aPresContext, - PRBool& aBidiEnabled); + nsresult Reorder(PRBool& aReordered); /** * Adjust frame positions following their visual order @@ -198,7 +195,7 @@ private: void RepositionInlineFrames(nsPresContext* aPresContext, nsIRenderingContext* aRendContext, nsIFrame* aFirstChild, - PRInt32 aChildCount) const; + PRBool aReordered) const; void RepositionContainerFrame(nsPresContext* aPresContext, nsIFrame* aContainer, diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index ba471bc6d4f..fe88591b568 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -500,7 +500,7 @@ GetLastSpecialSibling(nsFrameManager* aFrameManager, nsIFrame* aFrame) static nsIFrame* GetNifOrSpecialSibling(nsFrameManager *aFrameManager, nsIFrame *aFrame) { - nsIFrame *result = aFrame->GetNextInFlow(); + nsIFrame *result = aFrame->GetNextContinuation(); if (result) return result; @@ -515,7 +515,7 @@ SetFrameIsSpecial(nsIFrame* aFrame, nsIFrame* aSpecialSibling) NS_PRECONDITION(aFrame, "bad args!"); // Mark the frame and all of its siblings as "special". - for (nsIFrame* frame = aFrame; frame != nsnull; frame = frame->GetNextInFlow()) { + for (nsIFrame* frame = aFrame; frame != nsnull; frame = frame->GetNextContinuation()) { frame->AddStateBits(NS_FRAME_IS_SPECIAL); } @@ -8526,8 +8526,8 @@ FindPreviousAnonymousSibling(nsIPresShell* aPresShell, } // The frame may have a continuation. If so, we want the - // last-in-flow as our previous sibling. - prevSibling = prevSibling->GetLastInFlow(); + // last continuation as our previous sibling. + prevSibling = prevSibling->GetLastContinuation(); // If the frame is out-of-flow, GPFF() will have returned the // out-of-flow frame; we want the placeholder. @@ -8701,8 +8701,8 @@ nsCSSFrameConstructor::FindPreviousSibling(nsIContent* aContainer, prevSibling); } - // The frame may have a continuation. Get the last-in-flow - prevSibling = prevSibling->GetLastInFlow(); + // The frame may have a continuation. Get the last continuation + prevSibling = prevSibling->GetLastContinuation(); // XXXbz should the IsValidSibling check be after we get the // placeholder for out-of-flows? @@ -9031,8 +9031,8 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, } } - // Get the parent frame's last-in-flow - parentFrame = parentFrame->GetLastInFlow(); + // Get the parent frame's last continuation + parentFrame = parentFrame->GetLastContinuation(); nsIAtom* frameType = parentFrame->GetType(); // Deal with inner/outer tables, fieldsets @@ -9902,7 +9902,7 @@ DeletingFrameSubtree(nsPresContext* aPresContext, // recursing over a subtree, because those continuing frames should be // found as part of the walk over the top-most frame's continuing frames. // Walking them again will make this an N^2/2 algorithm. - aFrame = aFrame->GetNextInFlow(); + aFrame = aFrame->GetNextContinuation(); } while (aFrame); // Now destroy any out-of-flow frames that have been enqueued for @@ -11028,12 +11028,14 @@ nsresult nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext, nsIFrame* aFrame, nsIFrame* aParentFrame, - nsIFrame** aContinuingFrame) + nsIFrame** aContinuingFrame, + PRBool aIsFluid) { nsIPresShell* shell = aPresContext->PresShell(); nsStyleContext* styleContext = aFrame->GetStyleContext(); nsIFrame* newFrame = nsnull; nsresult rv = NS_OK; + nsIFrame* nextContinuation = aFrame->GetNextContinuation(); nsIFrame* nextInFlow = aFrame->GetNextInFlow(); // Use the frame type to determine what type of frame to create @@ -11228,6 +11230,13 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext, return NS_ERROR_OUT_OF_MEMORY; } + // Init() set newFrame to be a fluid continuation of aFrame. + // If we want a non-fluid continuation, we need to call SetPrevContinuation() + // to reset NS_FRAME_IS_FLUID_CONTINUATION. + if (!aIsFluid) { + newFrame->SetPrevContinuation(aFrame); + } + // Now deal with fixed-pos things.... They should appear on all pages, and // the placeholders must be kids of a block, so we want to move over the // placeholders when processing the child of the pageContentFrame. @@ -11239,6 +11248,9 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext, if (nextInFlow) { nextInFlow->SetPrevInFlow(newFrame); newFrame->SetNextInFlow(nextInFlow); + } else if (nextContinuation) { + nextContinuation->SetPrevContinuation(newFrame); + newFrame->SetNextContinuation(nextContinuation); } return NS_OK; } diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index e41bc4426e4..66ba00a8433 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -153,7 +153,8 @@ public: nsresult CreateContinuingFrame(nsPresContext* aPresContext, nsIFrame* aFrame, nsIFrame* aParentFrame, - nsIFrame** aContinuingFrame); + nsIFrame** aContinuingFrame, + PRBool aIsFluid = PR_TRUE); // Request to find the primary frame associated with a given content object. // This is typically called by the pres shell when there is no mapping in diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index c7fcf4fa75e..ef6bb27b9b0 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -668,21 +668,8 @@ nsFrameManager::InsertFrames(nsIFrame* aParentFrame, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { -#ifdef IBMBIDI - if (aPrevFrame) { - // Insert aFrameList after the last bidi continuation of aPrevFrame. - nsPropertyTable *propTable = GetPresContext()->PropertyTable(); - nsIFrame* nextBidi; - for (; ;) { - nextBidi = NS_STATIC_CAST(nsIFrame*, - propTable->GetProperty(aPrevFrame, nsLayoutAtoms::nextBidi)); - if (!nextBidi) { - break; - } - aPrevFrame = nextBidi; - } - } -#endif // IBMBIDI + NS_PRECONDITION(!aPrevFrame || !aPrevFrame->GetNextContinuation(), + "aPrevFrame must be the last continuation in its chain!"); return aParentFrame->InsertFrames(aListName, aPrevFrame, aFrameList); } @@ -692,15 +679,6 @@ nsFrameManager::RemoveFrame(nsIFrame* aParentFrame, nsIAtom* aListName, nsIFrame* aOldFrame) { -#ifdef IBMBIDI - // Don't let the parent remove next bidi. In the other cases the it should NOT be removed. - nsIFrame* nextBidi = - NS_STATIC_CAST(nsIFrame*, aOldFrame->GetProperty(nsLayoutAtoms::nextBidi)); - if (nextBidi) { - RemoveFrame(aParentFrame, aListName, nextBidi); - } -#endif // IBMBIDI - return aParentFrame->RemoveFrame(aListName, aOldFrame); } @@ -1257,7 +1235,7 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext, !aFrame->IsLeaf()) { // Check for new :after content, but only if the frame is the // last-in-flow. - nsIFrame* nextInFlow = aFrame->GetNextInFlow(); + nsIFrame* nextInFlow = aFrame->GetNextContinuation(); if (!nextInFlow) { // Getting the :after frame is more expensive than getting the pseudo @@ -1355,7 +1333,7 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame, nsIFrame* frame = aFrame; nsIFrame* frame2 = aFrame; - NS_ASSERTION(!frame->GetPrevInFlow(), "must start with the first in flow"); + NS_ASSERTION(!frame->GetPrevContinuation(), "must start with the first in flow"); // We want to start with this frame and walk all its next-in-flows, // as well as all its special siblings and their next-in-flows, @@ -1376,12 +1354,12 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame, // If it's going to cause a framechange, then don't bother // with the continuations or special siblings since they'll be // clobbered by the frame reconstruct anyway. - NS_ASSERTION(!frame->GetPrevInFlow(), + NS_ASSERTION(!frame->GetPrevContinuation(), "continuing frame had more severe impact than first-in-flow"); return topLevelChange; } - frame = frame->GetNextInFlow(); + frame = frame->GetNextContinuation(); } while (frame); // Might we have special siblings? diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 0d179161412..65fe2a6bb0c 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -367,11 +367,11 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const } // Output the flow linkage - if (nsnull != mPrevInFlow) { - fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, mPrevInFlow)); + if (nsnull != GetPrevInFlow()) { + fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, GetPrevInFlow())); } - if (nsnull != mNextInFlow) { - fprintf(out, " next-in-flow=%p", NS_STATIC_CAST(void*, mNextInFlow)); + if (nsnull != GetNextInFlow()) { + fprintf(out, " next-in-flow=%p", NS_STATIC_CAST(void*, GetNextInFlow())); } // Output the rect and state @@ -734,7 +734,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext, aMetrics.descent = aMetrics.height - aMetrics.ascent; // Whether or not we're complete hasn't changed - aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE; + aStatus = (nsnull != GetNextInFlow()) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE; // Factor the absolutely positioned child bounds into the overflow area ComputeCombinedArea(aReflowState, aMetrics); @@ -1365,11 +1365,11 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // Figure out how much of the computed height should be // applied to this frame. nscoord computedHeightLeftOver = aReflowState.mComputedHeight; - if (mPrevInFlow) { + if (GetPrevInFlow()) { // Reduce the height by the computed height of prev-in-flows. - for (nsIFrame* prev = mPrevInFlow; prev; prev = prev->GetPrevInFlow()) { + for (nsIFrame* prev = GetPrevInFlow(); prev; prev = prev->GetPrevInFlow()) { nscoord contentHeight = prev->GetRect().height; - if (prev == mPrevInFlow) { + if (prev == GetPrevInFlow()) { // subtract off the style top borderpadding to get the // content height contentHeight -= aReflowState.mComputedBorderPadding.top; @@ -2435,7 +2435,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState, PRBool aTryPull) } if (!overflowLines) { aState.mNextInFlow = - NS_STATIC_CAST(nsBlockFrame*, nextInFlow->mNextInFlow); + NS_STATIC_CAST(nsBlockFrame*, nextInFlow->GetNextInFlow()); continue; } nifLine = overflowLines->begin(); @@ -2829,7 +2829,7 @@ nsBlockFrame::PullFrame(nsBlockReflowState& aState, break; } - nextInFlow = (nsBlockFrame*) nextInFlow->mNextInFlow; + nextInFlow = (nsBlockFrame*) nextInFlow->GetNextInFlow(); aState.mNextInFlow = nextInFlow; } @@ -4337,7 +4337,7 @@ nsBlockFrame::ShouldJustifyLine(nsBlockReflowState& aState, // XXX Not sure about this part // Try our next-in-flows lines to answer the question - nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow; + nsBlockFrame* nextInFlow = (nsBlockFrame*) GetNextInFlow(); while (nsnull != nextInFlow) { for (line_iterator line = nextInFlow->begin_lines(), line_end = nextInFlow->end_lines(); @@ -4347,7 +4347,7 @@ nsBlockFrame::ShouldJustifyLine(nsBlockReflowState& aState, if (0 != line->GetChildCount()) return !line->IsBlock(); } - nextInFlow = (nsBlockFrame*) nextInFlow->mNextInFlow; + nextInFlow = (nsBlockFrame*) nextInFlow->GetNextInFlow(); } // This is the last line - so don't allow justification @@ -4456,8 +4456,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, bidiUtils->ReorderFrames(aState.mPresContext, aState.mReflowState.rendContext, - aLine->mFirstChild, nextInFlow, - aLine->GetChildCount() ); + aLine->mFirstChild, nextInFlow); } // bidiUtils } // not visual mode } // bidi enabled @@ -4861,7 +4860,7 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState) nsLineList* ourOverflowLines = nsnull; // First grab the prev-in-flows overflow lines - nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow; + nsBlockFrame* prevBlock = (nsBlockFrame*) GetPrevInFlow(); if (prevBlock) { overflowLines = prevBlock->RemoveOverflowLines(); if (overflowLines) { @@ -5504,7 +5503,7 @@ nsBlockFrame::RemoveFrame(nsIAtom* aListName, if (nsnull == aListName) { PRBool hasFloats = BlockHasAnyFloats(aOldFrame); - rv = DoRemoveFrame(aOldFrame); + rv = DoRemoveFrame(aOldFrame, PR_TRUE, PR_FALSE); if (hasFloats) { MarkSameSpaceManagerLinesDirty(this); } @@ -5519,7 +5518,7 @@ nsBlockFrame::RemoveFrame(nsIAtom* aListName, #ifdef IBMBIDI else if (nsLayoutAtoms::nextBidi == aListName) { // Skip the call to |ReflowDirtyChild| below by returning now. - return DoRemoveFrame(aOldFrame); + return DoRemoveFrame(aOldFrame, PR_TRUE, PR_FALSE); } #endif // IBMBIDI else { @@ -5594,12 +5593,13 @@ static nsresult RemoveBlockChild(nsIFrame* aFrame, PRBool aDestroyFrames) // This function removes aDeletedFrame and all its continuations. It // is optimized for deleting a whole series of frames. The easy // implementation would invoke itself recursively on -// aDeletedFrame->GetNextInFlow, then locate the line containing +// aDeletedFrame->GetNextContinuation, then locate the line containing // aDeletedFrame and remove aDeletedFrame from that line. But here we // start by locating aDeletedFrame and then scanning from that point // on looking for continuations. nsresult -nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRBool aDestroyFrames) +nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRBool aDestroyFrames, + PRBool aRemoveOnlyFluidContinuations) { // Clear our line cursor, since our lines may change. ClearLineCursor(); @@ -5702,21 +5702,22 @@ found_frame:; lineChildCount--; line->SetChildCount(lineChildCount); - // Destroy frame; capture its next-in-flow first in case we need + // Destroy frame; capture its next continuation first in case we need // to destroy that too. - nsIFrame* deletedNextInFlow = aDeletedFrame->GetNextInFlow(); + nsIFrame* deletedNextContinuation = aRemoveOnlyFluidContinuations ? + aDeletedFrame->GetNextInFlow() : aDeletedFrame->GetNextContinuation(); #ifdef NOISY_REMOVE_FRAME printf("DoRemoveFrame: %s line=%p frame=", searchingOverflowList?"overflow":"normal", line.get()); nsFrame::ListTag(stdout, aDeletedFrame); - printf(" prevSibling=%p deletedNextInFlow=%p\n", prevSibling, deletedNextInFlow); + printf(" prevSibling=%p deletedNextContinuation=%p\n", prevSibling, deletedNextContinuation); #endif if (aDestroyFrames) { aDeletedFrame->Destroy(presContext); } else { aDeletedFrame->SetNextSibling(nsnull); } - aDeletedFrame = deletedNextInFlow; + aDeletedFrame = deletedNextContinuation; PRBool haveAdvancedToNextLine = PR_FALSE; // If line is empty, remove it now. @@ -5759,23 +5760,23 @@ found_frame:; } else { // Make the line that just lost a frame dirty, and advance to // the next line. - if (!deletedNextInFlow || isLastFrameOnLine || - !line->Contains(deletedNextInFlow)) { + if (!deletedNextContinuation || isLastFrameOnLine || + !line->Contains(deletedNextContinuation)) { line->MarkDirty(); ++line; haveAdvancedToNextLine = PR_TRUE; } } - if (deletedNextInFlow) { + if (deletedNextContinuation) { // Continuations for placeholder frames don't always appear in // consecutive lines. So for placeholders, just continue the slow easy way. if (isPlaceholder) { - return RemoveBlockChild(deletedNextInFlow, aDestroyFrames); + return RemoveBlockChild(deletedNextContinuation, aDestroyFrames); } // See if we should keep looking in the current flow's line list. - if (deletedNextInFlow->GetParent() != this) { + if (deletedNextContinuation->GetParent() != this) { // The deceased frames continuation is not a child of the // current block. So break out of the loop so that we advance // to the next parent. @@ -5786,7 +5787,7 @@ found_frame:; // overflow line list. if (haveAdvancedToNextLine) { if (line != line_end && !searchingOverflowList && - !line->Contains(deletedNextInFlow)) { + !line->Contains(deletedNextContinuation)) { // We have advanced to the next *normal* line but the next-in-flow // is not there - force a switch to the overflow line list. line = line_end; @@ -5818,13 +5819,7 @@ nsBlockFrame::DeleteNextInFlowChild(nsPresContext* aPresContext, NS_PRECONDITION(prevInFlow, "bad next-in-flow"); NS_PRECONDITION(IsChild(aNextInFlow), "bad geometric parent"); -#ifdef IBMBIDI - if (!(prevInFlow->GetStateBits() & NS_FRAME_IS_BIDI) || - (NS_STATIC_CAST(nsIFrame*, - aPresContext->PropertyTable()->GetProperty(prevInFlow, nsLayoutAtoms::nextBidi)) != - aNextInFlow)) -#endif // IBMBIDI - DoRemoveFrame(aNextInFlow); + DoRemoveFrame(aNextInFlow); } //////////////////////////////////////////////////////////////////////// @@ -6069,9 +6064,9 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState, } if (lastPlaceholder) { // get the containing block of prevPlaceholder which is our prev-in-flow - if (mPrevInFlow) { + if (GetPrevInFlow()) { // get the break type of the last line in mPrevInFlow - line_iterator endLine = --((nsBlockFrame*)mPrevInFlow)->end_lines(); + line_iterator endLine = --((nsBlockFrame*)GetPrevInFlow())->end_lines(); if (endLine->HasFloatBreakAfter()) { aState.mFloatBreakType = endLine->GetBreakTypeAfter(); } @@ -6089,10 +6084,10 @@ PRIntn nsBlockFrame::GetSkipSides() const { PRIntn skip = 0; - if (nsnull != mPrevInFlow) { + if (nsnull != GetPrevInFlow()) { skip |= 1 << NS_SIDE_TOP; } - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { skip |= 1 << NS_SIDE_BOTTOM; } return skip; @@ -6667,7 +6662,7 @@ nsBlockFrame::SetInitialChildList(nsPresContext* aPresContext, else { // Lookup up the two pseudo style contexts - if (nsnull == mPrevInFlow) { + if (nsnull == GetPrevInFlow()) { nsRefPtr firstLetterStyle = GetFirstLetterStyle(aPresContext); if (nsnull != firstLetterStyle) { mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE; @@ -6687,7 +6682,7 @@ nsBlockFrame::SetInitialChildList(nsPresContext* aPresContext, // here so that RenumberLists will work (it needs the bullets to // store the bullet numbers). const nsStyleDisplay* styleDisplay = GetStyleDisplay(); - if ((nsnull == mPrevInFlow) && + if ((nsnull == GetPrevInFlow()) && (NS_STYLE_DISPLAY_LIST_ITEM == styleDisplay->mDisplay) && (nsnull == mBullet)) { // Resolve style for the bullet frame @@ -7118,7 +7113,7 @@ nsBlockFrame::VerifyOverflowSituation() NS_ASSERTION(! overflowLines->empty(), "should not be empty if present"); NS_ASSERTION(overflowLines->front()->mFirstChild, "bad overflow list"); } - flow = (nsBlockFrame*) flow->mNextInFlow; + flow = (nsBlockFrame*) flow->GetNextInFlow(); } } diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h index 6963bda37ba..2b6390b75fe 100644 --- a/mozilla/layout/generic/nsBlockFrame.h +++ b/mozilla/layout/generic/nsBlockFrame.h @@ -324,8 +324,11 @@ public: * @param aDestroyFrames if false then we don't actually destroy the * frame or its next in flows, we just remove them. This does NOT work * on out of flow frames so always use PR_TRUE for out of flows. + * @param aRemoveOnlyFluidContinuations if true, only in-flows are removed; + * if false, all continuations are removed. */ - nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, PRBool aDestroyFrames = PR_TRUE); + nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, PRBool aDestroyFrames = PR_TRUE, + PRBool aRemoveOnlyFluidContinuations = PR_TRUE); protected: /** grab overflow lines from this block's prevInFlow, and make them diff --git a/mozilla/layout/generic/nsColumnSetFrame.cpp b/mozilla/layout/generic/nsColumnSetFrame.cpp index 7b75ebe1420..e4823bacc63 100644 --- a/mozilla/layout/generic/nsColumnSetFrame.cpp +++ b/mozilla/layout/generic/nsColumnSetFrame.cpp @@ -638,7 +638,7 @@ nsColumnSetFrame::DrainOverflowColumns() { // First grab the prev-in-flows overflows and reparent them to this // frame. - nsColumnSetFrame* prev = NS_STATIC_CAST(nsColumnSetFrame*, mPrevInFlow); + nsColumnSetFrame* prev = NS_STATIC_CAST(nsColumnSetFrame*, GetPrevInFlow()); if (prev) { nsIFrame* overflows = prev->GetOverflowFrames(GetPresContext(), PR_TRUE); if (overflows) { diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index 227c4fe8631..2487b71a698 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -890,15 +890,6 @@ nsContainerFrame::DeleteNextInFlowChild(nsPresContext* aPresContext, } } -#ifdef IBMBIDI - if ((prevInFlow->GetStateBits() & NS_FRAME_IS_BIDI) && - (NS_STATIC_CAST(nsIFrame*, - aPresContext->PropertyTable()->GetProperty(prevInFlow, nsLayoutAtoms::nextBidi)) == - aNextInFlow)) { - return; - } -#endif // IBMBIDI - // Disconnect the next-in-flow from the flow list nsSplittableFrame::BreakFromPrevFlow(aNextInFlow); @@ -996,17 +987,17 @@ nsContainerFrame::PushChildren(nsPresContext* aPresContext, // Disconnect aFromChild from its previous sibling aPrevSibling->SetNextSibling(nsnull); - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { // XXX This is not a very good thing to do. If it gets removed // then remove the copy of this routine that doesn't do this from // nsInlineFrame. - nsContainerFrame* nextInFlow = (nsContainerFrame*)mNextInFlow; + nsContainerFrame* nextInFlow = (nsContainerFrame*)GetNextInFlow(); // When pushing and pulling frames we need to check for whether any // views need to be reparented. for (nsIFrame* f = aFromChild; f; f = f->GetNextSibling()) { - nsHTMLContainerFrame::ReparentFrameView(aPresContext, f, this, mNextInFlow); + nsHTMLContainerFrame::ReparentFrameView(aPresContext, f, this, nextInFlow); } - nextInFlow->mFrames.InsertFrames(mNextInFlow, nsnull, aFromChild); + nextInFlow->mFrames.InsertFrames(nextInFlow, nsnull, aFromChild); } else { // Add the frames to our overflow list @@ -1028,7 +1019,7 @@ nsContainerFrame::MoveOverflowToChildList(nsPresContext* aPresContext) PRBool result = PR_FALSE; // Check for an overflow list with our prev-in-flow - nsContainerFrame* prevInFlow = (nsContainerFrame*)mPrevInFlow; + nsContainerFrame* prevInFlow = (nsContainerFrame*)GetPrevInFlow(); if (nsnull != prevInFlow) { nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); @@ -1072,11 +1063,11 @@ nsContainerFrame::List(FILE* out, PRInt32 aIndent) const if (nsnull != mNextSibling) { fprintf(out, " next=%p", NS_STATIC_CAST(void*, mNextSibling)); } - if (nsnull != mPrevInFlow) { - fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, mPrevInFlow)); + if (nsnull != GetPrevContinuation()) { + fprintf(out, " prev-continuation=%p", NS_STATIC_CAST(void*, GetPrevContinuation())); } - if (nsnull != mNextInFlow) { - fprintf(out, " next-in-flow=%p", NS_STATIC_CAST(void*, mNextInFlow)); + if (nsnull != GetNextContinuation()) { + fprintf(out, " next-continuation=%p", NS_STATIC_CAST(void*, GetNextContinuation())); } fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { diff --git a/mozilla/layout/generic/nsFirstLetterFrame.cpp b/mozilla/layout/generic/nsFirstLetterFrame.cpp index 74ed1ceb5ba..8be85b74697 100644 --- a/mozilla/layout/generic/nsFirstLetterFrame.cpp +++ b/mozilla/layout/generic/nsFirstLetterFrame.cpp @@ -304,7 +304,7 @@ nsFirstLetterFrame::DrainOverflowFrames(nsPresContext* aPresContext) nsIFrame* overflowFrames; // Check for an overflow list with our prev-in-flow - nsFirstLetterFrame* prevInFlow = (nsFirstLetterFrame*)mPrevInFlow; + nsFirstLetterFrame* prevInFlow = (nsFirstLetterFrame*)GetPrevInFlow(); if (nsnull != prevInFlow) { overflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); if (overflowFrames) { diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index dc4fc15a392..a43d6e48067 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -2829,7 +2829,34 @@ NS_IMETHODIMP nsFrame::IsSplittable(nsSplittableType& aIsSplittable) const return NS_OK; } -nsIFrame* nsFrame::GetPrevInFlow() const +nsIFrame* nsFrame::GetPrevContinuation() const +{ + return nsnull; +} + +NS_IMETHODIMP nsFrame::SetPrevContinuation(nsIFrame* aPrevContinuation) +{ + // Ignore harmless requests to set it to NULL + if (aPrevContinuation) { + NS_ERROR("not splittable"); + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} + +nsIFrame* nsFrame::GetNextContinuation() const +{ + return nsnull; +} + +NS_IMETHODIMP nsFrame::SetNextContinuation(nsIFrame*) +{ + NS_ERROR("not splittable"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +nsIFrame* nsFrame::GetPrevInFlowVirtual() const { return nsnull; } @@ -2845,7 +2872,7 @@ NS_IMETHODIMP nsFrame::SetPrevInFlow(nsIFrame* aPrevInFlow) return NS_OK; } -nsIFrame* nsFrame::GetNextInFlow() const +nsIFrame* nsFrame::GetNextInFlowVirtual() const { return nsnull; } diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h index 2f45bd01d5d..f9be229cafe 100644 --- a/mozilla/layout/generic/nsFrame.h +++ b/mozilla/layout/generic/nsFrame.h @@ -216,9 +216,13 @@ public: nsIAtom* aAttribute, PRInt32 aModType); NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const; - virtual nsIFrame* GetPrevInFlow() const; + virtual nsIFrame* GetPrevContinuation() const; + NS_IMETHOD SetPrevContinuation(nsIFrame*); + virtual nsIFrame* GetNextContinuation() const; + NS_IMETHOD SetNextContinuation(nsIFrame*); + virtual nsIFrame* GetPrevInFlowVirtual() const; NS_IMETHOD SetPrevInFlow(nsIFrame*); - virtual nsIFrame* GetNextInFlow() const; + virtual nsIFrame* GetNextInFlowVirtual() const; NS_IMETHOD SetNextInFlow(nsIFrame*); NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const; NS_IMETHOD GetOriginToViewOffset(nsPoint& aOffset, nsIView **aView) const; diff --git a/mozilla/layout/generic/nsHTMLCanvasFrame.cpp b/mozilla/layout/generic/nsHTMLCanvasFrame.cpp index f1ad856ce92..4e6c85bdcd3 100644 --- a/mozilla/layout/generic/nsHTMLCanvasFrame.cpp +++ b/mozilla/layout/generic/nsHTMLCanvasFrame.cpp @@ -121,7 +121,7 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext, aMetrics.width += mBorderPadding.left + mBorderPadding.right; aMetrics.height += mBorderPadding.top + mBorderPadding.bottom; - if (mPrevInFlow) { + if (GetPrevInFlow()) { nscoord y = GetContinuationOffset(&aMetrics.width); aMetrics.height -= y + mBorderPadding.top; aMetrics.height = PR_MAX(0, aMetrics.height); @@ -256,8 +256,8 @@ nsHTMLCanvasFrame::GetContinuationOffset(nscoord* aWidth) const *aWidth = 0; } - if (mPrevInFlow) { - for (nsIFrame* prevInFlow = mPrevInFlow ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) { + if (GetPrevInFlow()) { + for (nsIFrame* prevInFlow = GetPrevInFlow() ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) { nsRect rect = prevInFlow->GetRect(); if (aWidth) { *aWidth = rect.width; diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index 8ae81124c19..01dfa4a53eb 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -97,10 +97,10 @@ struct nsMargin; typedef class nsIFrame nsIBox; // IID for the nsIFrame interface -// 2fb5effc-5eeb-4ccb-b9fa-325f8642200f +// bdf02423-88d6-41ca-818a-54d7b51328c3 #define NS_IFRAME_IID \ -{ 0x2fb5effc, 0x5eeb, 0x4ccb, \ - { 0xb9, 0xfa, 0x32, 0x5f, 0x86, 0x42, 0x20, 0x0f } } +{ 0xbdf02423, 0x88d6, 0x41ca, \ + { 0x81, 0x8a, 0x54, 0xd7, 0xb5, 0x13, 0x28, 0xc3 } } /** * Indication of how the frame can be split. This is used when doing runaround @@ -144,6 +144,11 @@ typedef PRUint32 nsFrameState; // cleared. #define NS_FRAME_FIRST_REFLOW 0x00000002 +// For a continuation frame, if this bit is set, then this a "fluid" +// continuation, i.e., across a line boundary. Otherwise it's a "hard" +// continuation, e.g. a bidi continuation. +#define NS_FRAME_IS_FLUID_CONTINUATION 0x00000004 + // If this bit is set, then there is a child frame in the frame that // extends outside this frame's bounding box. The implication is that // the frame's rect does not completely cover its children and @@ -913,13 +918,30 @@ public: */ NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const = 0; + /** + * Continuation member functions + */ + virtual nsIFrame* GetPrevContinuation() const = 0; + NS_IMETHOD SetPrevContinuation(nsIFrame*) = 0; + virtual nsIFrame* GetNextContinuation() const = 0; + NS_IMETHOD SetNextContinuation(nsIFrame*) = 0; + virtual nsIFrame* GetFirstContinuation() const { + return NS_CONST_CAST(nsIFrame*, this); + } + virtual nsIFrame* GetLastContinuation() const { + return NS_CONST_CAST(nsIFrame*, this); + } + /** * Flow member functions */ - virtual nsIFrame* GetPrevInFlow() const = 0; - NS_IMETHOD SetPrevInFlow(nsIFrame*) = 0; - virtual nsIFrame* GetNextInFlow() const = 0; - NS_IMETHOD SetNextInFlow(nsIFrame*) = 0; + virtual nsIFrame* GetPrevInFlowVirtual() const = 0; + nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); } + NS_IMETHOD SetPrevInFlow(nsIFrame*) = 0; + + virtual nsIFrame* GetNextInFlowVirtual() const = 0; + nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); } + NS_IMETHOD SetNextInFlow(nsIFrame*) = 0; /** * Return the first frame in our current flow. diff --git a/mozilla/layout/generic/nsImageFrame.cpp b/mozilla/layout/generic/nsImageFrame.cpp index 8f5fa373b7a..0573d74a5c4 100644 --- a/mozilla/layout/generic/nsImageFrame.cpp +++ b/mozilla/layout/generic/nsImageFrame.cpp @@ -873,11 +873,11 @@ nsImageFrame::GetInnerArea() const { nsRect r; r.x = mBorderPadding.left; - r.y = mPrevInFlow ? 0 : mBorderPadding.top; + r.y = GetPrevInFlow() ? 0 : mBorderPadding.top; r.width = mRect.width - mBorderPadding.left - mBorderPadding.right; r.height = mRect.height - - (mPrevInFlow ? 0 : mBorderPadding.top) - - (mNextInFlow ? 0 : mBorderPadding.bottom); + (GetPrevInFlow() ? 0 : mBorderPadding.top) - + (GetNextInFlow() ? 0 : mBorderPadding.bottom); return r; } @@ -890,8 +890,8 @@ nsImageFrame::GetContinuationOffset(nscoord* aWidth) const *aWidth = 0; } - if (mPrevInFlow) { - for (nsIFrame* prevInFlow = mPrevInFlow ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) { + if (GetPrevInFlow()) { + for (nsIFrame* prevInFlow = GetPrevInFlow() ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) { nsRect rect = prevInFlow->GetRect(); if (aWidth) { *aWidth = rect.width; @@ -942,7 +942,7 @@ nsImageFrame::Reflow(nsPresContext* aPresContext, aMetrics.width += mBorderPadding.left + mBorderPadding.right; aMetrics.height += mBorderPadding.top + mBorderPadding.bottom; - if (mPrevInFlow) { + if (GetPrevInFlow()) { nscoord y = GetContinuationOffset(&aMetrics.width); aMetrics.height -= y + mBorderPadding.top; aMetrics.height = PR_MAX(0, aMetrics.height); @@ -1297,7 +1297,7 @@ nsImageFrame::PaintImage(nsIRenderingContext& aRenderingContext, nsPoint aPt, nscoord offsetY = 0; // if the image is split account for y-offset - if (mPrevInFlow) { + if (GetPrevInFlow()) { offsetY = GetContinuationOffset(); } diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index 6af5ee65e23..02f389b89be 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -174,13 +174,19 @@ nsInlineFrame::AppendFrames(nsIAtom* aListName, nsIFrame* aFrameList) { if (nsnull != aListName) { - return NS_ERROR_INVALID_ARG; +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif + return NS_ERROR_INVALID_ARG; } if (aFrameList) { mFrames.AppendFrames(this, aFrameList); // Ask the parent frame to reflow me. - ReflowDirtyChild(GetPresContext()->PresShell(), nsnull); +#ifdef IBMBIDI + if (nsnull == aListName) +#endif + ReflowDirtyChild(GetPresContext()->PresShell(), nsnull); } return NS_OK; } @@ -246,9 +252,9 @@ nsInlineFrame::RemoveFrame(nsIAtom* aListName, // When the parent is an inline frame we have a simple task - just // remove the frame from its parents list and generate a reflow // command. - nsIFrame* oldFrameNextInFlow = aOldFrame->GetNextInFlow(); + nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation(); parent->mFrames.DestroyFrame(GetPresContext(), aOldFrame); - aOldFrame = oldFrameNextInFlow; + aOldFrame = oldFrameNextContinuation; if (aOldFrame) { parent = NS_STATIC_CAST(nsInlineFrame*, aOldFrame->GetParent()); } @@ -299,7 +305,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext, PRBool lazilySetParentPointer = PR_FALSE; // Check for an overflow list with our prev-in-flow - nsInlineFrame* prevInFlow = (nsInlineFrame*)mPrevInFlow; + nsInlineFrame* prevInFlow = (nsInlineFrame*)GetPrevInFlow(); if (nsnull != prevInFlow) { nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); @@ -369,7 +375,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext, // aReflowState) InlineReflowState irs; irs.mPrevFrame = nsnull; - irs.mNextInFlow = (nsInlineFrame*) mNextInFlow; + irs.mNextInFlow = (nsInlineFrame*) GetNextInFlow(); irs.mSetParentPointer = lazilySetParentPointer; nsresult rv; @@ -433,7 +439,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, nsLineLayout* lineLayout = aReflowState.mLineLayout; nscoord leftEdge = 0; - if (nsnull == mPrevInFlow) { + if (nsnull == GetPrevContinuation()) { leftEdge = aReflowState.mComputedBorderPadding.left; } nscoord availableWidth = aReflowState.availableWidth; @@ -485,7 +491,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, } // Attempt to pull frames from our next-in-flow until we can't - if (!done && (nsnull != mNextInFlow)) { + if (!done && (nsnull != GetNextInFlow())) { while (!done) { PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK(); PRBool isComplete; @@ -531,7 +537,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, lineLayout->EndSpan(this, size, aMetrics.mComputeMEW ? &aMetrics.mMaxElementWidth : nsnull); if ((0 == size.height) && (0 == size.width) && - ((nsnull != mPrevInFlow) || (nsnull != mNextInFlow))) { + ((nsnull != GetPrevInFlow()) || (nsnull != GetNextInFlow()))) { // This is a continuation of a previous inline. Therefore make // sure we don't affect the line-height. aMetrics.width = 0; @@ -545,10 +551,10 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, else { // Compute final width aMetrics.width = size.width; - if (nsnull == mPrevInFlow) { + if (nsnull == GetPrevContinuation()) { aMetrics.width += aReflowState.mComputedBorderPadding.left; } - if (NS_FRAME_IS_COMPLETE(aStatus)) { + if (NS_FRAME_IS_COMPLETE(aStatus) && (!GetNextContinuation() || GetNextInFlow())) { aMetrics.width += aReflowState.mComputedBorderPadding.right; } @@ -687,16 +693,16 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext, aStatus |= NS_FRAME_NOT_COMPLETE; PushFrames(aPresContext, nextFrame, aFrame); } - else if (nsnull != mNextInFlow) { + else if (nsnull != GetNextInFlow()) { // We must return an incomplete status if there are more child // frames remaining in a next-in-flow that follows this frame. - nsInlineFrame* nextInFlow = (nsInlineFrame*) mNextInFlow; + nsInlineFrame* nextInFlow = (nsInlineFrame*) GetNextInFlow(); while (nsnull != nextInFlow) { if (nextInFlow->mFrames.NotEmpty()) { aStatus |= NS_FRAME_NOT_COMPLETE; break; } - nextInFlow = (nsInlineFrame*) nextInFlow->mNextInFlow; + nextInFlow = (nsInlineFrame*) nextInFlow->GetNextInFlow(); } } } @@ -741,7 +747,7 @@ nsInlineFrame::PullOneFrame(nsPresContext* aPresContext, nsHTMLContainerFrame::ReparentFrameView(aPresContext, frame, nextInFlow, this); break; } - nextInFlow = (nsInlineFrame*) nextInFlow->mNextInFlow; + nextInFlow = (nsInlineFrame*) nextInFlow->GetNextInFlow(); irs.mNextInFlow = nextInFlow; } @@ -777,27 +783,27 @@ PRIntn nsInlineFrame::GetSkipSides() const { PRIntn skip = 0; - if (nsnull != mPrevInFlow) { - nsInlineFrame* prev = (nsInlineFrame*) mPrevInFlow; + if (nsnull != GetPrevContinuation()) { + nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation(); if (prev->mRect.height || prev->mRect.width) { - // Prev-in-flow is not empty therefore we don't render our left + // Prev continuation is not empty therefore we don't render our left // border edge. skip |= 1 << NS_SIDE_LEFT; } else { - // If the prev-in-flow is empty, then go ahead and let our left + // If the prev continuation is empty, then go ahead and let our left // edge border render. } } - if (nsnull != mNextInFlow) { - nsInlineFrame* next = (nsInlineFrame*) mNextInFlow; + if (nsnull != GetNextContinuation()) { + nsInlineFrame* next = (nsInlineFrame*) GetNextContinuation(); if (next->mRect.height || next->mRect.width) { - // Next-in-flow is not empty therefore we don't render our right + // Next continuation is not empty therefore we don't render our right // border edge. skip |= 1 << NS_SIDE_RIGHT; } else { - // If the next-in-flow is empty, then go ahead and let our right + // If the next continuation is empty, then go ahead and let our right // edge border render. } } @@ -889,7 +895,7 @@ nsIFrame* nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowState& irs, PRBool* aIsComplete) { nsIFrame* frame = nsInlineFrame::PullOneFrame(aPresContext, irs, aIsComplete); - if (frame && !mPrevInFlow) { + if (frame && !GetPrevInFlow()) { // We are a first-line frame. Fixup the child frames // style-context that we just pulled. aPresContext->FrameManager()->ReParentStyleContext(frame, mStyleContext); @@ -908,7 +914,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, } // Check for an overflow list with our prev-in-flow - nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow; + nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)GetPrevInFlow(); if (nsnull != prevInFlow) { nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); if (prevOverflowFrames) { @@ -933,7 +939,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, // aReflowState) InlineReflowState irs; irs.mPrevFrame = nsnull; - irs.mNextInFlow = (nsInlineFrame*) mNextInFlow; + irs.mNextInFlow = (nsInlineFrame*) GetNextInFlow(); nsresult rv; PRBool wasEmpty = mFrames.IsEmpty(); @@ -944,7 +950,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, PullOneFrame(aPresContext, irs, &complete); } - if (nsnull == mPrevInFlow) { + if (nsnull == GetPrevInFlow()) { // XXX This is pretty sick, but what we do here is to pull-up, in // advance, all of the next-in-flows children. We re-resolve their // style while we are at at it so that when we reflow they have diff --git a/mozilla/layout/generic/nsLineLayout.cpp b/mozilla/layout/generic/nsLineLayout.cpp index 1f24a394710..8b52571a49f 100644 --- a/mozilla/layout/generic/nsLineLayout.cpp +++ b/mozilla/layout/generic/nsLineLayout.cpp @@ -1227,7 +1227,7 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd, PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection); // Only apply start-margin on the first-in flow for inline frames - if (HasPrevInFlow(pfd->mFrame)) { + if (pfd->mFrame->GetPrevContinuation()) { // Zero this out so that when we compute the max-element-width of // the frame we will properly avoid adding in the starting margin. if (ltr) @@ -1274,7 +1274,8 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, // XXXwaterson this is probably not exactly right; e.g., embeddings, etc. PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection); - if (NS_FRAME_IS_NOT_COMPLETE(aStatus) && !pfd->GetFlag(PFD_ISLETTERFRAME)) { + if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) || (pfd->mFrame->GetNextContinuation() && !pfd->mFrame->GetNextInFlow())) + && !pfd->GetFlag(PFD_ISLETTERFRAME)) { // Only apply end margin for the last-in-flow. Zero this out so // that when we compute the max-element-width of the frame we // will properly avoid adding in the end margin. diff --git a/mozilla/layout/generic/nsPageFrame.cpp b/mozilla/layout/generic/nsPageFrame.cpp index cf26cf16837..1168562e753 100644 --- a/mozilla/layout/generic/nsPageFrame.cpp +++ b/mozilla/layout/generic/nsPageFrame.cpp @@ -145,8 +145,8 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext, NS_ASSERTION(nsLayoutAtoms::pageContentFrame == firstFrame->GetType(), "This frame isn't a pageContentFrame"); - if (contentPage && mPrevInFlow) { - nsPageFrame* prevPage = NS_STATIC_CAST(nsPageFrame*, mPrevInFlow); + if (contentPage && GetPrevInFlow()) { + nsPageFrame* prevPage = NS_STATIC_CAST(nsPageFrame*, GetPrevInFlow()); nsPageContentFrame* prevContentPage = NS_STATIC_CAST(nsPageContentFrame*, prevPage->mFrames.FirstChild()); nsIFrame* prevLastChild = prevContentPage->mFrames.LastChild(); diff --git a/mozilla/layout/generic/nsSplittableFrame.cpp b/mozilla/layout/generic/nsSplittableFrame.cpp index c13d5fef751..34067ea2de9 100644 --- a/mozilla/layout/generic/nsSplittableFrame.cpp +++ b/mozilla/layout/generic/nsSplittableFrame.cpp @@ -52,7 +52,7 @@ nsSplittableFrame::Init(nsPresContext* aPresContext, if (aPrevInFlow) { // Hook the frame into the flow - mPrevInFlow = aPrevInFlow; + SetPrevInFlow(aPrevInFlow); aPrevInFlow->SetNextInFlow(this); } @@ -63,7 +63,7 @@ NS_IMETHODIMP nsSplittableFrame::Destroy(nsPresContext* aPresContext) { // Disconnect from the flow list - if (mPrevInFlow || mNextInFlow) { + if (mPrevContinuation || mNextContinuation) { RemoveFromFlow(this); } @@ -78,33 +78,112 @@ nsSplittableFrame::IsSplittable(nsSplittableType& aIsSplittable) const return NS_OK; } +nsIFrame* nsSplittableFrame::GetPrevContinuation() const +{ + return mPrevContinuation; +} + +NS_METHOD nsSplittableFrame::SetPrevContinuation(nsIFrame* aFrame) +{ + NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a prev continuation with incorrect type!"); + NS_ASSERTION (!IsInPrevContinuationChain(aFrame, this), "creating a loop in continuation chain!"); + mPrevContinuation = aFrame; + RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); + return NS_OK; +} + +nsIFrame* nsSplittableFrame::GetNextContinuation() const +{ + return mNextContinuation; +} + +NS_METHOD nsSplittableFrame::SetNextContinuation(nsIFrame* aFrame) +{ + NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a next continuation with incorrect type!"); + NS_ASSERTION (!IsInNextContinuationChain(aFrame, this), "creating a loop in continuation chain!"); + mNextContinuation = aFrame; + if (aFrame) + aFrame->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); + return NS_OK; +} + +nsIFrame* nsSplittableFrame::GetFirstContinuation() const +{ + nsSplittableFrame* firstContinuation = NS_CONST_CAST(nsSplittableFrame*, this); + while (firstContinuation->mPrevContinuation) { + firstContinuation = NS_STATIC_CAST(nsSplittableFrame*, firstContinuation->mPrevContinuation); + } + NS_POSTCONDITION(firstContinuation, "illegal state in continuation chain."); + return firstContinuation; +} + +nsIFrame* nsSplittableFrame::GetLastContinuation() const +{ + nsSplittableFrame* lastContinuation = NS_CONST_CAST(nsSplittableFrame*, this); + while (lastContinuation->mNextContinuation) { + lastContinuation = NS_STATIC_CAST(nsSplittableFrame*, lastContinuation->mNextContinuation); + } + NS_POSTCONDITION(lastContinuation, "illegal state in continuation chain."); + return lastContinuation; +} + +#ifdef DEBUG +PRBool nsSplittableFrame::IsInPrevContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2) +{ + while (aFrame1) { + if (aFrame1 == aFrame2) + return PR_TRUE; + aFrame1 = aFrame1->GetPrevContinuation(); + } + return PR_FALSE; +} + +PRBool nsSplittableFrame::IsInNextContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2) +{ + while (aFrame1) { + if (aFrame1 == aFrame2) + return PR_TRUE; + aFrame1 = aFrame1->GetNextContinuation(); + } + return PR_FALSE; +} +#endif + nsIFrame* nsSplittableFrame::GetPrevInFlow() const { - return mPrevInFlow; + return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nsnull; } NS_METHOD nsSplittableFrame::SetPrevInFlow(nsIFrame* aFrame) { - mPrevInFlow = aFrame; + NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a prev in flow with incorrect type!"); + NS_ASSERTION (!IsInPrevContinuationChain(aFrame, this), "creating a loop in continuation chain!"); + mPrevContinuation = aFrame; + AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); return NS_OK; } nsIFrame* nsSplittableFrame::GetNextInFlow() const { - return mNextInFlow; + return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? + mNextContinuation : nsnull; } NS_METHOD nsSplittableFrame::SetNextInFlow(nsIFrame* aFrame) { - mNextInFlow = aFrame; + NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a next in flow with incorrect type!"); + NS_ASSERTION (!IsInNextContinuationChain(aFrame, this), "creating a loop in continuation chain!"); + mNextContinuation = aFrame; + if (aFrame) + aFrame->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); return NS_OK; } nsIFrame* nsSplittableFrame::GetFirstInFlow() const { - nsSplittableFrame* firstInFlow = (nsSplittableFrame*)this; - while (firstInFlow->mPrevInFlow) { - firstInFlow = (nsSplittableFrame*)firstInFlow->mPrevInFlow; + nsSplittableFrame* firstInFlow = NS_CONST_CAST(nsSplittableFrame*, this); + while (nsIFrame *prev = firstInFlow->GetPrevInFlow()) { + firstInFlow = NS_STATIC_CAST(nsSplittableFrame*, prev); } NS_POSTCONDITION(firstInFlow, "illegal state in flow chain."); return firstInFlow; @@ -112,9 +191,9 @@ nsIFrame* nsSplittableFrame::GetFirstInFlow() const nsIFrame* nsSplittableFrame::GetLastInFlow() const { - nsSplittableFrame* lastInFlow = (nsSplittableFrame*)this; - while (lastInFlow->mNextInFlow) { - lastInFlow = (nsSplittableFrame*)lastInFlow->mNextInFlow; + nsSplittableFrame* lastInFlow = NS_CONST_CAST(nsSplittableFrame*, this); + while (nsIFrame* next = lastInFlow->GetNextInFlow()) { + lastInFlow = NS_STATIC_CAST(nsSplittableFrame*, next); } NS_POSTCONDITION(lastInFlow, "illegal state in flow chain."); return lastInFlow; @@ -124,15 +203,25 @@ nsIFrame* nsSplittableFrame::GetLastInFlow() const void nsSplittableFrame::RemoveFromFlow(nsIFrame* aFrame) { - nsIFrame* prevInFlow = aFrame->GetPrevInFlow(); - nsIFrame* nextInFlow = aFrame->GetNextInFlow(); + nsIFrame* prevContinuation = aFrame->GetPrevContinuation(); + nsIFrame* nextContinuation = aFrame->GetNextContinuation(); - if (prevInFlow) { - prevInFlow->SetNextInFlow(nextInFlow); - } - - if (nextInFlow) { - nextInFlow->SetPrevInFlow(prevInFlow); + // The new continuation is fluid only if the continuation on both sides + // of the removed frame was fluid + if (aFrame->GetPrevInFlow() && aFrame->GetNextInFlow()) { + if (prevContinuation) { + prevContinuation->SetNextInFlow(nextContinuation); + } + if (nextContinuation) { + nextContinuation->SetPrevInFlow(prevContinuation); + } + } else { + if (prevContinuation) { + prevContinuation->SetNextContinuation(nextContinuation); + } + if (nextContinuation) { + nextContinuation->SetPrevContinuation(prevContinuation); + } } aFrame->SetPrevInFlow(nsnull); @@ -144,8 +233,20 @@ void nsSplittableFrame::BreakFromPrevFlow(nsIFrame* aFrame) { nsIFrame* prevInFlow = aFrame->GetPrevInFlow(); + // If this frame has a non-fluid continuation, transfer it to its prevInFlow + nsIFrame* nextNonFluid = nsnull; + nsIFrame* nextContinuation = aFrame->GetNextContinuation(); + if (nextContinuation && !(nextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION)) { + nextNonFluid = nextContinuation; + aFrame->SetNextContinuation(nsnull); + } if (prevInFlow) { - prevInFlow->SetNextInFlow(nsnull); + if (nextNonFluid) { + prevInFlow->SetNextContinuation(nextNonFluid); + nextNonFluid->SetPrevContinuation(prevInFlow); + } else { + prevInFlow->SetNextInFlow(nsnull); + } aFrame->SetPrevInFlow(nsnull); } } @@ -155,13 +256,13 @@ void nsSplittableFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent, PRBool aIncludeStyleData) { nsFrame::DumpBaseRegressionData(aPresContext, out, aIndent, aIncludeStyleData); - if (nsnull != mNextInFlow) { + if (nsnull != mNextContinuation) { IndentBy(out, aIndent); - fprintf(out, "\n", PRUptrdiff(mNextInFlow)); + fprintf(out, "\n", PRUptrdiff(mNextContinuation)); } - if (nsnull != mPrevInFlow) { + if (nsnull != mPrevContinuation) { IndentBy(out, aIndent); - fprintf(out, "\n", PRUptrdiff(mPrevInFlow)); + fprintf(out, "\n", PRUptrdiff(mPrevContinuation)); } } diff --git a/mozilla/layout/generic/nsSplittableFrame.h b/mozilla/layout/generic/nsSplittableFrame.h index 769344d1887..1f91027a87c 100644 --- a/mozilla/layout/generic/nsSplittableFrame.h +++ b/mozilla/layout/generic/nsSplittableFrame.h @@ -53,20 +53,45 @@ public: NS_IMETHOD Destroy(nsPresContext* aPresContext); - // Flow member functions. - virtual nsIFrame* GetPrevInFlow() const; + /* + * Frame continuations can be either fluid or not: + * Fluid continuations ("in-flows") are the result of line breaking, + * column breaking, or page breaking. + * Other (non-fluid) continuations can be the result of BiDi frame splitting. + * A "flow" is a chain of fluid continuations. + */ + + // Get the previous/next continuation, regardless of its type (fluid or non-fluid). + virtual nsIFrame* GetPrevContinuation() const; + virtual nsIFrame* GetNextContinuation() const; + + // Set a previous/next non-fluid continuation. + NS_IMETHOD SetPrevContinuation(nsIFrame*); + NS_IMETHOD SetNextContinuation(nsIFrame*); + + // Get the first/last continuation for this frame. + virtual nsIFrame* GetFirstContinuation() const; + virtual nsIFrame* GetLastContinuation() const; + +#ifdef DEBUG + // Can aFrame2 be reached from aFrame1 by following prev/next continuations? + static PRBool IsInPrevContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2); + static PRBool IsInNextContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2); +#endif + + // Get the previous/next continuation, only if it is fluid (an "in-flow"). + nsIFrame* GetPrevInFlow() const; + nsIFrame* GetNextInFlow() const; + + virtual nsIFrame* GetPrevInFlowVirtual() const { return GetPrevInFlow(); } + virtual nsIFrame* GetNextInFlowVirtual() const { return GetNextInFlow(); } + + // Set a previous/next fluid continuation. NS_IMETHOD SetPrevInFlow(nsIFrame*); - virtual nsIFrame* GetNextInFlow() const; NS_IMETHOD SetNextInFlow(nsIFrame*); - /** - * Return the first frame in our current flow. - */ + // Get the first/last frame in the current flow. virtual nsIFrame* GetFirstInFlow() const; - - /** - * Return the last frame in our current flow. - */ virtual nsIFrame* GetLastInFlow() const; // Remove the frame from the flow. Connects the frame's prev-in-flow @@ -81,8 +106,8 @@ protected: virtual void DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent, PRBool aIncludeStyleData); #endif - nsIFrame* mPrevInFlow; - nsIFrame* mNextInFlow; + nsIFrame* mPrevContinuation; + nsIFrame* mNextContinuation; }; #endif /* nsSplittableFrame_h___ */ diff --git a/mozilla/layout/generic/nsTextFrame.cpp b/mozilla/layout/generic/nsTextFrame.cpp index 1ca2dd2ea8b..163583a3151 100644 --- a/mozilla/layout/generic/nsTextFrame.cpp +++ b/mozilla/layout/generic/nsTextFrame.cpp @@ -268,14 +268,36 @@ public: nsIContent* aChild, PRBool aAppend); - virtual nsIFrame* GetNextInFlow() const { - return mNextInFlow; + virtual nsIFrame* GetNextContinuation() const { + return mNextContinuation; + } + NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) { + NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(), + "setting a next continuation with incorrect type!"); + NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this), + "creating a loop in continuation chain!"); + mNextContinuation = aNextContinuation; + if (aNextContinuation) + aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); + return NS_OK; + } + virtual nsIFrame* GetNextInFlowVirtual() const { return GetNextInFlow(); } + nsIFrame* GetNextInFlow() const { + return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? + mNextContinuation : nsnull; } NS_IMETHOD SetNextInFlow(nsIFrame* aNextInFlow) { - mNextInFlow = aNextInFlow; + NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(), + "setting a next in flow with incorrect type!"); + NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this), + "creating a loop in continuation chain!"); + mNextContinuation = aNextInFlow; + if (aNextInFlow) + aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); return NS_OK; } virtual nsIFrame* GetLastInFlow() const; + virtual nsIFrame* GetLastContinuation() const; NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const { aIsSplittable = NS_FRAME_SPLITTABLE; @@ -551,7 +573,7 @@ public: protected: virtual ~nsTextFrame(); - nsIFrame* mNextInFlow; + nsIFrame* mNextContinuation; PRInt32 mContentOffset; PRInt32 mContentLength; PRInt32 mColumn; @@ -1367,8 +1389,8 @@ NS_IMETHODIMP nsTextFrame::GetAccessible(nsIAccessible** aAccessible) NS_IMETHODIMP nsTextFrame::Destroy(nsPresContext* aPresContext) { - if (mNextInFlow) { - mNextInFlow->SetPrevInFlow(nsnull); + if (mNextContinuation) { + mNextContinuation->SetPrevInFlow(nsnull); } // Let the base class destroy the frame return nsFrame::Destroy(aPresContext); @@ -1384,17 +1406,36 @@ public: NS_IMETHOD Destroy(nsPresContext* aPresContext); - virtual nsIFrame* GetPrevInFlow() const { - return mPrevInFlow; + virtual nsIFrame* GetPrevContinuation() const { + return mPrevContinuation; + } + NS_IMETHOD SetPrevContinuation(nsIFrame* aPrevContinuation) { + NS_ASSERTION (!aPrevContinuation || GetType() == aPrevContinuation->GetType(), + "setting a prev continuation with incorrect type!"); + NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevContinuation, this), + "creating a loop in continuation chain!"); + mPrevContinuation = aPrevContinuation; + RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); + return NS_OK; + } + virtual nsIFrame* GetPrevInFlowVirtual() const { return GetPrevInFlow(); } + nsIFrame* GetPrevInFlow() const { + return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nsnull; } NS_IMETHOD SetPrevInFlow(nsIFrame* aPrevInFlow) { - mPrevInFlow = aPrevInFlow; + NS_ASSERTION (!aPrevInFlow || GetType() == aPrevInFlow->GetType(), + "setting a prev in flow with incorrect type!"); + NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevInFlow, this), + "creating a loop in continuation chain!"); + mPrevContinuation = aPrevInFlow; + AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); return NS_OK; } virtual nsIFrame* GetFirstInFlow() const; + virtual nsIFrame* GetFirstContinuation() const; protected: - nsIFrame* mPrevInFlow; + nsIFrame* mPrevContinuation; }; NS_IMETHODIMP @@ -1409,8 +1450,9 @@ nsContinuingTextFrame::Init(nsPresContext* aPresContext, rv = nsTextFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); if (aPrevInFlow) { + nsIFrame* nextContinuation = aPrevInFlow->GetNextContinuation(); // Hook the frame into the flow - mPrevInFlow = aPrevInFlow; + SetPrevInFlow(aPrevInFlow); aPrevInFlow->SetNextInFlow(this); #ifdef IBMBIDI if (aPrevInFlow->GetStateBits() & NS_FRAME_IS_BIDI) { @@ -1427,17 +1469,12 @@ nsContinuingTextFrame::Init(nsPresContext* aPresContext, propTable->SetProperty(this, nsLayoutAtoms::charType, propTable->GetProperty(aPrevInFlow, nsLayoutAtoms::charType), nsnull, nsnull); - - void* value = propTable->GetProperty(aPrevInFlow, - nsLayoutAtoms::nextBidi); - if (value) { // nextBidi - // aPrevInFlow and this frame will point to the same next bidi frame. - propTable->SetProperty(this, nsLayoutAtoms::nextBidi, - value, nsnull, nsnull); - - ( (nsIFrame*) value)->GetOffsets(start, end); + if (nextContinuation) { + SetNextContinuation(nextContinuation); + nextContinuation->SetPrevContinuation(this); + nextContinuation->GetOffsets(start, end); mContentLength = PR_MAX(1, start - mContentOffset); - } // value + } mState |= NS_FRAME_IS_BIDI; } // prev frame is bidi #endif // IBMBIDI @@ -1449,7 +1486,7 @@ nsContinuingTextFrame::Init(nsPresContext* aPresContext, NS_IMETHODIMP nsContinuingTextFrame::Destroy(nsPresContext* aPresContext) { - if (mPrevInFlow || mNextInFlow) { + if (mPrevContinuation || mNextContinuation) { nsSplittableFrame::RemoveFromFlow(this); } // Let the base class destroy the frame @@ -1470,6 +1507,20 @@ nsContinuingTextFrame::GetFirstInFlow() const return firstInFlow; } +nsIFrame* +nsContinuingTextFrame::GetFirstContinuation() const +{ + // Can't cast to |nsContinuingTextFrame*| because the first one isn't. + nsIFrame *firstContinuation, + *previous = NS_CONST_CAST(nsIFrame*, + NS_STATIC_CAST(const nsIFrame*, mPrevContinuation)); + do { + firstContinuation = previous; + previous = firstContinuation->GetPrevContinuation(); + } while (previous); + return firstContinuation; +} + //DRAW SELECTION ITERATOR USED FOR TEXTFRAMES ONLY //helper class for drawing multiply selected text class DrawSelectionIterator @@ -1844,13 +1895,24 @@ nsTextFrame::GetCursor(const nsPoint& aPoint, nsIFrame* nsTextFrame::GetLastInFlow() const { - nsTextFrame* lastInFlow = (nsTextFrame*)this; - while (lastInFlow->mNextInFlow) { - lastInFlow = (nsTextFrame*)lastInFlow->mNextInFlow; + nsTextFrame* lastInFlow = NS_CONST_CAST(nsTextFrame*, this); + while (lastInFlow->GetNextInFlow()) { + lastInFlow = NS_STATIC_CAST(nsTextFrame*, lastInFlow->GetNextInFlow()); } NS_POSTCONDITION(lastInFlow, "illegal state in flow chain."); return lastInFlow; } +nsIFrame* +nsTextFrame::GetLastContinuation() const +{ + nsTextFrame* lastInFlow = NS_CONST_CAST(nsTextFrame*, this); + while (lastInFlow->mNextContinuation) { + lastInFlow = NS_STATIC_CAST(nsTextFrame*, lastInFlow->mNextContinuation); + } + NS_POSTCONDITION(lastInFlow, "illegal state in continuation chain."); + return lastInFlow; +} + NS_IMETHODIMP nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext, @@ -1862,7 +1924,7 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext, PRBool markAllDirty = PR_TRUE; if (aAppend) { markAllDirty = PR_FALSE; - nsTextFrame* frame = (nsTextFrame*)GetLastInFlow(); + nsTextFrame* frame = NS_STATIC_CAST(nsTextFrame*, GetLastInFlow()); frame->mState &= ~TEXT_WHITESPACE_FLAGS; frame->mState |= NS_FRAME_IS_DIRTY; targetTextFrame = frame; @@ -1875,14 +1937,7 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext, while (textFrame) { textFrame->mState &= ~TEXT_WHITESPACE_FLAGS; textFrame->mState |= NS_FRAME_IS_DIRTY; -#ifdef IBMBIDI - void* nextBidiFrame; - if ((textFrame->mState & NS_FRAME_IS_BIDI) && - (nextBidiFrame = propTable->GetProperty(textFrame, nsLayoutAtoms::nextBidi))) - textFrame = (nsTextFrame*)nextBidiFrame; - else -#endif - textFrame = (nsTextFrame*)textFrame->mNextInFlow; + textFrame = NS_STATIC_CAST(nsTextFrame*, textFrame->GetNextContinuation()); } } @@ -4232,23 +4287,16 @@ nsTextFrame::SetSelected(nsPresContext* aPresContext, } if (aSpread == eSpreadDown) { - nsIFrame* frame = GetPrevInFlow(); + nsIFrame* frame = GetPrevContinuation(); while(frame){ frame->SetSelected(aPresContext, aRange,aSelected,eSpreadNone); - frame = frame->GetPrevInFlow(); + frame = frame->GetPrevContinuation(); } - frame = GetNextInFlow(); + frame = GetNextContinuation(); while (frame){ frame->SetSelected(aPresContext, aRange,aSelected,eSpreadNone); - frame = frame->GetNextInFlow(); + frame = frame->GetNextContinuation(); } -#ifdef IBMBIDI - if ((mState & NS_FRAME_IS_BIDI) && - (frame = NS_STATIC_CAST(nsIFrame*, - aPresContext->PropertyTable()->GetProperty(this, nsLayoutAtoms::nextBidi)))) { - frame->SetSelected(aPresContext, aRange, aSelected, aSpread); - } -#endif // IBMBIDI } return NS_OK; } @@ -4395,33 +4443,14 @@ nsTextFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset, if ((contentOffset > mContentLength) || ((contentOffset == mContentLength) && inHint) ) { //this is not the frame we are looking for. - nsIFrame* nextInFlow = GetNextInFlow(); - if (nextInFlow) + nsIFrame* nextContinuation = GetNextContinuation(); + if (nextContinuation) { - return nextInFlow->GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame); + return nextContinuation->GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame); } else { -#ifdef IBMBIDI // Simon - // There is no nextInFlow - check if there is a bidi - // continuation frame - if (mState & NS_FRAME_IS_BIDI) - { - nsIFrame *nextBidi = GetNextSibling(); - if (nextBidi) - { - PRInt32 start, end; - if (NS_SUCCEEDED(nextBidi->GetOffsets(start, end)) && start > 0) - { - return nextBidi->GetChildFrameContainingOffset(inContentOffset, - inHint, outFrameContentOffset, outChildFrame); - } - } - } -#endif // IBMBIDI - { - if (contentOffset != mContentLength) //that condition was only for when there is a choice - return NS_ERROR_FAILURE; - } + if (contentOffset != mContentLength) //that condition was only for when there is a choice + return NS_ERROR_FAILURE; } } @@ -4534,18 +4563,9 @@ nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos) aPos->mStartOffset = mContentOffset; } if (aPos->mStartOffset > (mContentOffset + mContentLength)){ - nsIFrame *nextInFlow; -#ifdef IBMBIDI - if (isOddLevel) { - nextInFlow = NS_STATIC_CAST(nsIFrame*, - aPresContext->PropertyTable()->GetProperty(this, - nsLayoutAtoms::nextBidi)); - } - else -#endif - nextInFlow = GetNextInFlow(); - if (!nextInFlow){ - NS_ASSERTION(PR_FALSE,"nsTextFrame::PeekOffset no more flow \n"); + nsIFrame *nextContinuation = GetNextContinuation(); + if (!nextContinuation){ + NS_ASSERTION(PR_FALSE,"nsTextFrame::PeekOffset no more continuation\n"); return NS_ERROR_INVALID_ARG; } // undoing the RTL flipping of mPreferLeft for the delegation @@ -4553,7 +4573,7 @@ nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos) if ((eSelectCharacter == aPos->mAmount) || (eSelectWord == aPos->mAmount)) aPos->mPreferLeft ^= isOddLevel; - return nextInFlow->PeekOffset(aPresContext, aPos); + return nextContinuation->PeekOffset(aPresContext, aPos); } // XXX TODO: explain the following: @@ -5226,10 +5246,7 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext, PRInt32 start = -1, end; if (mState & NS_FRAME_IS_BIDI) { - nextBidi = NS_STATIC_CAST(nsTextFrame*, - aPresContext->PropertyTable()->GetProperty(this, - nsLayoutAtoms::nextBidi)); - + nextBidi = NS_STATIC_CAST(nsTextFrame*, GetLastInFlow()->GetNextContinuation()); if (nextBidi) { if (mContentLength < 1) { mContentLength = 1; @@ -5867,7 +5884,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, PRInt32 startingOffset = 0; nsIFrame* prevInFlow = GetPrevInFlow(); if (nsnull != prevInFlow) { - nsTextFrame* prev = (nsTextFrame*)prevInFlow; + nsTextFrame* prev = NS_STATIC_CAST(nsTextFrame*, prevInFlow); startingOffset = prev->mContentOffset + prev->mContentLength; // If our starting offset doesn't agree with mContentOffset, then our @@ -5949,7 +5966,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, // Set inWord to true if we are part of a previous piece of text's word. This // is only valid for one pass through the measuring loop. - PRBool inWord = lineLayout.InWord() || ((nsnull != prevInFlow) && (((nsTextFrame*)prevInFlow)->mState & TEXT_FIRST_LETTER)); + PRBool inWord = lineLayout.InWord() || ((nsnull != prevInFlow) && (NS_STATIC_CAST(nsTextFrame*, prevInFlow)->mState & TEXT_FIRST_LETTER)); if (inWord) { mState |= TEXT_IN_WORD; } @@ -5982,7 +5999,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, // NOTE: Trailing whitespace includes word and letter spacing! realWidth += ts.mSpaceWidth + ts.mWordSpacing + ts.mLetterSpacing; } - if (!mNextInFlow && + if (!GetNextInFlow() && (mState & TEXT_OPTIMIZE_RESIZE) && !aMetrics.mComputeMEW && (lastTimeWeSkippedLeadingWS == skipWhitespace) && @@ -6597,12 +6614,12 @@ nsTextFrame::List(FILE* out, PRInt32 aIndent) const if (nsnull != mNextSibling) { fprintf(out, " next=%p", NS_STATIC_CAST(void*, mNextSibling)); } - nsIFrame* prevInFlow = GetPrevInFlow(); - if (nsnull != prevInFlow) { - fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, prevInFlow)); + nsIFrame* prevContinuation = GetPrevContinuation(); + if (nsnull != prevContinuation) { + fprintf(out, " prev-continuation=%p", NS_STATIC_CAST(void*, prevContinuation)); } - if (nsnull != mNextInFlow) { - fprintf(out, " next-in-flow=%p", NS_STATIC_CAST(void*, mNextInFlow)); + if (nsnull != mNextContinuation) { + fprintf(out, " next-continuation=%p", NS_STATIC_CAST(void*, mNextContinuation)); } // Output the rect and state diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index f700eb2fe12..e01f2beb267 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -194,7 +194,7 @@ nsTableCellFrame::GetRowIndex(PRInt32 &aRowIndex) const nsresult nsTableCellFrame::GetColIndex(PRInt32 &aColIndex) const { - if (mPrevInFlow) { + if (GetPrevInFlow()) { return ((nsTableCellFrame*)GetFirstInFlow())->GetColIndex(aColIndex); } else { @@ -527,10 +527,10 @@ PRIntn nsTableCellFrame::GetSkipSides() const { PRIntn skip = 0; - if (nsnull != mPrevInFlow) { + if (nsnull != GetPrevInFlow()) { skip |= 1 << NS_SIDE_TOP; } - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { skip |= 1 << NS_SIDE_BOTTOM; } return skip; diff --git a/mozilla/layout/tables/nsTableColGroupFrame.cpp b/mozilla/layout/tables/nsTableColGroupFrame.cpp index 34d24cf9200..c4081044f5f 100644 --- a/mozilla/layout/tables/nsTableColGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableColGroupFrame.cpp @@ -326,10 +326,10 @@ PRIntn nsTableColGroupFrame::GetSkipSides() const { PRIntn skip = 0; - if (nsnull != mPrevInFlow) { + if (nsnull != GetPrevInFlow()) { skip |= 1 << NS_SIDE_TOP; } - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { skip |= 1 << NS_SIDE_BOTTOM; } return skip; diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index 8057ec82156..b8906e0e00d 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -438,7 +438,7 @@ nsTableFrame::SetInitialChildList(nsPresContext* aPresContext, // If we have a prev-in-flow, then we're a table that has been split and // so don't treat this like an append - if (!mPrevInFlow) { + if (!GetPrevInFlow()) { // process col groups first so that real cols get constructed before // anonymous ones due to cells in rows. InsertColGroups(0, mColGroups.FirstChild()); @@ -542,7 +542,7 @@ PRInt32 nsTableFrame::GetIndexOfLastRealCol() nsTableColFrame* nsTableFrame::GetColFrame(PRInt32 aColIndex) const { - NS_ASSERTION(!mPrevInFlow, "GetColFrame called on next in flow"); + NS_ASSERTION(!GetPrevInFlow(), "GetColFrame called on next in flow"); PRInt32 numCols = mColFrames.Count(); if ((aColIndex >= 0) && (aColIndex < numCols)) { return (nsTableColFrame *)mColFrames.ElementAt(aColIndex); @@ -1526,10 +1526,10 @@ nsTableFrame::GetSkipSides() const PRIntn skip = 0; // frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto // account for pagination - if (nsnull != mPrevInFlow) { + if (nsnull != GetPrevInFlow()) { skip |= 1 << NS_SIDE_TOP; } - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { skip |= 1 << NS_SIDE_BOTTOM; } return skip; @@ -1896,7 +1896,7 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext, return NS_OK; aStatus = NS_FRAME_COMPLETE; - if (!mPrevInFlow && !mTableLayoutStrategy) { + if (!GetPrevInFlow() && !mTableLayoutStrategy) { NS_ASSERTION(PR_FALSE, "strategy should have been created in Init"); return NS_ERROR_NULL_POINTER; } @@ -1907,7 +1907,7 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext, nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState); // see if collapsing borders need to be calculated - if (!mPrevInFlow && IsBorderCollapse() && NeedToCalcBCBorders()) { + if (!GetPrevInFlow() && IsBorderCollapse() && NeedToCalcBCBorders()) { GET_TWIPS_TO_PIXELS(aPresContext, p2t); CalcBCBorders(); } @@ -1929,7 +1929,7 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext, NS_WARNING("table initial reflow called twice"); } else { - if (!mPrevInFlow) { // only do pass1 on a first in flow + if (!GetPrevInFlow()) { // only do pass1 on a first in flow if (IsAutoLayout()) { // only do pass1 reflow on an auto layout table nsTableReflowState reflowState(*aPresContext, aReflowState, *this, @@ -1947,7 +1947,7 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext, } } SetHadInitialReflow(PR_TRUE); - if (!mPrevInFlow) { + if (!GetPrevInFlow()) { SetNeedStrategyBalance(PR_TRUE); // force a balance and then a pass2 reflow if ((nextReason != eReflowReason_StyleChange) || IsAutoLayout()) nextReason = eReflowReason_Resize; @@ -1988,7 +1988,7 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext, // reflows with a constrained width. if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) { // see if an extra reflow will be necessary in pagination mode when there is a specified table height - if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) { + if (isPaginated && !GetPrevInFlow() && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) { nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); if ((tableSpecifiedHeight > 0) && (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) { @@ -2073,7 +2073,7 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext, // See if we need to calc max elem and/or preferred widths. This isn't done on // continuations or if we have balanced (since it was done then) if ((aDesiredSize.mComputeMEW || (aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH)) && - !mPrevInFlow && !balanced) { + !GetPrevInFlow() && !balanced) { // Since the calculation has some cost, avoid doing it for an unconstrained initial // reflow (it was done when the strategy was initialized in pass 1 above) and most // unconstrained resize reflows. XXX The latter optimization could be a problem if the @@ -2153,7 +2153,7 @@ nsTableFrame::ReflowTable(nsHTMLReflowMetrics& aDesiredSize, aLastChildReflowed = nsnull; PRBool haveReflowedColGroups = PR_TRUE; - if (!mPrevInFlow) { + if (!GetPrevInFlow()) { if (NeedStrategyInit()) { mTableLayoutStrategy->Initialize(aReflowState); BalanceColumnWidths(aReflowState); @@ -2244,8 +2244,8 @@ nsTableFrame::PushChildren(const nsAutoVoidArray& aFrames, } } - if (nsnull != mNextInFlow) { - nsTableFrame* nextInFlow = (nsTableFrame*)mNextInFlow; + if (nsnull != GetNextInFlow()) { + nsTableFrame* nextInFlow = (nsTableFrame*)GetNextInFlow(); // Insert the frames after any repeated header and footer frames nsIFrame* firstBodyFrame = nextInFlow->GetFirstBodyRowGroupFrame(); @@ -2258,7 +2258,7 @@ nsTableFrame::PushChildren(const nsAutoVoidArray& aFrames, for (nsIFrame* f = frames.FirstChild(); f; f = f->GetNextSibling()) { nsHTMLContainerFrame::ReparentFrameView(GetPresContext(), f, this, nextInFlow); } - nextInFlow->mFrames.InsertFrames(mNextInFlow, prevSibling, frames.FirstChild()); + nextInFlow->mFrames.InsertFrames(GetNextInFlow(), prevSibling, frames.FirstChild()); } else { // Add the frames to our overflow list @@ -2279,7 +2279,7 @@ nsTableFrame::MoveOverflowToChildList(nsPresContext* aPresContext) PRBool result = PR_FALSE; // Check for an overflow list with our prev-in-flow - nsTableFrame* prevInFlow = (nsTableFrame*)mPrevInFlow; + nsTableFrame* prevInFlow = (nsTableFrame*)GetPrevInFlow(); if (prevInFlow) { nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); if (prevOverflowFrames) { @@ -2686,7 +2686,7 @@ nsTableFrame::IncrementalReflow(const nsHTMLReflowState& aReflowState, // Constrain our reflow width to the computed table width. Note: this is // based on the width of the first-in-flow PRInt32 lastWidth = mRect.width; - if (mPrevInFlow) { + if (GetPrevInFlow()) { nsTableFrame* table = (nsTableFrame*)GetFirstInFlow(); lastWidth = table->mRect.width; } @@ -3356,7 +3356,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState, // set the repeatablility of headers and footers in the original table during its first reflow // the repeatability of header and footers on continued tables is handled when they are created - if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE == aReflowState.availSize.height)) { + if (isPaginated && !GetPrevInFlow() && (NS_UNCONSTRAINEDSIZE == aReflowState.availSize.height)) { nsRect actualRect; nsRect adjRect; presContext->GetPageDim(&actualRect, &adjRect); @@ -3384,7 +3384,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState, // use the cell map to determine which cell is in which column. void nsTableFrame::BalanceColumnWidths(const nsHTMLReflowState& aReflowState) { - NS_ASSERTION(!mPrevInFlow, "never ever call me on a continuing frame!"); + NS_ASSERTION(!GetPrevInFlow(), "never ever call me on a continuing frame!"); // fixed-layout tables need to reinitialize the layout strategy. When there are scroll bars // reflow gets called twice and the 2nd time has the correct space available. @@ -3414,7 +3414,7 @@ void nsTableFrame::BalanceColumnWidths(const nsHTMLReflowState& aReflowState) nscoord nsTableFrame::CalcDesiredWidth(const nsHTMLReflowState& aReflowState) { - NS_ASSERTION(!mPrevInFlow, "never ever call me on a continuing frame!"); + NS_ASSERTION(!GetPrevInFlow(), "never ever call me on a continuing frame!"); nsTableCellMap* cellMap = GetCellMap(); if (!cellMap) { NS_ASSERTION(PR_FALSE, "never ever call me until the cell map is built!"); @@ -3493,7 +3493,7 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLRef } // see if a specified table height requires dividing additional space to rows - if (!mPrevInFlow) { + if (!GetPrevInFlow()) { nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); if ((tableSpecifiedHeight > 0) && (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) && @@ -6872,7 +6872,7 @@ nsTableFrame::PaintBCBorders(nsIRenderingContext& aRenderingContext, nsTableFrame* firstInFlow = (nsTableFrame*)GetFirstInFlow(); if (!firstInFlow) ABORT0(); GET_PIXELS_TO_TWIPS(GetPresContext(), p2t); - PRInt32 startRowY = (mPrevInFlow) ? 0 : childAreaOffset.top; // y position of first row in damage area + PRInt32 startRowY = (GetPrevInFlow()) ? 0 : childAreaOffset.top; // y position of first row in damage area const nsStyleBackground* bgColor = nsCSSRendering::FindNonTransparentBackground(mStyleContext); // determine the damage area in terms of rows and columns and finalize startColX and startRowY @@ -6894,8 +6894,8 @@ nsTableFrame::PaintBCBorders(nsIRenderingContext& aRenderingContext, nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame); if (!rgFrame) ABORT0(); for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) { // conservatively estimate the half border widths outside the row - nscoord topBorderHalf = (mPrevInFlow) ? 0 : rowFrame->GetTopBCBorderWidth(&p2t) + onePixel; - nscoord bottomBorderHalf = (mNextInFlow) ? 0 : rowFrame->GetBottomBCBorderWidth(&p2t) + onePixel; + nscoord topBorderHalf = (GetPrevInFlow()) ? 0 : rowFrame->GetTopBCBorderWidth(&p2t) + onePixel; + nscoord bottomBorderHalf = (GetNextInFlow()) ? 0 : rowFrame->GetBottomBCBorderWidth(&p2t) + onePixel; // get the row rect relative to the table rather than the row group nsSize rowSize = rowFrame->GetSize(); if (haveIntersect) { diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index fe284b6b915..644d5faf1b6 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -538,7 +538,7 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState) if (IS_TABLE_CELL(kidFrame->GetType())) { nscoord availWidth = ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth(); nsSize desSize = ((nsTableCellFrame *)kidFrame)->GetDesiredSize(); - if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !mPrevInFlow) { + if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !GetPrevInFlow()) { CalculateCellActualSize(kidFrame, desSize.width, desSize.height, availWidth); } // height may have changed, adjust descent to absorb any excess difference @@ -629,10 +629,10 @@ PRIntn nsTableRowFrame::GetSkipSides() const { PRIntn skip = 0; - if (nsnull != mPrevInFlow) { + if (nsnull != GetPrevInFlow()) { skip |= 1 << NS_SIDE_TOP; } - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { skip |= 1 << NS_SIDE_BOTTOM; } return skip; @@ -1016,7 +1016,7 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext, } if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) { - if (!mPrevInFlow) { + if (!GetPrevInFlow()) { // Calculate the cell's actual size given its pass2 size. This function // takes into account the specified height (in the style), and any special // logic needed for backwards compatibility @@ -1076,7 +1076,7 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext, } else if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) { aDesiredSize.height = CalcHeight(aReflowState); - if (mPrevInFlow) { + if (GetPrevInFlow()) { nscoord height = CalcHeightFromUnpaginatedHeight(aPresContext, *this); aDesiredSize.height = PR_MAX(aDesiredSize.height, height); } @@ -1366,7 +1366,7 @@ nsTableRowFrame::IR_TargetIsChild(nsPresContext* aPresContext, // frames. If any of them has a continuing frame, then we're not complete. We // can't just return the status of the cell frame we just reflowed... aStatus = NS_FRAME_COMPLETE; - if (mNextInFlow) { + if (GetNextInFlow()) { for (nsIFrame* cell = mFrames.FirstChild(); cell; cell = cell->GetNextSibling()) { nsIFrame* contFrame = cell->GetNextInFlow(); @@ -1552,7 +1552,7 @@ void nsTableRowFrame::SetUnpaginatedHeight(nsPresContext* aPresContext, nscoord aValue) { - NS_ASSERTION(!mPrevInFlow, "program error"); + NS_ASSERTION(!GetPrevInFlow(), "program error"); // Get the property nscoord* value = (nscoord*)nsTableFrame::GetProperty(this, nsLayoutAtoms::rowUnpaginatedHeightProperty, PR_TRUE); if (value) { diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp index 3be1d0d7821..f04d47b7769 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp @@ -228,10 +228,10 @@ PRIntn nsTableRowGroupFrame::GetSkipSides() const { PRIntn skip = 0; - if (nsnull != mPrevInFlow) { + if (nsnull != GetPrevInFlow()) { skip |= 1 << NS_SIDE_TOP; } - if (nsnull != mNextInFlow) { + if (nsnull != GetNextInFlow()) { skip |= 1 << NS_SIDE_BOTTOM; } return skip; @@ -601,7 +601,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsPresContext* aPresContext, // See if the row has an originating cell with rowspan > 1. We cannot determine this for a row in a // continued row group by calling RowHasSpanningCells, because the row's fif may not have any originating // cells yet the row may have a continued cell which originates in it. - if (mPrevInFlow || tableFrame->RowHasSpanningCells(startRowIndex + rowIndex, numEffCols)) { + if (GetPrevInFlow() || tableFrame->RowHasSpanningCells(startRowIndex + rowIndex, numEffCols)) { nsTableCellFrame* cellFrame = rowFrame->GetFirstCell(); // iteratate the row's cell frames while (cellFrame) { @@ -1464,7 +1464,7 @@ nsTableRowGroupFrame::IR_TargetIsMe(nsPresContext* aPresContext, } // XXX If we have a next-in-flow, then we're not complete - if (mNextInFlow) { + if (GetNextInFlow()) { aStatus = NS_FRAME_NOT_COMPLETE; } return rv; @@ -1700,7 +1700,7 @@ nsTableRowGroupFrame::IR_TargetIsChild(nsPresContext* aPresContext, // Return our desired width //aDesiredSize.width = aReflowState.reflowState.availableWidth; - if (mNextInFlow) { + if (GetNextInFlow()) { aStatus = NS_FRAME_NOT_COMPLETE; }