mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Backing out
This commit is contained in:
parent
7c626fa17b
commit
28f1f19b47
@ -883,6 +883,16 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
|
||||
mSpaceManager->Translate(tx, ty);
|
||||
|
||||
#ifdef IBMBIDI
|
||||
PRInt32 start, end;
|
||||
|
||||
if (mPresContext->BidiEnabled()) {
|
||||
if (aFrame->GetStateBits() & NS_FRAME_IS_BIDI) {
|
||||
aFrame->GetOffsets(start, end);
|
||||
}
|
||||
}
|
||||
#endif // IBMBIDI
|
||||
|
||||
nsIAtom* frameType = aFrame->GetType();
|
||||
PRInt32 savedOptionalBreakOffset;
|
||||
nsIContent* savedOptionalBreakContent =
|
||||
@ -1076,6 +1086,24 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
printf(" status=%x\n", aReflowStatus);
|
||||
#endif
|
||||
|
||||
if (aFrame->GetStateBits() & NS_FRAME_IS_BIDI) {
|
||||
// Since aReflowStatus may change, check it at the end
|
||||
if (NS_INLINE_IS_BREAK_BEFORE(aReflowStatus) ) {
|
||||
aFrame->AdjustOffsetsForBidi(start, end);
|
||||
}
|
||||
else if (!NS_FRAME_IS_COMPLETE(aReflowStatus) ) {
|
||||
PRInt32 newEnd;
|
||||
aFrame->GetOffsets(start, newEnd);
|
||||
if (newEnd != end) {
|
||||
nsIFrame* nextInFlow = aFrame->GetNextInFlow();
|
||||
if (nextInFlow) {
|
||||
nextInFlow->GetOffsets(start, end);
|
||||
nextInFlow->AdjustOffsetsForBidi(newEnd, end);
|
||||
} // nextInFlow
|
||||
} // newEnd != end
|
||||
} // !NS_FRAME_IS_COMPLETE(aReflowStatus)
|
||||
} // isBidiFrame
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -139,10 +139,16 @@
|
||||
// This bit is set on frames that trimmed trailing whitespace characters when
|
||||
// calculating their width during reflow.
|
||||
#define TEXT_TRIMMED_TRAILING_WHITESPACE 0x01000000
|
||||
// Set when the frame's text may have a different style from its in-flow
|
||||
// brethren (e.g. the frame is in first-letter or first-line), so text runs
|
||||
// may need to be reconstructed when the frame's content offset/length changes.
|
||||
// We set this on the frame that has in first-letter or first-line, but not
|
||||
// in-flow siblings outside first-letter or first-line.
|
||||
#define TEXT_RUN_LAYOUT_DEPENDENT 0x02000000
|
||||
|
||||
#define TEXT_REFLOW_FLAGS \
|
||||
(TEXT_FIRST_LETTER|TEXT_START_OF_LINE|TEXT_END_OF_LINE|TEXT_HYPHEN_BREAK| \
|
||||
TEXT_TRIMMED_TRAILING_WHITESPACE)
|
||||
TEXT_TRIMMED_TRAILING_WHITESPACE|TEXT_RUN_LAYOUT_DEPENDENT)
|
||||
|
||||
// Cache bits for IsEmpty().
|
||||
// Set this bit if the textframe is known to be only collapsible whitespace.
|
||||
@ -302,6 +308,7 @@ public:
|
||||
nsTextFrame(nsStyleContext* aContext) : nsFrame(aContext)
|
||||
{
|
||||
NS_ASSERTION(mContentOffset == 0, "Bogus content offset");
|
||||
NS_ASSERTION(mContentLength == 0, "Bogus content length");
|
||||
}
|
||||
|
||||
// nsIFrame
|
||||
@ -394,9 +401,6 @@ public:
|
||||
|
||||
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval);
|
||||
|
||||
// Update offsets to account for new length. This may clear mTextRun.
|
||||
void SetLength(PRInt32 aLength);
|
||||
|
||||
NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const;
|
||||
|
||||
virtual void AdjustOffsetsForBidi(PRInt32 start, PRInt32 end);
|
||||
@ -503,12 +507,8 @@ public:
|
||||
#endif
|
||||
|
||||
PRInt32 GetContentOffset() const { return mContentOffset; }
|
||||
PRInt32 GetContentLength() const { return GetContentEnd() - mContentOffset; }
|
||||
PRInt32 GetContentEnd() const;
|
||||
// This returns the length the frame thinks it *should* have after it was
|
||||
// last reflowed (0 if it hasn't been reflowed yet). This should be used only
|
||||
// when setting up the text offsets for a new continuation frame.
|
||||
PRInt32 GetContentLengthHint() const { return mContentLengthHint; }
|
||||
PRInt32 GetContentLength() const { return mContentLength; }
|
||||
PRInt32 GetContentEnd() const { return mContentOffset + mContentLength; }
|
||||
|
||||
// Compute the length of the content mapped by this frame
|
||||
// and all its in-flow siblings. Basically this means starting at mContentOffset
|
||||
@ -534,8 +534,7 @@ public:
|
||||
gfxSkipCharsIterator EnsureTextRun(nsIRenderingContext* aRC = nsnull,
|
||||
nsIFrame* aLineContainer = nsnull,
|
||||
const nsLineList::iterator* aLine = nsnull,
|
||||
PRUint32* aFlowEndInTextRun = nsnull,
|
||||
PRBool aInReflow = PR_FALSE);
|
||||
PRUint32* aFlowEndInTextRun = nsnull);
|
||||
|
||||
gfxTextRun* GetTextRun() { return mTextRun; }
|
||||
void SetTextRun(gfxTextRun* aTextRun) { mTextRun = aTextRun; }
|
||||
@ -555,20 +554,8 @@ protected:
|
||||
virtual ~nsTextFrame();
|
||||
|
||||
nsIFrame* mNextContinuation;
|
||||
// The key invariant here is that mContentOffset never decreases along
|
||||
// a next-continuation chain. And of course mContentOffset is always <= the
|
||||
// the text node's content length, and the mContentOffset for the first frame
|
||||
// is always 0. Furthermore the text mapped by a frame is determined by
|
||||
// GetContentOffset() and GetContentLength()/GetContentEnd(), which get
|
||||
// the length from the difference between this frame's offset and the next
|
||||
// frame's offset, or the text length if there is no next frame. This means
|
||||
// the frames always map the text node without overlapping or leaving any gaps.
|
||||
PRInt32 mContentOffset;
|
||||
// This does *not* indicate the length of text currently mapped by the frame;
|
||||
// instead it's a hint saying that this frame *wants* to map this much text
|
||||
// so if we create a new continuation, this is where that continuation should
|
||||
// start.
|
||||
PRInt32 mContentLengthHint;
|
||||
PRInt32 mContentLength;
|
||||
nscoord mAscent;
|
||||
gfxTextRun* mTextRun;
|
||||
|
||||
@ -579,6 +566,8 @@ protected:
|
||||
PRBool isRTLChars,
|
||||
PRBool isOddLevel,
|
||||
PRBool isBidiSystem);
|
||||
|
||||
void SetOffsets(PRInt32 start, PRInt32 end);
|
||||
};
|
||||
|
||||
static void
|
||||
@ -723,11 +712,6 @@ nsTextFrameTextRunCache::Shutdown() {
|
||||
gTextRuns = nsnull;
|
||||
}
|
||||
|
||||
PRInt32 nsTextFrame::GetContentEnd() const {
|
||||
nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation());
|
||||
return next ? next->GetContentOffset() : mContent->GetText()->GetLength();
|
||||
}
|
||||
|
||||
PRInt32 nsTextFrame::GetInFlowContentLength() {
|
||||
#ifdef IBMBIDI
|
||||
nsTextFrame* nextBidi = nsnull;
|
||||
@ -1213,8 +1197,6 @@ BuildTextRuns(nsIRenderingContext* aRC, nsTextFrame* aForFrame,
|
||||
NS_ASSERTION(line != endLines && !line->IsBlock(), "Where is this frame anyway??");
|
||||
nsIFrame* child = line->mFirstChild;
|
||||
do {
|
||||
line->SetInvalidateTextRuns(PR_FALSE);
|
||||
|
||||
scanner.SetAtStartOfLine();
|
||||
scanner.SetCommonAncestorWithLastFrame(nsnull);
|
||||
PRInt32 i;
|
||||
@ -1363,9 +1345,12 @@ void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
|
||||
!HasTerminalNewline(mLastFrame)) {
|
||||
nsTextFrame* frame = static_cast<nsTextFrame*>(aFrame);
|
||||
mappedFlow->mEndFrame = static_cast<nsTextFrame*>(frame->GetNextInFlow());
|
||||
NS_ASSERTION(mappedFlow->mContentEndOffset == frame->GetContentOffset(),
|
||||
"Overlapping or discontiguous frames => BAD");
|
||||
mappedFlow->mContentEndOffset = frame->GetContentEnd();
|
||||
// Frames in the same flow can overlap at least temporarily
|
||||
// (e.g. when first-line builds its textrun, we need to have it suck
|
||||
// up all the in-flow content because we don't know how long the line
|
||||
// is going to be).
|
||||
mappedFlow->mContentEndOffset =
|
||||
PR_MAX(mappedFlow->mContentEndOffset, frame->GetContentEnd());
|
||||
if (mCurrentFramesAllSameTextRun != frame->GetTextRun()) {
|
||||
mCurrentFramesAllSameTextRun = nsnull;
|
||||
}
|
||||
@ -1587,8 +1572,10 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
|
||||
PRInt32 contentLength = contentEnd - contentStart;
|
||||
|
||||
if (content == lastContent) {
|
||||
NS_ASSERTION(endOfLastContent == contentStart,
|
||||
"Gap or overlap in textframes mapping content?!");
|
||||
NS_ASSERTION(endOfLastContent >= contentStart,
|
||||
"Gap in textframes mapping content?!");
|
||||
// Text frames can overlap (see comment in ScanFrame below)
|
||||
contentStart = PR_MAX(contentStart, endOfLastContent);
|
||||
if (contentStart >= contentEnd)
|
||||
continue;
|
||||
userData->mMappedFlows[finalMappedFlowCount - 1].mContentLength += contentLength;
|
||||
@ -1969,10 +1956,9 @@ GetReferenceRenderingContext(nsTextFrame* aTextFrame, nsIRenderingContext* aRC)
|
||||
gfxSkipCharsIterator
|
||||
nsTextFrame::EnsureTextRun(nsIRenderingContext* aRC, nsIFrame* aLineContainer,
|
||||
const nsLineList::iterator* aLine,
|
||||
PRUint32* aFlowEndInTextRun,
|
||||
PRBool aInReflow)
|
||||
PRUint32* aFlowEndInTextRun)
|
||||
{
|
||||
if (mTextRun && aLine && !(*aLine)->GetInvalidateTextRuns()) {
|
||||
if (mTextRun) {
|
||||
if (mTextRun->GetExpirationState()->IsTracked()) {
|
||||
gTextRuns->MarkUsed(mTextRun);
|
||||
}
|
||||
@ -2054,7 +2040,7 @@ nsTextFrame::GetTrimmedOffsets(const nsTextFragment* aFrag,
|
||||
{
|
||||
NS_ASSERTION(mTextRun, "Need textrun here");
|
||||
|
||||
TrimmedOffsets offsets = { GetContentOffset(), GetContentLength() };
|
||||
TrimmedOffsets offsets = { mContentOffset, mContentLength };
|
||||
const nsStyleText* textStyle = GetStyleText();
|
||||
if (textStyle->WhiteSpaceIsSignificant())
|
||||
return offsets;
|
||||
@ -3218,9 +3204,13 @@ nsTextFrame::Init(nsIContent* aContent,
|
||||
NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!");
|
||||
NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT),
|
||||
"Bogus content!");
|
||||
nsresult rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
// Note that if we're created due to bidi splitting the bidi code
|
||||
// will override what we compute here, so it's ok.
|
||||
// We're not a continuing frame.
|
||||
// mContentOffset = 0; not necessary since we get zeroed out at init
|
||||
return nsFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
mContentLength = GetInFlowContentLength();
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
@ -3303,14 +3293,8 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
|
||||
SetPrevInFlow(aPrevInFlow);
|
||||
aPrevInFlow->SetNextInFlow(this);
|
||||
nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow);
|
||||
mContentOffset = prev->GetContentOffset() + prev->GetContentLengthHint();
|
||||
if (prev->GetStyleContext() != GetStyleContext()) {
|
||||
// We're taking part of prev's text, and its style may be different
|
||||
// so clear its textrun which may no longer be valid (and don't set ours)
|
||||
prev->ClearTextRun();
|
||||
} else {
|
||||
mTextRun = prev->GetTextRun();
|
||||
}
|
||||
mTextRun = prev->GetTextRun();
|
||||
mContentOffset = prev->GetContentEnd();
|
||||
#ifdef IBMBIDI
|
||||
if (aPrevInFlow->GetStateBits() & NS_FRAME_IS_BIDI) {
|
||||
PRInt32 start, end;
|
||||
@ -3330,6 +3314,7 @@ nsContinuingTextFrame::Init(nsIContent* aContent,
|
||||
SetNextContinuation(nextContinuation);
|
||||
nextContinuation->SetPrevContinuation(this);
|
||||
nextContinuation->GetOffsets(start, end);
|
||||
mContentLength = PR_MAX(1, start - mContentOffset);
|
||||
}
|
||||
mState |= NS_FRAME_IS_BIDI;
|
||||
} // prev frame is bidi
|
||||
@ -3560,13 +3545,15 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext,
|
||||
ClearTextRunsInFlowChain(this);
|
||||
|
||||
nsTextFrame* targetTextFrame;
|
||||
nsTextFrame* lastTextFrame;
|
||||
PRInt32 nodeLength = mContent->GetText()->GetLength();
|
||||
|
||||
if (aAppend) {
|
||||
targetTextFrame = static_cast<nsTextFrame*>(GetLastContinuation());
|
||||
targetTextFrame->mState &= ~TEXT_WHITESPACE_FLAGS;
|
||||
lastTextFrame = static_cast<nsTextFrame*>(GetLastContinuation());
|
||||
lastTextFrame->mState &= ~TEXT_WHITESPACE_FLAGS;
|
||||
targetTextFrame = lastTextFrame;
|
||||
} else {
|
||||
// Mark all the continuation frames as dirty, and fix up content offsets to
|
||||
// Mark all the continuation frames as dirty, and fix up mContentLengths to
|
||||
// be valid.
|
||||
// Don't set NS_FRAME_IS_DIRTY on |this|, since we call FrameNeedsReflow
|
||||
// below.
|
||||
@ -3578,6 +3565,10 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext,
|
||||
if (textFrame->mContentOffset > newLength) {
|
||||
textFrame->mContentOffset = newLength;
|
||||
}
|
||||
if (textFrame->mContentOffset + textFrame->mContentLength > newLength) {
|
||||
textFrame->mContentLength = newLength - textFrame->mContentOffset;
|
||||
}
|
||||
lastTextFrame = textFrame;
|
||||
textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation());
|
||||
if (!textFrame) {
|
||||
break;
|
||||
@ -3586,6 +3577,8 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext,
|
||||
} while (1);
|
||||
targetTextFrame = this;
|
||||
}
|
||||
// Set the length of the last text frame in the chain (necessary if the node grew)
|
||||
lastTextFrame->mContentLength = nodeLength - lastTextFrame->mContentOffset;
|
||||
|
||||
// Ask the parent frame to reflow me.
|
||||
aPresContext->GetPresShell()->FrameNeedsReflow(targetTextFrame,
|
||||
@ -3663,8 +3656,8 @@ nsTextFrame::GetSelectionDetails()
|
||||
{
|
||||
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
|
||||
SelectionDetails* details =
|
||||
GetFrameSelection()->LookUpSelection(mContent, GetContentOffset(),
|
||||
GetContentLength(), PR_FALSE);
|
||||
GetFrameSelection()->LookUpSelection(mContent, mContentOffset,
|
||||
mContentLength, PR_FALSE);
|
||||
SelectionDetails* sd;
|
||||
for (sd = details; sd; sd = sd->mNext) {
|
||||
sd->mStart += mContentOffset;
|
||||
@ -4515,7 +4508,7 @@ nsTextFrame::GetPointFromOffset(nsPresContext* aPresContext,
|
||||
if (mState & NS_FRAME_IS_DIRTY)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (GetContentLength() <= 0) {
|
||||
if (mContentLength <= 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -4617,7 +4610,7 @@ nsTextFrame::GetChildFrameContainingOffset(PRInt32 aContentOffset,
|
||||
PRBool
|
||||
nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
|
||||
{
|
||||
NS_ASSERTION(aOffset && *aOffset <= GetContentLength(), "aOffset out of range");
|
||||
NS_ASSERTION(aOffset && *aOffset <= mContentLength, "aOffset out of range");
|
||||
|
||||
gfxSkipCharsIterator iter = EnsureTextRun();
|
||||
if (!mTextRun)
|
||||
@ -4661,8 +4654,7 @@ private:
|
||||
PRBool
|
||||
nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
|
||||
{
|
||||
PRInt32 contentLength = GetContentLength();
|
||||
NS_ASSERTION(aOffset && *aOffset <= contentLength, "aOffset out of range");
|
||||
NS_ASSERTION(aOffset && *aOffset <= mContentLength, "aOffset out of range");
|
||||
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
@ -4677,7 +4669,7 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
|
||||
TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_TRUE);
|
||||
|
||||
// A negative offset means "end of frame".
|
||||
PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
|
||||
PRInt32 startOffset = mContentOffset + (*aOffset < 0 ? mContentLength : *aOffset);
|
||||
|
||||
if (!aForward) {
|
||||
PRInt32 i;
|
||||
@ -4705,7 +4697,7 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
*aOffset = contentLength;
|
||||
*aOffset = mContentLength;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
@ -4811,8 +4803,7 @@ PRBool
|
||||
nsTextFrame::PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool aIsKeyboardSelect,
|
||||
PRInt32* aOffset, PRBool* aSawBeforeType)
|
||||
{
|
||||
PRInt32 contentLength = GetContentLength();
|
||||
NS_ASSERTION (aOffset && *aOffset <= contentLength, "aOffset out of range");
|
||||
NS_ASSERTION (aOffset && *aOffset <= mContentLength, "aOffset out of range");
|
||||
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
@ -4820,7 +4811,7 @@ nsTextFrame::PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool
|
||||
if (selectStyle == NS_STYLE_USER_SELECT_ALL)
|
||||
return PR_FALSE;
|
||||
|
||||
PRInt32 offset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
|
||||
PRInt32 offset = mContentOffset + (*aOffset < 0 ? mContentLength : *aOffset);
|
||||
ClusterIterator cIter(this, offset, aForward ? 1 : -1);
|
||||
|
||||
if (!cIter.NextCluster())
|
||||
@ -4967,7 +4958,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
|
||||
{
|
||||
PRUint32 flowEndInTextRun;
|
||||
gfxSkipCharsIterator iter =
|
||||
EnsureTextRun(aRenderingContext, nsnull, aData->line, &flowEndInTextRun);
|
||||
EnsureTextRun(aRenderingContext, nsnull, nsnull, &flowEndInTextRun);
|
||||
if (!mTextRun)
|
||||
return;
|
||||
|
||||
@ -5065,7 +5056,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
|
||||
{
|
||||
PRUint32 flowEndInTextRun;
|
||||
gfxSkipCharsIterator iter =
|
||||
EnsureTextRun(aRenderingContext, nsnull, aData->line, &flowEndInTextRun);
|
||||
EnsureTextRun(aRenderingContext, nsnull, nsnull, &flowEndInTextRun);
|
||||
if (!mTextRun)
|
||||
return;
|
||||
|
||||
@ -5200,34 +5191,6 @@ HasSoftHyphenBefore(const nsTextFragment* aFrag, gfxTextRun* aTextRun,
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::SetLength(PRInt32 aLength)
|
||||
{
|
||||
mContentLengthHint = aLength;
|
||||
PRInt32 end = GetContentOffset() + aLength;
|
||||
nsTextFrame* f = static_cast<nsTextFrame*>(GetNextInFlow());
|
||||
if (!f)
|
||||
return;
|
||||
if (end < f->mContentOffset) {
|
||||
// Our frame is shrinking. Give the text to our next in flow.
|
||||
f->mContentOffset = end;
|
||||
if (f->GetTextRun() != mTextRun) {
|
||||
ClearTextRun();
|
||||
f->ClearTextRun();
|
||||
}
|
||||
return;
|
||||
}
|
||||
while (f && f->mContentOffset < end) {
|
||||
// Our frame is growing. Take text from our in-flow.
|
||||
f->mContentOffset = end;
|
||||
if (f->GetTextRun() != mTextRun) {
|
||||
ClearTextRun();
|
||||
f->ClearTextRun();
|
||||
}
|
||||
f = static_cast<nsTextFrame*>(f->GetNextInFlow());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
@ -5251,17 +5214,25 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
// can change whether the frame maps whitespace-only text or not.
|
||||
RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
|
||||
|
||||
nsTextFrame* prevInFlow = static_cast<nsTextFrame*>(GetPrevInFlow());
|
||||
if (prevInFlow) {
|
||||
// Our mContentOffset may be out of date due to our prev-in-flow growing or
|
||||
// shrinking. Update it.
|
||||
mContentOffset = prevInFlow->GetContentEnd();
|
||||
}
|
||||
|
||||
// Temporarily map all possible content while we construct our new textrun.
|
||||
// so that when doing reflow our styles prevail over any part of the
|
||||
// textrun we look at. Note that next-in-flows may be mapping the same
|
||||
// content; gfxTextRun construction logic will ensure that we take priority.
|
||||
PRInt32 maxContentLength = GetInFlowContentLength();
|
||||
mContentLength = maxContentLength;
|
||||
|
||||
// XXX If there's no line layout, we shouldn't even have created this
|
||||
// frame. This may happen if, for example, this is text inside a table
|
||||
// but not inside a cell. For now, just don't reflow. We also don't need to
|
||||
// reflow if there is no content.
|
||||
if (!aReflowState.mLineLayout || !maxContentLength) {
|
||||
if (!aReflowState.mLineLayout || !mContentLength) {
|
||||
ClearMetrics(aMetrics);
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
@ -5300,7 +5271,11 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
PRBool layoutDependentTextRun =
|
||||
lineLayout.GetFirstLetterStyleOK() || lineLayout.GetInFirstLine();
|
||||
if (layoutDependentTextRun) {
|
||||
SetLength(maxContentLength);
|
||||
AddStateBits(TEXT_RUN_LAYOUT_DEPENDENT);
|
||||
}
|
||||
if (layoutDependentTextRun ||
|
||||
(prevInFlow && (prevInFlow->GetStateBits() & TEXT_RUN_LAYOUT_DEPENDENT))) {
|
||||
ClearTextRun();
|
||||
}
|
||||
|
||||
PRUint32 flowEndInTextRun;
|
||||
@ -5319,8 +5294,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
// DOM offsets of the text range we need to measure, after trimming
|
||||
// whitespace, restricting to first-letter, and restricting preformatted text
|
||||
// to nearest newline
|
||||
PRInt32 length = maxContentLength;
|
||||
PRInt32 offset = GetContentOffset();
|
||||
PRInt32 length = mContentLength;
|
||||
PRInt32 offset = mContentOffset;
|
||||
|
||||
// Restrict preformatted text to the nearest newline
|
||||
PRInt32 newLineOffset = -1;
|
||||
@ -5472,7 +5447,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
// Record that whitespace has already been trimmed.
|
||||
AddStateBits(TEXT_TRIMMED_TRAILING_WHITESPACE);
|
||||
}
|
||||
PRInt32 contentLength = offset + charsFit - GetContentOffset();
|
||||
mContentLength = offset + charsFit - mContentOffset;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Compute output metrics
|
||||
@ -5551,13 +5526,13 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Compute reflow status
|
||||
aStatus = contentLength == maxContentLength
|
||||
aStatus = mContentLength == maxContentLength
|
||||
? NS_FRAME_COMPLETE : NS_FRAME_NOT_COMPLETE;
|
||||
|
||||
if (charsFit == 0 && length > 0) {
|
||||
// Couldn't place any text
|
||||
aStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
||||
} else if (contentLength > 0 && contentLength - 1 == newLineOffset) {
|
||||
} else if (mContentLength > 0 && mContentLength - 1 == newLineOffset) {
|
||||
// Ends in \n
|
||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
|
||||
lineLayout.SetLineEndsInBR(PR_TRUE);
|
||||
@ -5588,7 +5563,10 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
charsFit - numJustifiableCharacters);
|
||||
}
|
||||
|
||||
SetLength(contentLength);
|
||||
if (layoutDependentTextRun) {
|
||||
// Nuke any text run since it may not be valid now that we have reflowed
|
||||
ClearTextRun();
|
||||
}
|
||||
|
||||
Invalidate(nsRect(nsPoint(0, 0), GetSize()));
|
||||
|
||||
@ -5620,8 +5598,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsPresContext* aPresContext,
|
||||
|
||||
AddStateBits(TEXT_END_OF_LINE);
|
||||
|
||||
PRInt32 contentLength = GetContentLength();
|
||||
if (!contentLength)
|
||||
if (!mContentLength)
|
||||
return NS_OK;
|
||||
|
||||
gfxSkipCharsIterator start = EnsureTextRun(&aRC);
|
||||
@ -5640,11 +5617,11 @@ nsTextFrame::TrimTrailingWhiteSpace(nsPresContext* aPresContext,
|
||||
aLastCharIsJustifiable = PR_TRUE;
|
||||
} else if (trimmed.GetEnd() < GetContentEnd()) {
|
||||
gfxSkipCharsIterator end = iter;
|
||||
PRUint32 endOffset = end.ConvertOriginalToSkipped(GetContentOffset() + contentLength);
|
||||
PRUint32 endOffset = end.ConvertOriginalToSkipped(mContentOffset + mContentLength);
|
||||
if (trimmedEnd < endOffset) {
|
||||
// We can't be dealing with tabs here ... they wouldn't be trimmed. So it's
|
||||
// OK to pass null for the line container.
|
||||
PropertyProvider provider(mTextRun, textStyle, frag, this, start, contentLength,
|
||||
PropertyProvider provider(mTextRun, textStyle, frag, this, start, mContentLength,
|
||||
nsnull, 0);
|
||||
delta = mTextRun->GetAdvanceWidth(trimmedEnd, endOffset - trimmedEnd, &provider);
|
||||
// non-compressed whitespace being skipped at end of line -> justifiable
|
||||
@ -5657,7 +5634,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsPresContext* aPresContext,
|
||||
if (!aLastCharIsJustifiable &&
|
||||
NS_STYLE_TEXT_ALIGN_JUSTIFY == textStyle->mTextAlign) {
|
||||
// Check if any character in the last cluster is justifiable
|
||||
PropertyProvider provider(mTextRun, textStyle, frag, this, start, contentLength,
|
||||
PropertyProvider provider(mTextRun, textStyle, frag, this, start, mContentLength,
|
||||
nsnull, 0);
|
||||
PRBool isCJK = IsChineseJapaneseLangGroup(this);
|
||||
gfxSkipCharsIterator justificationEnd(iter);
|
||||
@ -5737,8 +5714,8 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString,
|
||||
gfxSkipCharsBuilder skipCharsBuilder;
|
||||
nsTextFrame* textFrame;
|
||||
const nsTextFragment* textFrag = mContent->GetText();
|
||||
PRUint32 keptCharsLength = 0;
|
||||
PRUint32 validCharsLength = 0;
|
||||
PRInt32 keptCharsLength = 0;
|
||||
PRInt32 validCharsLength = 0;
|
||||
|
||||
// Build skipChars and copy text, for each text frame in this continuation block
|
||||
for (textFrame = this; textFrame;
|
||||
@ -5766,10 +5743,10 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString,
|
||||
while (iter.GetOriginalOffset() < trimmedContentOffsets.GetEnd() &&
|
||||
keptCharsLength < aSkippedMaxLength) {
|
||||
// For each original char from content text
|
||||
if (iter.IsOriginalCharSkipped() || ++validCharsLength <= aSkippedStartOffset) {
|
||||
if (iter.IsOriginalCharSkipped() || ++ validCharsLength <= aSkippedStartOffset) {
|
||||
skipCharsBuilder.SkipChar();
|
||||
} else {
|
||||
++keptCharsLength;
|
||||
++ keptCharsLength;
|
||||
skipCharsBuilder.KeepChar();
|
||||
if (aAppendToString) {
|
||||
aAppendToString->Append(
|
||||
@ -5810,13 +5787,12 @@ nsTextFrame::ToCString(nsString& aBuf, PRInt32* aTotalContentLength) const
|
||||
// Compute the total length of the text content.
|
||||
*aTotalContentLength = frag->GetLength();
|
||||
|
||||
PRInt32 contentLength = GetContentLength();
|
||||
// Set current fragment and current fragment offset
|
||||
if (0 == contentLength) {
|
||||
if (0 == mContentLength) {
|
||||
return;
|
||||
}
|
||||
PRInt32 fragOffset = GetContentOffset();
|
||||
PRInt32 n = fragOffset + contentLength;
|
||||
PRInt32 fragOffset = mContentOffset;
|
||||
PRInt32 n = fragOffset + mContentLength;
|
||||
while (fragOffset < n) {
|
||||
PRUnichar ch = frag->CharAt(fragOffset++);
|
||||
if (ch == '\r') {
|
||||
@ -5901,7 +5877,7 @@ nsTextFrame::List(FILE* out, PRInt32 aIndent) const
|
||||
// Output the first/last content offset and prev/next in flow info
|
||||
PRBool isComplete = GetContentEnd() == totalContentLength;
|
||||
fprintf(out, "[%d,%d,%c] ",
|
||||
GetContentOffset(), GetContentLength(),
|
||||
mContentOffset, mContentLength,
|
||||
isComplete ? 'T':'F');
|
||||
|
||||
if (nsnull != mNextSibling) {
|
||||
@ -6008,24 +5984,20 @@ void
|
||||
nsTextFrame::AdjustOffsetsForBidi(PRInt32 aStart, PRInt32 aEnd)
|
||||
{
|
||||
AddStateBits(NS_FRAME_IS_BIDI);
|
||||
SetOffsets(aStart, aEnd);
|
||||
/*
|
||||
* After Bidi resolution we may need to reassign text runs.
|
||||
* This is called during bidi resolution from the block container, so we
|
||||
* shouldn't be holding a local reference to a textrun anywhere.
|
||||
*/
|
||||
ClearTextRun();
|
||||
}
|
||||
|
||||
nsTextFrame* prev = static_cast<nsTextFrame*>(GetPrevInFlow());
|
||||
if (prev) {
|
||||
// the bidi resolver can be very evil when columns/pages are involved. Don't
|
||||
// let it violate our invariants.
|
||||
PRInt32 prevOffset = prev->GetContentOffset();
|
||||
aStart = PR_MAX(aStart, prevOffset);
|
||||
aEnd = PR_MAX(aEnd, prevOffset);
|
||||
}
|
||||
if (mContentOffset != aStart) {
|
||||
mContentOffset = aStart;
|
||||
ClearTextRun();
|
||||
if (prev) {
|
||||
prev->ClearTextRun();
|
||||
}
|
||||
}
|
||||
|
||||
SetLength(aEnd - aStart);
|
||||
void
|
||||
nsTextFrame::SetOffsets(PRInt32 aStart, PRInt32 aEnd)
|
||||
{
|
||||
mContentOffset = aStart;
|
||||
mContentLength = aEnd - aStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user