Keep track of the line container and forget the current line if it's for a different container.
b=444027 r+sr=roc
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -672,16 +672,17 @@ nsBlockFrame::GetMinWidth(nsIRenderingCo
line == curFrame->begin_lines()) {
const nsStyleCoord &indent = GetStyleText()->mTextIndent;
if (indent.GetUnit() == eStyleUnit_Coord)
data.currentLine += indent.GetCoordValue();
}
// XXX Bug NNNNNN Should probably handle percentage text-indent.
data.line = &line;
+ data.lineContainer = curFrame;
nsIFrame *kid = line->mFirstChild;
for (PRInt32 i = 0, i_end = line->GetChildCount(); i != i_end;
++i, kid = kid->GetNextSibling()) {
kid->AddInlineMinWidth(aRenderingContext, &data);
}
}
#ifdef DEBUG
if (gNoisyIntrinsic) {
@@ -746,16 +747,17 @@ nsBlockFrame::GetPrefWidth(nsIRenderingC
line == curFrame->begin_lines()) {
const nsStyleCoord &indent = GetStyleText()->mTextIndent;
if (indent.GetUnit() == eStyleUnit_Coord)
data.currentLine += indent.GetCoordValue();
}
// XXX Bug NNNNNN Should probably handle percentage text-indent.
data.line = &line;
+ data.lineContainer = curFrame;
nsIFrame *kid = line->mFirstChild;
for (PRInt32 i = 0, i_end = line->GetChildCount(); i != i_end;
++i, kid = kid->GetNextSibling()) {
kid->AddInlinePrefWidth(aRenderingContext, &data);
}
}
#ifdef DEBUG
if (gNoisyIntrinsic) {
@@ -5238,17 +5240,17 @@ nsBlockInFlowLineIterator::Prev()
}
}
PRBool
nsBlockInFlowLineIterator::FindValidLine()
{
line_iterator end = mInOverflowLines ? mInOverflowLines->end() : mFrame->end_lines();
if (mLine != end)
- return PR_TRUE;
+ return PR_TRUE;
PRBool currentlyInOverflowLines = mInOverflowLines != nsnull;
while (PR_TRUE) {
if (currentlyInOverflowLines) {
mFrame = static_cast<nsBlockFrame*>(mFrame->GetNextInFlow());
if (!mFrame)
return PR_FALSE;
mInOverflowLines = nsnull;
mLine = mFrame->begin_lines();
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1168,26 +1168,30 @@ public:
* in inline layout. Code that determines the intrinsic width of a
* region of inline layout accumulates the result into this structure.
* This pattern is needed because we need to maintain state
* information about whitespace (for both collapsing and trimming).
*/
struct InlineIntrinsicWidthData {
InlineIntrinsicWidthData()
: line(nsnull)
+ , lineContainer(nsnull)
, prevLines(0)
, currentLine(0)
, skipWhitespace(PR_TRUE)
, trailingWhitespace(0)
{}
// The line. This may be null if the inlines are not associated with
// a block or if we just don't know the line.
const nsLineList_iterator* line;
+ // The line container.
+ nsIFrame* lineContainer;
+
// The maximum intrinsic width for all previous lines.
nscoord prevLines;
// The maximum intrinsic width for the current line. At a line
// break (mandatory for preferred width; allowed for minimum width),
// the caller should call |Break()|.
nscoord currentLine;
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -666,32 +666,32 @@ class nsLineList_iterator {
iterator_self_type copy(*this);
return --copy;
}
// Passing by value rather than by reference and reference to const
// to keep AIX happy.
PRBool operator==(const iterator_self_type aOther) const
{
- NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+ NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
return mCurrent == aOther.mCurrent;
}
PRBool operator!=(const iterator_self_type aOther) const
{
- NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+ NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
return mCurrent != aOther.mCurrent;
}
PRBool operator==(const iterator_self_type aOther)
{
- NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+ NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
return mCurrent == aOther.mCurrent;
}
PRBool operator!=(const iterator_self_type aOther)
{
- NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
+ NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
return mCurrent != aOther.mCurrent;
}
private:
link_type *mCurrent;
#ifdef DEBUG
link_type *mListLink; // the list's link, i.e., the end
#endif
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -948,30 +948,38 @@ BuildTextRunsScanner::FindBoundaries(nsI
#define NUM_LINES_TO_BUILD_TEXT_RUNS 200
/**
* General routine for building text runs. This is hairy because of the need
* to build text runs that span content nodes.
*
* @param aForFrameLine the line containing aForFrame; if null, we'll figure
* out the line (slowly)
- * @param aBlockFrame the block containing aForFrame; if null, we'll figure
- * out the block (slowly)
+ * @param aLineContainer the line container containing aForFrame; if null,
+ * we'll walk the ancestors to find it. It's required to be non-null when
+ * aForFrameLine is non-null.
*/
static void
BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame,
- nsIFrame* aLineContainer, const nsLineList::iterator* aForFrameLine)
-{
- NS_ASSERTION(aForFrame || (aForFrameLine && aLineContainer),
- "One of aForFrame or aForFrameLine+aLineContainer must be set!");
+ nsIFrame* aLineContainer,
+ const nsLineList::iterator* aForFrameLine)
+{
+ NS_ASSERTION(aForFrame || aLineContainer,
+ "One of aForFrame or aLineContainer must be set!");
+ NS_ASSERTION(!aForFrameLine || aLineContainer,
+ "line but no line container");
- if (!aLineContainer || !aForFrameLine) {
+ if (!aLineContainer) {
aLineContainer = FindLineContainer(aForFrame);
} else {
- NS_ASSERTION(!aForFrame || aLineContainer == FindLineContainer(aForFrame), "Wrong line container hint");
+ NS_ASSERTION(!aForFrame ||
+ (aLineContainer == FindLineContainer(aForFrame) ||
+ (aLineContainer->GetType() == nsGkAtoms::letterFrame &&
+ aLineContainer->GetStyleDisplay()->IsFloating())),
+ "Wrong line container hint");
}
nsPresContext* presContext = aLineContainer->PresContext();
BuildTextRunsScanner scanner(presContext, aContext, aLineContainer);
nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aLineContainer);
if (!block) {
@@ -5364,17 +5372,17 @@ void nsTextFrame::MarkIntrinsicWidthsDir
// temporarily override the "current line ending" settings.
void
nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
nsIFrame::InlineMinWidthData *aData)
{
PRUint32 flowEndInTextRun;
gfxContext* ctx = aRenderingContext->ThebesContext();
gfxSkipCharsIterator iter =
- EnsureTextRun(ctx, nsnull, aData->line, &flowEndInTextRun);
+ EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
if (!mTextRun)
return;
// Pass null for the line container. This will disable tab spacing, but that's
// OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = mContent->GetText();
PropertyProvider provider(mTextRun, textStyle, frag, this,
@@ -5466,33 +5474,42 @@ nsTextFrame::AddInlineMinWidth(nsIRender
gfxTextRun* lastTextRun = nsnull;
// nsContinuingTextFrame does nothing for AddInlineMinWidth; all text frames
// in the flow are handled right here.
for (f = this; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
// f->mTextRun could be null if we haven't set up textruns yet for f.
// Except in OOM situations, lastTextRun will only be null for the first
// text frame.
if (f == this || f->mTextRun != lastTextRun) {
+ nsIFrame* lc;
+ if (aData->lineContainer &&
+ aData->lineContainer != (lc = FindLineContainer(f))) {
+ NS_ASSERTION(f != this, "wrong InlineMinWidthData container"
+ " for first continuation");
+ aData->line = nsnull;
+ aData->lineContainer = lc;
+ }
+
// This will process all the text frames that share the same textrun as f.
f->AddInlineMinWidthForFlow(aRenderingContext, aData);
lastTextRun = f->mTextRun;
}
}
}
// XXX this doesn't handle characters shaped by line endings. We need to
// temporarily override the "current line ending" settings.
void
nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
nsIFrame::InlinePrefWidthData *aData)
{
PRUint32 flowEndInTextRun;
gfxContext* ctx = aRenderingContext->ThebesContext();
gfxSkipCharsIterator iter =
- EnsureTextRun(ctx, nsnull, aData->line, &flowEndInTextRun);
+ EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
if (!mTextRun)
return;
// Pass null for the line container. This will disable tab spacing, but that's
// OK since we can't really handle tabs for intrinsic sizing anyway.
const nsStyleText* textStyle = GetStyleText();
const nsTextFragment* frag = mContent->GetText();
@@ -5581,16 +5598,25 @@ nsTextFrame::AddInlinePrefWidth(nsIRende
gfxTextRun* lastTextRun = nsnull;
// nsContinuingTextFrame does nothing for AddInlineMinWidth; all text frames
// in the flow are handled right here.
for (f = this; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
// f->mTextRun could be null if we haven't set up textruns yet for f.
// Except in OOM situations, lastTextRun will only be null for the first
// text frame.
if (f == this || f->mTextRun != lastTextRun) {
+ nsIFrame* lc;
+ if (aData->lineContainer &&
+ aData->lineContainer != (lc = FindLineContainer(f))) {
+ NS_ASSERTION(f != this, "wrong InlinePrefWidthData container"
+ " for first continuation");
+ aData->line = nsnull;
+ aData->lineContainer = lc;
+ }
+
// This will process all the text frames that share the same textrun as f.
f->AddInlinePrefWidthForFlow(aRenderingContext, aData);
lastTextRun = f->mTextRun;
}
}
}
/* virtual */ nsSize