mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 580167 part 1. Create an nsTextFrame::ReflowText that doesn't need a reflow state. r=dbaron
This commit is contained in:
parent
51fff79f07
commit
49fc0489a4
@ -367,6 +367,11 @@ public:
|
|||||||
TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
|
TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
|
||||||
PRBool aTrimAfter);
|
PRBool aTrimAfter);
|
||||||
|
|
||||||
|
// Similar to Reflow(), but for use from nsLineLayout
|
||||||
|
void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||||
|
nsIRenderingContext* aRenderingContext, PRBool aShouldBlink,
|
||||||
|
nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsTextFrame();
|
virtual ~nsTextFrame();
|
||||||
|
|
||||||
|
@ -6195,12 +6195,38 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
{
|
{
|
||||||
DO_GLOBAL_REFLOW_COUNT("nsTextFrame");
|
DO_GLOBAL_REFLOW_COUNT("nsTextFrame");
|
||||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
if (!aReflowState.mLineLayout) {
|
||||||
|
ClearMetrics(aMetrics);
|
||||||
|
aStatus = NS_FRAME_COMPLETE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReflowText(*aReflowState.mLineLayout, aReflowState.availableWidth,
|
||||||
|
aReflowState.rendContext, aReflowState.mFlags.mBlinks,
|
||||||
|
aMetrics, aStatus);
|
||||||
|
|
||||||
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||||
|
nsIRenderingContext* aRenderingContext,
|
||||||
|
PRBool aShouldBlink,
|
||||||
|
nsHTMLReflowMetrics& aMetrics,
|
||||||
|
nsReflowStatus& aStatus)
|
||||||
|
{
|
||||||
#ifdef NOISY_REFLOW
|
#ifdef NOISY_REFLOW
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": BeginReflow: availableSize=%d,%d\n",
|
printf(": BeginReflow: availableWidth=%d\n", aAvailableWidth);
|
||||||
aReflowState.availableWidth, aReflowState.availableHeight);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
nsPresContext* presContext = PresContext();
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
// Set up flags and clear out state
|
// Set up flags and clear out state
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
@ -6216,22 +6242,17 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
// content; gfxTextRun construction logic will ensure that we take priority.
|
// content; gfxTextRun construction logic will ensure that we take priority.
|
||||||
PRInt32 maxContentLength = GetInFlowContentLength();
|
PRInt32 maxContentLength = GetInFlowContentLength();
|
||||||
|
|
||||||
// XXX If there's no line layout, we shouldn't even have created this
|
// We don't need to reflow if there is no content.
|
||||||
// frame. This may happen if, for example, this is text inside a table
|
if (!maxContentLength) {
|
||||||
// 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) {
|
|
||||||
ClearMetrics(aMetrics);
|
ClearMetrics(aMetrics);
|
||||||
aStatus = NS_FRAME_COMPLETE;
|
aStatus = NS_FRAME_COMPLETE;
|
||||||
return NS_OK;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLineLayout& lineLayout = *aReflowState.mLineLayout;
|
if (aShouldBlink) {
|
||||||
|
|
||||||
if (aReflowState.mFlags.mBlinks) {
|
|
||||||
if (0 == (mState & TEXT_BLINK_ON)) {
|
if (0 == (mState & TEXT_BLINK_ON)) {
|
||||||
mState |= TEXT_BLINK_ON;
|
mState |= TEXT_BLINK_ON;
|
||||||
nsBlinkTimer::AddBlinkFrame(aPresContext, this);
|
nsBlinkTimer::AddBlinkFrame(presContext, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -6243,14 +6264,14 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
const nsStyleText* textStyle = GetStyleText();
|
const nsStyleText* textStyle = GetStyleText();
|
||||||
|
|
||||||
PRBool atStartOfLine = lineLayout.LineAtStart();
|
PRBool atStartOfLine = aLineLayout.LineAtStart();
|
||||||
if (atStartOfLine) {
|
if (atStartOfLine) {
|
||||||
AddStateBits(TEXT_START_OF_LINE);
|
AddStateBits(TEXT_START_OF_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 flowEndInTextRun;
|
PRUint32 flowEndInTextRun;
|
||||||
nsIFrame* lineContainer = lineLayout.GetLineContainerFrame();
|
nsIFrame* lineContainer = aLineLayout.GetLineContainerFrame();
|
||||||
gfxContext* ctx = aReflowState.rendContext->ThebesContext();
|
gfxContext* ctx = aRenderingContext->ThebesContext();
|
||||||
const nsTextFragment* frag = mContent->GetText();
|
const nsTextFragment* frag = mContent->GetText();
|
||||||
|
|
||||||
// DOM offsets of the text range we need to measure, after trimming
|
// DOM offsets of the text range we need to measure, after trimming
|
||||||
@ -6290,21 +6311,21 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
PRBool completedFirstLetter = PR_FALSE;
|
PRBool completedFirstLetter = PR_FALSE;
|
||||||
// Layout dependent styles are a problem because we need to reconstruct
|
// Layout dependent styles are a problem because we need to reconstruct
|
||||||
// the gfxTextRun based on our layout.
|
// the gfxTextRun based on our layout.
|
||||||
if (lineLayout.GetInFirstLetter() || lineLayout.GetInFirstLine()) {
|
if (aLineLayout.GetInFirstLetter() || aLineLayout.GetInFirstLine()) {
|
||||||
SetLength(maxContentLength, &lineLayout);
|
SetLength(maxContentLength, &aLineLayout);
|
||||||
|
|
||||||
if (lineLayout.GetInFirstLetter()) {
|
if (aLineLayout.GetInFirstLetter()) {
|
||||||
// floating first-letter boundaries are significant in textrun
|
// floating first-letter boundaries are significant in textrun
|
||||||
// construction, so clear the textrun out every time we hit a first-letter
|
// construction, so clear the textrun out every time we hit a first-letter
|
||||||
// and have changed our length (which controls the first-letter boundary)
|
// and have changed our length (which controls the first-letter boundary)
|
||||||
ClearTextRun();
|
ClearTextRun();
|
||||||
// Find the length of the first-letter. We need a textrun for this.
|
// Find the length of the first-letter. We need a textrun for this.
|
||||||
gfxSkipCharsIterator iter =
|
gfxSkipCharsIterator iter =
|
||||||
EnsureTextRun(ctx, lineContainer, lineLayout.GetLine(), &flowEndInTextRun);
|
EnsureTextRun(ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun);
|
||||||
|
|
||||||
if (mTextRun) {
|
if (mTextRun) {
|
||||||
PRInt32 firstLetterLength = length;
|
PRInt32 firstLetterLength = length;
|
||||||
if (lineLayout.GetFirstLetterStyleOK()) {
|
if (aLineLayout.GetFirstLetterStyleOK()) {
|
||||||
completedFirstLetter =
|
completedFirstLetter =
|
||||||
FindFirstLetterRange(frag, mTextRun, offset, iter, &firstLetterLength);
|
FindFirstLetterRange(frag, mTextRun, offset, iter, &firstLetterLength);
|
||||||
if (newLineOffset >= 0) {
|
if (newLineOffset >= 0) {
|
||||||
@ -6333,7 +6354,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
// Change this frame's length to the first-letter length right now
|
// Change this frame's length to the first-letter length right now
|
||||||
// so that when we rebuild the textrun it will be built with the
|
// so that when we rebuild the textrun it will be built with the
|
||||||
// right first-letter boundary
|
// right first-letter boundary
|
||||||
SetLength(offset + length - GetContentOffset(), &lineLayout);
|
SetLength(offset + length - GetContentOffset(), &aLineLayout);
|
||||||
// Ensure that the textrun will be rebuilt
|
// Ensure that the textrun will be rebuilt
|
||||||
ClearTextRun();
|
ClearTextRun();
|
||||||
}
|
}
|
||||||
@ -6341,7 +6362,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gfxSkipCharsIterator iter =
|
gfxSkipCharsIterator iter =
|
||||||
EnsureTextRun(ctx, lineContainer, lineLayout.GetLine(), &flowEndInTextRun);
|
EnsureTextRun(ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun);
|
||||||
|
|
||||||
if (mTextRun && iter.GetOriginalEnd() < offset + length) {
|
if (mTextRun && iter.GetOriginalEnd() < offset + length) {
|
||||||
// The textrun does not map enough text for this frame. This can happen
|
// The textrun does not map enough text for this frame. This can happen
|
||||||
@ -6350,13 +6371,13 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
// consumed all the text of the textrun. We need a new textrun.
|
// consumed all the text of the textrun. We need a new textrun.
|
||||||
ClearTextRun();
|
ClearTextRun();
|
||||||
iter = EnsureTextRun(ctx, lineContainer,
|
iter = EnsureTextRun(ctx, lineContainer,
|
||||||
lineLayout.GetLine(), &flowEndInTextRun);
|
aLineLayout.GetLine(), &flowEndInTextRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mTextRun) {
|
if (!mTextRun) {
|
||||||
ClearMetrics(aMetrics);
|
ClearMetrics(aMetrics);
|
||||||
aStatus = NS_FRAME_COMPLETE;
|
aStatus = NS_FRAME_COMPLETE;
|
||||||
return NS_OK;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(gfxSkipCharsIterator(iter).ConvertOriginalToSkipped(offset + length)
|
NS_ASSERTION(gfxSkipCharsIterator(iter).ConvertOriginalToSkipped(offset + length)
|
||||||
@ -6369,7 +6390,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
iter.SetOriginalOffset(offset);
|
iter.SetOriginalOffset(offset);
|
||||||
nscoord xOffsetForTabs = (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) ?
|
nscoord xOffsetForTabs = (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) ?
|
||||||
(lineLayout.GetCurrentFrameXDistanceFromBlock() -
|
(aLineLayout.GetCurrentFrameXDistanceFromBlock() -
|
||||||
lineContainer->GetUsedBorderAndPadding().left)
|
lineContainer->GetUsedBorderAndPadding().left)
|
||||||
: -1;
|
: -1;
|
||||||
PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length,
|
PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length,
|
||||||
@ -6388,7 +6409,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRInt32 limitLength = length;
|
PRInt32 limitLength = length;
|
||||||
PRInt32 forceBreak = lineLayout.GetForcedBreakPosition(mContent);
|
PRInt32 forceBreak = aLineLayout.GetForcedBreakPosition(mContent);
|
||||||
PRBool forceBreakAfter = PR_FALSE;
|
PRBool forceBreakAfter = PR_FALSE;
|
||||||
if (forceBreak >= offset + length) {
|
if (forceBreak >= offset + length) {
|
||||||
forceBreakAfter = forceBreak == offset + length;
|
forceBreakAfter = forceBreak == offset + length;
|
||||||
@ -6418,16 +6439,16 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
PRUint32 transformedLastBreak = 0;
|
PRUint32 transformedLastBreak = 0;
|
||||||
PRBool usedHyphenation;
|
PRBool usedHyphenation;
|
||||||
gfxFloat trimmedWidth = 0;
|
gfxFloat trimmedWidth = 0;
|
||||||
gfxFloat availWidth = aReflowState.availableWidth;
|
gfxFloat availWidth = aAvailableWidth;
|
||||||
PRBool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant();
|
PRBool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant();
|
||||||
PRInt32 unusedOffset;
|
PRInt32 unusedOffset;
|
||||||
gfxBreakPriority breakPriority;
|
gfxBreakPriority breakPriority;
|
||||||
lineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority);
|
aLineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority);
|
||||||
PRUint32 transformedCharsFit =
|
PRUint32 transformedCharsFit =
|
||||||
mTextRun->BreakAndMeasureText(transformedOffset, transformedLength,
|
mTextRun->BreakAndMeasureText(transformedOffset, transformedLength,
|
||||||
(GetStateBits() & TEXT_START_OF_LINE) != 0,
|
(GetStateBits() & TEXT_START_OF_LINE) != 0,
|
||||||
availWidth,
|
availWidth,
|
||||||
&provider, !lineLayout.LineIsBreakable(),
|
&provider, !aLineLayout.LineIsBreakable(),
|
||||||
canTrimTrailingWhitespace ? &trimmedWidth : nsnull,
|
canTrimTrailingWhitespace ? &trimmedWidth : nsnull,
|
||||||
&textMetrics, boundingBoxType, ctx,
|
&textMetrics, boundingBoxType, ctx,
|
||||||
&usedHyphenation, &transformedLastBreak,
|
&usedHyphenation, &transformedLastBreak,
|
||||||
@ -6501,9 +6522,9 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
if (!brokeText && lastBreak >= 0) {
|
if (!brokeText && lastBreak >= 0) {
|
||||||
// Since everything fit and no break was forced,
|
// Since everything fit and no break was forced,
|
||||||
// record the last break opportunity
|
// record the last break opportunity
|
||||||
NS_ASSERTION(textMetrics.mAdvanceWidth - trimmableWidth <= aReflowState.availableWidth,
|
NS_ASSERTION(textMetrics.mAdvanceWidth - trimmableWidth <= aAvailableWidth,
|
||||||
"If the text doesn't fit, and we have a break opportunity, why didn't MeasureText use it?");
|
"If the text doesn't fit, and we have a break opportunity, why didn't MeasureText use it?");
|
||||||
lineLayout.NotifyOptionalBreakPosition(mContent, lastBreak, PR_TRUE, breakPriority);
|
aLineLayout.NotifyOptionalBreakPosition(mContent, lastBreak, PR_TRUE, breakPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 contentLength = offset + charsFit - GetContentOffset();
|
PRInt32 contentLength = offset + charsFit - GetContentOffset();
|
||||||
@ -6553,7 +6574,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
aMetrics.mOverflowArea.UnionRect(boundingBox,
|
aMetrics.mOverflowArea.UnionRect(boundingBox,
|
||||||
nsRect(0, 0, aMetrics.width, aMetrics.height));
|
nsRect(0, 0, aMetrics.width, aMetrics.height));
|
||||||
|
|
||||||
UnionTextDecorationOverflow(aPresContext, provider, &aMetrics.mOverflowArea);
|
UnionTextDecorationOverflow(presContext, provider, &aMetrics.mOverflowArea);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
// Clean up, update state
|
// Clean up, update state
|
||||||
@ -6565,13 +6586,13 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
// at most one space so there's no way for trimmable width from a previous
|
// at most one space so there's no way for trimmable width from a previous
|
||||||
// frame to accumulate with trimmable width from this frame.)
|
// frame to accumulate with trimmable width from this frame.)
|
||||||
if (transformedCharsFit > 0) {
|
if (transformedCharsFit > 0) {
|
||||||
lineLayout.SetTrimmableWidth(NSToCoordFloor(trimmableWidth));
|
aLineLayout.SetTrimmableWidth(NSToCoordFloor(trimmableWidth));
|
||||||
AddStateBits(TEXT_HAS_NONCOLLAPSED_CHARACTERS);
|
AddStateBits(TEXT_HAS_NONCOLLAPSED_CHARACTERS);
|
||||||
}
|
}
|
||||||
if (charsFit > 0 && charsFit == length &&
|
if (charsFit > 0 && charsFit == length &&
|
||||||
HasSoftHyphenBefore(frag, mTextRun, offset, end)) {
|
HasSoftHyphenBefore(frag, mTextRun, offset, end)) {
|
||||||
// Record a potential break after final soft hyphen
|
// Record a potential break after final soft hyphen
|
||||||
lineLayout.NotifyOptionalBreakPosition(mContent, offset + length,
|
aLineLayout.NotifyOptionalBreakPosition(mContent, offset + length,
|
||||||
textMetrics.mAdvanceWidth + provider.GetHyphenWidth() <= availWidth,
|
textMetrics.mAdvanceWidth + provider.GetHyphenWidth() <= availWidth,
|
||||||
eNormalBreak);
|
eNormalBreak);
|
||||||
}
|
}
|
||||||
@ -6592,8 +6613,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
if (textMetrics.mAdvanceWidth - trimmableWidth > availWidth) {
|
if (textMetrics.mAdvanceWidth - trimmableWidth > availWidth) {
|
||||||
breakAfter = PR_TRUE;
|
breakAfter = PR_TRUE;
|
||||||
} else {
|
} else {
|
||||||
lineLayout.NotifyOptionalBreakPosition(mContent, offset + length, PR_TRUE,
|
aLineLayout.NotifyOptionalBreakPosition(mContent, offset + length,
|
||||||
eNormalBreak);
|
PR_TRUE, eNormalBreak);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6607,12 +6628,12 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
} else if (contentLength > 0 && mContentOffset + contentLength - 1 == newLineOffset) {
|
} else if (contentLength > 0 && mContentOffset + contentLength - 1 == newLineOffset) {
|
||||||
// Ends in \n
|
// Ends in \n
|
||||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
|
aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
|
||||||
lineLayout.SetLineEndsInBR(PR_TRUE);
|
aLineLayout.SetLineEndsInBR(PR_TRUE);
|
||||||
} else if (breakAfter) {
|
} else if (breakAfter) {
|
||||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
|
aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
|
||||||
}
|
}
|
||||||
if (completedFirstLetter) {
|
if (completedFirstLetter) {
|
||||||
lineLayout.SetFirstLetterStyleOK(PR_FALSE);
|
aLineLayout.SetFirstLetterStyleOK(PR_FALSE);
|
||||||
aStatus |= NS_INLINE_BREAK_FIRST_LETTER_COMPLETE;
|
aStatus |= NS_INLINE_BREAK_FIRST_LETTER_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6648,11 +6669,11 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
NS_ASSERTION(numJustifiableCharacters <= charsFit,
|
NS_ASSERTION(numJustifiableCharacters <= charsFit,
|
||||||
"Bad justifiable character count");
|
"Bad justifiable character count");
|
||||||
lineLayout.SetTextJustificationWeights(numJustifiableCharacters,
|
aLineLayout.SetTextJustificationWeights(numJustifiableCharacters,
|
||||||
charsFit - numJustifiableCharacters);
|
charsFit - numJustifiableCharacters);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLength(contentLength, &lineLayout);
|
SetLength(contentLength, &aLineLayout);
|
||||||
|
|
||||||
if (mContent->HasFlag(NS_TEXT_IN_SELECTION)) {
|
if (mContent->HasFlag(NS_TEXT_IN_SELECTION)) {
|
||||||
SelectionDetails* details = GetSelectionDetails();
|
SelectionDetails* details = GetSelectionDetails();
|
||||||
@ -6672,8 +6693,6 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
aMetrics.width, aMetrics.height, aMetrics.ascent,
|
aMetrics.width, aMetrics.height, aMetrics.ascent,
|
||||||
aStatus);
|
aStatus);
|
||||||
#endif
|
#endif
|
||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ PRBool
|
/* virtual */ PRBool
|
||||||
|
Loading…
Reference in New Issue
Block a user