зеркало из https://github.com/mozilla/gecko-dev.git
Bug 263359 part 3: resolve paragraph on encountering <br> or embedded block elements
This commit is contained in:
Родитель
c29305f3ee
Коммит
ec7706761d
|
@ -317,6 +317,7 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
|||
mLogicalFrames.Clear();
|
||||
mContentToFrameIndex.Clear();
|
||||
mBuffer.SetLength(0);
|
||||
mEmbeddingStack.Clear();
|
||||
|
||||
nsPresContext *presContext = aBlockFrame->PresContext();
|
||||
|
||||
|
@ -361,7 +362,7 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
|||
mPrevFrame = nsnull;
|
||||
|
||||
// handle bidi-override being set on the block itself before calling
|
||||
// InitLogicalArray.
|
||||
// TraverseFrames.
|
||||
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset();
|
||||
PRUnichar ch = 0;
|
||||
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
|
||||
|
@ -374,22 +375,23 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
|||
if (ch != 0) {
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mBuffer.Append(ch);
|
||||
mEmbeddingStack.AppendElement(ch);
|
||||
}
|
||||
}
|
||||
mPrevContent = nsnull;
|
||||
for (nsBlockFrame* block = aBlockFrame; block;
|
||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
InitLogicalArray(block->GetFirstChild(nsnull));
|
||||
TraverseFrames(aBlockFrame, block->GetFirstChild(nsnull));
|
||||
}
|
||||
|
||||
if (ch != 0) {
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mBuffer.Append(kPDF);
|
||||
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
|
||||
}
|
||||
|
||||
// XXX: TODO: Handle preformatted text ('\n')
|
||||
mBuffer.ReplaceChar("\t\r\n", kSpace);
|
||||
// Resolve final paragraph
|
||||
ResolveParagraph(aBlockFrame);
|
||||
return mSuccess;
|
||||
}
|
||||
|
@ -404,6 +406,9 @@ nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame)
|
|||
mSuccess = NS_OK;
|
||||
return;
|
||||
}
|
||||
// XXX: TODO: Handle preformatted text ('\n')
|
||||
mBuffer.ReplaceChar("\t\r\n", kSpace);
|
||||
|
||||
PRInt32 runCount;
|
||||
PRUint8 embeddingLevel = mParaLevel;
|
||||
|
||||
|
@ -587,13 +592,13 @@ nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame)
|
|||
fragmentLength -= temp;
|
||||
|
||||
if (frame && fragmentLength <= 0) {
|
||||
// If the frame is at the end of a run, split all ancestor inlines that
|
||||
// need splitting.
|
||||
// If the frame is at the end of a run, and this is not the end of our
|
||||
// paragrah, split all ancestor inlines that need splitting.
|
||||
// To determine whether we're at the end of the run, we check that we've
|
||||
// finished processing the current run, and that the current frame
|
||||
// doesn't have a fluid continuation (it could have a fluid continuation
|
||||
// of zero length, so testing runLength alone is not sufficient).
|
||||
if (runLength <= 0 && !frame->GetNextInFlow()) {
|
||||
if (numRun + 1 < runCount && runLength <= 0 && !frame->GetNextInFlow()) {
|
||||
nsIFrame* child = frame;
|
||||
nsIFrame* parent = frame->GetParent();
|
||||
// As long as we're on the last sibling, the parent doesn't have to be split.
|
||||
|
@ -641,13 +646,24 @@ PRBool IsBidiLeaf(nsIFrame* aFrame) {
|
|||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
||||
nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
|
||||
nsIFrame* aCurrentFrame)
|
||||
{
|
||||
if (!aCurrentFrame)
|
||||
return;
|
||||
|
||||
for (nsIFrame* childFrame = aCurrentFrame; childFrame;
|
||||
childFrame = childFrame->GetNextSibling()) {
|
||||
nsIFrame* childFrame = aCurrentFrame;
|
||||
do {
|
||||
/*
|
||||
* It's important to get the next sibling and next continuation *before*
|
||||
* handling the frame: If we encounter a forced paragraph break and call
|
||||
* ResolveParagraph within this loop, doing GetNextSibling and
|
||||
* GetNextContinuation after that could return a bidi continuation that had
|
||||
* just been split from the original childFrame and we would process it
|
||||
* twice.
|
||||
*/
|
||||
nsIFrame* nextSibling = childFrame->GetNextSibling();
|
||||
PRBool isLastFrame = !childFrame->GetNextContinuation();
|
||||
|
||||
// If the real frame for a placeholder is a first letter frame, we need to
|
||||
// drill down into it and include its contents in Bidi resolution.
|
||||
|
@ -691,6 +707,7 @@ nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
|||
if (ch != 0 && !frame->GetPrevContinuation()) {
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mBuffer.Append(ch);
|
||||
mEmbeddingStack.AppendElement(ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -716,26 +733,66 @@ nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame)
|
|||
} else if (nsGkAtoms::brFrame == frameType) {
|
||||
// break frame -- append line separator
|
||||
mBuffer.Append(kLineSeparator);
|
||||
ResolveParagraphWithinBlock(aBlockFrame);
|
||||
} else {
|
||||
// other frame type -- see the Unicode Bidi Algorithm:
|
||||
// "...inline objects (such as graphics) are treated as if they are ...
|
||||
// U+FFFC"
|
||||
mBuffer.Append(kObjectSubstitute);
|
||||
if (!frame->GetStyleContext()->GetStyleDisplay()->IsInlineOutside()) {
|
||||
// if it is not inline, end the paragraph
|
||||
ResolveParagraphWithinBlock(aBlockFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For a non-leaf frame, recurse into TraverseFrames
|
||||
nsIFrame* kid = frame->GetFirstChild(nsnull);
|
||||
InitLogicalArray(kid);
|
||||
TraverseFrames(aBlockFrame, kid);
|
||||
}
|
||||
|
||||
// If the element is attributed by dir, indicate direction pop (add PDF frame)
|
||||
if (ch != 0 && !frame->GetNextContinuation()) {
|
||||
if (ch != 0 && isLastFrame) {
|
||||
// Add a dummy frame pointer representing a bidi control code after the
|
||||
// last frame of an element specifying embedding or override
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
mBuffer.Append(kPDF);
|
||||
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
|
||||
}
|
||||
} // for
|
||||
childFrame = nextSibling;
|
||||
} while (childFrame);
|
||||
}
|
||||
|
||||
void
|
||||
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame)
|
||||
{
|
||||
nsIPresShell* shell;
|
||||
nsStyleContext* styleContext;
|
||||
|
||||
if (mEmbeddingStack.Length() > 0) {
|
||||
shell = aBlockFrame->PresContext()->PresShell();
|
||||
styleContext = aBlockFrame->GetStyleContext();
|
||||
|
||||
// pop all embeddings and overrides
|
||||
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
|
||||
mBuffer.Append(kPDF);
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveParagraph(aBlockFrame);
|
||||
|
||||
// Clear the frame array and paragraph buffer, and restore the stored
|
||||
// embeddings and overrides
|
||||
mLogicalFrames.Clear();
|
||||
mContentToFrameIndex.Clear();
|
||||
mBuffer.SetLength(0);
|
||||
if (mEmbeddingStack.Length() > 0) {
|
||||
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
|
||||
mBuffer.Append(mEmbeddingStack[i]);
|
||||
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -176,6 +176,7 @@ public:
|
|||
*/
|
||||
nsresult Resolve(nsBlockFrame* aBlockFrame);
|
||||
void ResolveParagraph(nsBlockFrame* aBlockFrame);
|
||||
void ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame);
|
||||
|
||||
/**
|
||||
* Reorder this line using Bidi engine.
|
||||
|
@ -363,11 +364,14 @@ private:
|
|||
nscoord* aWidth /* may be null */);
|
||||
|
||||
/**
|
||||
* Set up an array of the frames after splitting frames so that each frame has
|
||||
* consistent directionality. At this point the frames are still in logical
|
||||
* order
|
||||
* Traverse the child frames of the block element and:
|
||||
* Set up an array of the frames in logical order
|
||||
* Create a string containing the text content of all the frames
|
||||
* If we encounter content that requires us to split the element into more
|
||||
* than one paragraph for bidi resolution, resolve the paragraph up to that
|
||||
* point.
|
||||
*/
|
||||
void InitLogicalArray(nsIFrame* aCurrentFrame);
|
||||
void TraverseFrames(nsBlockFrame* aBlockFrame, nsIFrame* aCurrentFrame);
|
||||
|
||||
/**
|
||||
* Initialize the logically-ordered array of frames
|
||||
|
@ -507,7 +511,8 @@ private:
|
|||
PRUint32 aSrcLength,
|
||||
PRUnichar* aDest);
|
||||
|
||||
nsAutoString mBuffer;
|
||||
nsString mBuffer;
|
||||
nsTArray<PRUnichar> mEmbeddingStack;
|
||||
nsTArray<nsIFrame*> mLogicalFrames;
|
||||
nsTArray<nsIFrame*> mVisualFrames;
|
||||
nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
|
||||
|
|
Загрузка…
Ссылка в новой задаче