From 2147de52fcc2a9d0f2b7a880fb53ca4e01ac1778 Mon Sep 17 00:00:00 2001 From: "uriber%gmail.com" Date: Sat, 13 Jan 2007 18:20:28 +0000 Subject: [PATCH] Don't bidi-split line frames. bug=364839, r+sr=bzbarsky. git-svn-id: svn://10.0.0.236/trunk@218277 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsBidiPresUtils.cpp | 24 +++++++-- mozilla/layout/generic/nsFrameList.cpp | 68 ++++++++++++++++--------- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/mozilla/layout/base/nsBidiPresUtils.cpp b/mozilla/layout/base/nsBidiPresUtils.cpp index e29e648a60d..3c0cd05345f 100644 --- a/mozilla/layout/base/nsBidiPresUtils.cpp +++ b/mozilla/layout/base/nsBidiPresUtils.cpp @@ -101,6 +101,15 @@ nsBidiPresUtils::IsSuccessful() const /* Some helper methods for Resolve() */ +// Should this frame be split between text runs? +PRBool +IsBidiSplittable(nsIFrame* aFrame) { + nsIAtom* frameType = aFrame->GetType(); + // Bidi inline containers should be split, unless they're line frames. + return aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer) + && frameType != nsGkAtoms::lineFrame; +} + static nsresult SplitInlineAncestors(nsPresContext* aPresContext, nsIFrame* aFrame) @@ -111,7 +120,7 @@ SplitInlineAncestors(nsPresContext* aPresContext, nsIFrame* newFrame = aFrame->GetNextSibling(); nsIFrame* newParent; - while (parent->IsFrameOfType(nsIFrame::eBidiInlineContainer)) { + while (IsBidiSplittable(parent)) { nsIFrame* grandparent = parent->GetParent(); NS_ASSERTION(grandparent, "Couldn't get parent's parent in nsBidiPresUtils::SplitInlineAncestors"); @@ -447,12 +456,12 @@ nsBidiPresUtils::Resolve(nsPresContext* aPresContext, nsIFrame* child = frame; nsIFrame* parent = frame->GetParent(); while (parent && - parent->IsFrameOfType(nsIFrame::eBidiInlineContainer) && + IsBidiSplittable(parent) && !child->GetNextSibling()) { child = parent; parent = child->GetParent(); } - if (parent && parent->IsFrameOfType(nsIFrame::eBidiInlineContainer)) + if (parent && IsBidiSplittable(parent)) SplitInlineAncestors(aPresContext, child); } } // for @@ -461,7 +470,6 @@ nsBidiPresUtils::Resolve(nsPresContext* aPresContext, // 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); // Need the IsBlockLevel() check because nsFirstLetterFrame is // always of type eBidiInlineContainer, even if it's floating. @@ -608,6 +616,14 @@ nsBidiPresUtils::ReorderFrames(nsPresContext* aPresContext, nsIFrame* aFirstFrameOnLine, PRInt32 aNumFramesOnLine) { + // If this line consists of a line frame, reorder the line frame's children. + if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) { + aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull); + // All children of the line frame are on the first line. Setting aNumFramesOnLine + // to -1 makes InitLogicalArrayFromLine look at all of them. + aNumFramesOnLine = -1; + } + InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine); PRBool isReordered; diff --git a/mozilla/layout/generic/nsFrameList.cpp b/mozilla/layout/generic/nsFrameList.cpp index 176a83a7407..5eab70e3257 100644 --- a/mozilla/layout/generic/nsFrameList.cpp +++ b/mozilla/layout/generic/nsFrameList.cpp @@ -442,21 +442,32 @@ nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const if (!parent) return aFrame ? GetPrevSiblingFor(aFrame) : LastChild(); - nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild); - + nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild); + nsBidiPresUtils* bidiUtils = mFirstChild->GetPresContext()->GetBidiUtils(); + nsresult result = parent->QueryInterface(NS_GET_IID(nsILineIterator), (void**)&iter); if (NS_FAILED(result) || !iter) { - // If the parent is not a block frame, just get the next or prev sibling, depending on block and frame direction. - nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); - if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { - return aFrame ? GetPrevSiblingFor(aFrame) : LastChild(); + // Parent is not a block Frame + if (parent->GetType() == nsGkAtoms::lineFrame) { + // Line frames are not bidi-splittable, so need to consider bidi reordering + if (baseLevel == NSBIDI_LTR) { + return bidiUtils->GetFrameToLeftOf(aFrame, mFirstChild, -1); + } else { // RTL + return bidiUtils->GetFrameToRightOf(aFrame, mFirstChild, -1); + } } else { - return aFrame ? aFrame->GetNextSibling() : mFirstChild; - } + // Just get the next or prev sibling, depending on block and frame direction. + nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); + if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { + return aFrame ? GetPrevSiblingFor(aFrame) : LastChild(); + } else { + return aFrame ? aFrame->GetNextSibling() : mFirstChild; + } + } } - // Otherwise use the LineIterator to find the previous visual sibling on this line, - // or the last one on the previous line. + // Parent is a block frame, so use the LineIterator to find the previous visual + // sibling on this line, or the last one on the previous line. PRInt32 thisLine; if (aFrame) { @@ -466,9 +477,7 @@ nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const } else { iter->GetNumLines(&thisLine); } - - nsBidiPresUtils* bidiUtils = mFirstChild->GetPresContext()->GetBidiUtils(); - + nsIFrame* frame = nsnull; nsIFrame* firstFrameOnLine; PRInt32 numFramesOnLine; @@ -511,20 +520,31 @@ nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const return aFrame ? GetPrevSiblingFor(aFrame) : mFirstChild; nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild); + nsBidiPresUtils* bidiUtils = mFirstChild->GetPresContext()->GetBidiUtils(); nsresult result = parent->QueryInterface(NS_GET_IID(nsILineIterator), (void**)&iter); - if (NS_FAILED(result) || !iter) { - // If the parent is not a block frame, just get the next or prev sibling, depending on block and frame direction. - nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); - if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { - return aFrame ? aFrame->GetNextSibling() : mFirstChild; + if (NS_FAILED(result) || !iter) { + // Parent is not a block Frame + if (parent->GetType() == nsGkAtoms::lineFrame) { + // Line frames are not bidi-splittable, so need to consider bidi reordering + if (baseLevel == NSBIDI_LTR) { + return bidiUtils->GetFrameToRightOf(aFrame, mFirstChild, -1); + } else { // RTL + return bidiUtils->GetFrameToLeftOf(aFrame, mFirstChild, -1); + } } else { - return aFrame ? GetPrevSiblingFor(aFrame) : LastChild(); - } + // Just get the next or prev sibling, depending on block and frame direction. + nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild); + if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) { + return aFrame ? aFrame->GetNextSibling() : mFirstChild; + } else { + return aFrame ? GetPrevSiblingFor(aFrame) : LastChild(); + } + } } - // Otherwise use the LineIterator to find the next visual sibling on this line, - // or the first one on the next line. + // Parent is a block frame, so use the LineIterator to find the next visual + // sibling on this line, or the first one on the next line. PRInt32 thisLine; if (aFrame) { @@ -534,9 +554,7 @@ nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const } else { thisLine = -1; } - - nsBidiPresUtils* bidiUtils = mFirstChild->GetPresContext()->GetBidiUtils(); - + nsIFrame* frame = nsnull; nsIFrame* firstFrameOnLine; PRInt32 numFramesOnLine;