зеркало из https://github.com/mozilla/gecko-dev.git
Various pagination related bug fixes; pass in reflow command to FindTextRuns
This commit is contained in:
Родитель
f6fcd6698d
Коммит
a4bf798d9b
|
@ -181,8 +181,12 @@ protected:
|
|||
|
||||
PRBool IsPseudoFrame() const;
|
||||
|
||||
nsresult InitialReflow(nsCSSBlockReflowState& aState);
|
||||
|
||||
nsresult FrameAppendedReflow(nsCSSBlockReflowState& aState);
|
||||
|
||||
nsresult CreateNewFrames(nsIPresContext* aPresContext);
|
||||
|
||||
nsresult FindTextRuns(nsCSSBlockReflowState& aState);
|
||||
|
||||
nsresult ChildIncrementalReflow(nsCSSBlockReflowState& aState);
|
||||
|
@ -220,7 +224,7 @@ protected:
|
|||
|
||||
PRBool PullFrame(nsCSSBlockReflowState& aState,
|
||||
LineData* aToLine,
|
||||
LineData* aFromLine,
|
||||
LineData** aFromList,
|
||||
PRBool aUpdateGeometricParent,
|
||||
nsInlineReflowStatus& aResult);
|
||||
|
||||
|
@ -338,12 +342,12 @@ LineData::~LineData()
|
|||
}
|
||||
|
||||
static void
|
||||
ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
|
||||
ListFloaters(FILE* out, nsVoidArray* aFloaters)
|
||||
{
|
||||
PRInt32 i, n = aFloaters->Count();
|
||||
for (i = 0; i < n; i++) {
|
||||
nsIFrame* frame = (nsIFrame*) aFloaters->ElementAt(i);
|
||||
frame->List(out, aIndent);
|
||||
frame->ListTag(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,7 +365,7 @@ LineData::List(FILE* out, PRInt32 aIndent) const
|
|||
{
|
||||
PRInt32 i;
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
fprintf(out, "%p: count=%d state=%x {%d,%d,%d,%d} <\n",
|
||||
fprintf(out, "line %p: count=%d state=%x {%d,%d,%d,%d} <\n",
|
||||
this, mChildCount, GetState(),
|
||||
mBounds.x, mBounds.y, mBounds.width, mBounds.height);
|
||||
|
||||
|
@ -375,9 +379,8 @@ LineData::List(FILE* out, PRInt32 aIndent) const
|
|||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
|
||||
if (nsnull != mFloaters) {
|
||||
fputs("> bcl-floaters=<\n", out);
|
||||
ListFloaters(out, aIndent + 1, mFloaters);
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
fputs("> bcl-floaters=<", out);
|
||||
ListFloaters(out, mFloaters);
|
||||
}
|
||||
fputs(">\n", out);
|
||||
}
|
||||
|
@ -846,8 +849,7 @@ nsCSSBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
|
|||
PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
|
||||
aContinuingFrame = cf;
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("nsCSSBlockFrame::CreateContinuingFrame: prev-in-flow=%p newFrame=%p",
|
||||
this, cf));
|
||||
("nsCSSBlockFrame::CreateContinuingFrame: newFrame=%p", cf));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -907,8 +909,8 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||
|
||||
// Dump run-in floaters
|
||||
if (nsnull != mRunInFloaters) {
|
||||
fputs(" run-in-floaters=<\n", out);
|
||||
ListFloaters(out, aIndent + 1, mRunInFloaters);
|
||||
fputs(" run-in-floaters=<", out);
|
||||
ListFloaters(out, mRunInFloaters);
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
fputs(">", out);
|
||||
}
|
||||
|
@ -934,6 +936,8 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||
if (nsnull != mTextRuns) {
|
||||
fputs(" text-runs=<\n", out);
|
||||
ListTextRuns(out, aIndent + 1, mTextRuns);
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
fputs(">", out);
|
||||
}
|
||||
fputs("\n", out);
|
||||
|
||||
|
@ -1111,10 +1115,6 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
|
|||
// that needs generating.
|
||||
if (eReflowReason_Initial == aReflowState.reason) {
|
||||
NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
|
||||
nsresult rv = ProcessInitialReflow(aPresContext);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
|
||||
|
@ -1131,7 +1131,7 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
|
|||
if (eReflowReason_Initial == state.reason) {
|
||||
DrainOverflowLines();
|
||||
state.GetAvailableSpace();
|
||||
rv = FrameAppendedReflow(state);
|
||||
rv = InitialReflow(state);
|
||||
mState &= ~NS_FRAME_FIRST_REFLOW;
|
||||
}
|
||||
else if (eReflowReason_Incremental == state.reason) {
|
||||
|
@ -1183,7 +1183,12 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
|
|||
mLastContentIsComplete = line->GetLastContentIsComplete();
|
||||
}
|
||||
if (state.mBlockIsPseudo) {
|
||||
PropagateContentOffsets();
|
||||
// Tell our parent to update it's offsets because our offsets have
|
||||
// changed.
|
||||
nsContainerFrame* parent = (nsContainerFrame*) mGeometricParent;
|
||||
parent->PropagateContentOffsets(this, mFirstContentOffset,
|
||||
mLastContentOffset,
|
||||
mLastContentIsComplete);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1359,6 +1364,33 @@ IsBlock(PRUint8 aDisplay)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSBlockFrame::InitialReflow(nsCSSBlockReflowState& aState)
|
||||
{
|
||||
// Create synthetic content (XXX a hack)
|
||||
nsresult rv = ProcessInitialReflow(aState.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Create new frames
|
||||
if (nsnull == mNextInFlow) {
|
||||
rv = CreateNewFrames(aState.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate text-run information
|
||||
rv = FindTextRuns(aState);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Reflow everything
|
||||
return ResizeReflow(aState);
|
||||
}
|
||||
|
||||
// XXX this is not incremental; yuck. it's because of
|
||||
// DrainOverflowLines; we don't know how to reflow the overflow lines
|
||||
// and incrementally handle the new lines....time for dirty bits!
|
||||
|
@ -1366,40 +1398,57 @@ IsBlock(PRUint8 aDisplay)
|
|||
nsresult
|
||||
nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
|
||||
{
|
||||
// Determine the starting kidContentIndex and the childPrevInFlow if
|
||||
// the last child is not yet complete.
|
||||
PRInt32 kidContentIndex = 0;
|
||||
nsIFrame* childPrevInFlow = nsnull;
|
||||
nsIFrame* lastFrame = nsnull;
|
||||
LineData* lastLine = nsnull;
|
||||
if ((nsnull == mLines) && (nsnull != mPrevInFlow)) {
|
||||
nsCSSBlockFrame* prev = (nsCSSBlockFrame*)mPrevInFlow;
|
||||
lastLine = LastLine(prev->mLines);
|
||||
if (nsnull != lastLine) {
|
||||
lastFrame = lastLine->LastChild();
|
||||
lastFrame->GetContentIndex(kidContentIndex);
|
||||
if (lastLine->GetLastContentIsComplete()) {
|
||||
kidContentIndex++;
|
||||
}
|
||||
else {
|
||||
childPrevInFlow = lastFrame;
|
||||
}
|
||||
nsresult rv = CreateNewFrames(aState.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Generate text-run information
|
||||
rv = FindTextRuns(aState);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX temporary: Reflow everything
|
||||
return ResizeReflow(aState);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSBlockFrame::CreateNewFrames(nsIPresContext* aPresContext)
|
||||
{
|
||||
NS_ASSERTION((nsnull == mOverflowLines) && (nsnull == mNextInFlow),
|
||||
"bad call to CreateNewFrames");
|
||||
|
||||
// Get our last line and then get its last child. Use that
|
||||
// information to determine our kidContentIndex.
|
||||
LineData* lastLine = LastLine(mLines);
|
||||
nsIFrame* lastFrame;
|
||||
PRInt32 kidContentIndex;
|
||||
if (nsnull != lastLine) {
|
||||
lastFrame = lastLine->LastChild();
|
||||
lastFrame->GetContentIndex(kidContentIndex);
|
||||
if (lastLine->GetLastContentIsComplete()) {
|
||||
kidContentIndex++;
|
||||
}
|
||||
lastLine = nsnull;
|
||||
lastFrame = nsnull;
|
||||
else {
|
||||
#ifdef NS_DEBUG
|
||||
// Because we always create continuations as we find them (XXX
|
||||
// sigh) instead of when we need them, we can assert that if the
|
||||
// last child is not complete then it already has a continuation.
|
||||
nsIFrame* kidNextInFlow;
|
||||
lastFrame->GetNextInFlow(kidNextInFlow);
|
||||
NS_ASSERTION(nsnull != kidNextInFlow, "whoops");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lastLine = LastLine(mLines);
|
||||
if (nsnull != lastLine) {
|
||||
lastFrame = lastLine->LastChild();
|
||||
lastFrame->GetContentIndex(kidContentIndex);
|
||||
if (lastLine->GetLastContentIsComplete()) {
|
||||
kidContentIndex++;
|
||||
}
|
||||
else {
|
||||
childPrevInFlow = lastFrame;
|
||||
}
|
||||
}
|
||||
// We can't have an empty line list and have a prev-in-flow. If we
|
||||
// have a prev-in-flow then we are its continuation which means it
|
||||
// must have pushed some lines into its overflow list; therefore
|
||||
// we must have some lines.
|
||||
NS_ASSERTION(nsnull == mPrevInFlow, "prev-in-flow without overflow lines");
|
||||
lastFrame = nsnull;
|
||||
kidContentIndex = 0;
|
||||
}
|
||||
|
||||
// Make sure that new inlines go onto the end of the lastLine when
|
||||
|
@ -1415,6 +1464,9 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
|
|||
nsresult rv;
|
||||
PRInt32 lastContentIndex;
|
||||
lastContentIndex = mContent->ChildCount();
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsCSSBlockFrame::CreateNewFrames: kidContentIndex=%d lastContentIndex=%d",
|
||||
kidContentIndex, lastContentIndex));
|
||||
for (; kidContentIndex < lastContentIndex; kidContentIndex++) {
|
||||
nsIContent* kid;
|
||||
kid = mContent->ChildAt(kidContentIndex);
|
||||
|
@ -1424,8 +1476,7 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
|
|||
|
||||
// Create frame for our new child and add it to the sibling list
|
||||
nsIFrame* frame;
|
||||
rv = nsHTMLBase::CreateFrame(aState.mPresContext, this, kid,
|
||||
childPrevInFlow, frame);
|
||||
rv = nsHTMLBase::CreateFrame(aPresContext, this, kid, nsnull, frame);
|
||||
NS_RELEASE(kid);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
|
@ -1434,7 +1485,9 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
|
|||
lastFrame->SetNextSibling(frame);
|
||||
}
|
||||
lastFrame = frame;
|
||||
childPrevInFlow = nsnull;
|
||||
//XXX childPrevInFlow = nsnull;
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
|
||||
("nsCSSBlockFrame::CreateNewFrames: new-frame=%p", frame));
|
||||
|
||||
// See if the child is a block or non-block
|
||||
const nsStyleDisplay* kidDisplay;
|
||||
|
@ -1499,15 +1552,9 @@ nsCSSBlockFrame::FrameAppendedReflow(nsCSSBlockReflowState& aState)
|
|||
lastLine->SetLastContentIsComplete();
|
||||
}
|
||||
|
||||
// Generate text-run information
|
||||
rv = FindTextRuns(aState);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX temporary; use dirty bits instead so we can skip over all of
|
||||
// the lines that weren't changed.
|
||||
return ResizeReflow(aState);
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsCSSBlockFrame::CreateNewFrames"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1528,7 +1575,8 @@ nsCSSBlockFrame::FindTextRuns(nsCSSBlockReflowState& aState)
|
|||
nsIInlineReflow* inlineReflow;
|
||||
if (NS_OK == frame->QueryInterface(kIInlineReflowIID,
|
||||
(void**)&inlineReflow)) {
|
||||
nsresult rv = inlineReflow->FindTextRuns(aState.mLineLayout);
|
||||
nsresult rv = inlineReflow->FindTextRuns(aState.mLineLayout,
|
||||
aState.reflowCommand);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1768,13 +1816,9 @@ nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
|
|||
|
||||
// Pull frames from the next line until we can't
|
||||
while (nsnull != aLine->mNext) {
|
||||
LineData* line = aLine->mNext;
|
||||
keepGoing = PullFrame(aState, aLine, line, PR_FALSE, aReflowResult);
|
||||
if (0 == line->mChildCount) {
|
||||
aLine->mNext = line->mNext;
|
||||
line->mNext = aState.mFreeList; // put on freelist
|
||||
aState.mFreeList = line;
|
||||
}
|
||||
LineData** linep = &aLine->mNext;
|
||||
keepGoing = PullFrame(aState, aLine, &aLine->mNext,
|
||||
PR_FALSE, aReflowResult);
|
||||
if (!keepGoing) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -1789,12 +1833,8 @@ nsCSSBlockFrame::ReflowLine(nsCSSBlockReflowState& aState,
|
|||
aState.mNextInFlow = nextInFlow;
|
||||
continue;
|
||||
}
|
||||
keepGoing = PullFrame(aState, aLine, line, PR_TRUE, aReflowResult);
|
||||
if (0 == line->mChildCount) {
|
||||
nextInFlow->mLines = line->mNext;
|
||||
line->mNext = aState.mFreeList; // put on freelist
|
||||
aState.mFreeList = line;
|
||||
}
|
||||
keepGoing = PullFrame(aState, aLine, &nextInFlow->mLines,
|
||||
PR_TRUE, aReflowResult);
|
||||
if (!keepGoing) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -2012,19 +2052,23 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
|
|||
}
|
||||
if (nsnull != nextInFlow) {
|
||||
// We made a next-in-flow for the block child frame. Create a
|
||||
// line to map that block childs next-in-flow and then push that
|
||||
// line to our next-in-flow.
|
||||
// line to map the block childs next-in-flow.
|
||||
LineData* line = new LineData(nextInFlow, 1);
|
||||
if (nsnull == line) {
|
||||
aReflowResult = nsInlineReflowStatus(NS_ERROR_OUT_OF_MEMORY);
|
||||
return PR_FALSE;
|
||||
}
|
||||
line->SetLastContentIsComplete();
|
||||
line->SetIsBlock();
|
||||
line->mNext = aLine->mNext;
|
||||
aLine->mNext = line;
|
||||
}
|
||||
|
||||
// Push the new line to the next-in-flow
|
||||
aState.mPrevLine = aLine;
|
||||
// Advance mPrevLine because we are keeping aLine (since some of
|
||||
// the child block frame fit). Then push any remaining lines to
|
||||
// our next-in-flow
|
||||
aState.mPrevLine = aLine;
|
||||
if (nsnull != aLine->mNext) {
|
||||
PushLines(aState);
|
||||
}
|
||||
aReflowResult = NS_INLINE_LINE_BREAK_AFTER(reflowStatus);
|
||||
|
@ -2182,27 +2226,34 @@ nsCSSBlockFrame::SplitLine(nsCSSBlockReflowState& aState,
|
|||
PRBool
|
||||
nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
|
||||
LineData* aLine,
|
||||
LineData* aFromLine,
|
||||
LineData** aFromList,
|
||||
PRBool aUpdateGeometricParent,
|
||||
nsInlineReflowStatus& aReflowResult)
|
||||
{
|
||||
if (0 == aFromLine->mChildCount) {
|
||||
NS_ASSERTION(nsnull == aFromLine->mFirstChild, "bad line");
|
||||
LineData* fromLine = *aFromList;
|
||||
NS_ASSERTION(nsnull != fromLine, "bad line to pull from");
|
||||
if (0 == fromLine->mChildCount) {
|
||||
// Discard empty lines immediately. Empty lines can happen here
|
||||
// because of DeleteChildsNextInFlow not being able to delete
|
||||
// lines.
|
||||
*aFromList = fromLine->mNext;
|
||||
fromLine->mNext = aState.mFreeList;
|
||||
aState.mFreeList = fromLine;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// If our line is not empty and the child in aFromLine is a block
|
||||
// then we cannot pull up the frame into this line.
|
||||
if ((0 != aLine->mChildCount) && aFromLine->IsBlock()) {
|
||||
if ((0 != aLine->mChildCount) && fromLine->IsBlock()) {
|
||||
aReflowResult = NS_INLINE_LINE_BREAK_BEFORE(0);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Take frame from aFromLine
|
||||
nsIFrame* frame = aFromLine->mFirstChild;
|
||||
// Take frame from fromLine
|
||||
nsIFrame* frame = fromLine->mFirstChild;
|
||||
if (0 == aLine->mChildCount++) {
|
||||
aLine->mFirstChild = frame;
|
||||
aLine->SetIsBlock(aFromLine->IsBlock());
|
||||
aLine->SetIsBlock(fromLine->IsBlock());
|
||||
#ifdef NS_DEBUG
|
||||
const nsStyleDisplay* display;
|
||||
frame->GetStyleData(eStyleStruct_Display,
|
||||
|
@ -2211,11 +2262,15 @@ nsCSSBlockFrame::PullFrame(nsCSSBlockReflowState& aState,
|
|||
NS_ASSERTION(isBlock == aLine->IsBlock(), "bad line isBlock");
|
||||
#endif
|
||||
}
|
||||
if (0 != --aFromLine->mChildCount) {
|
||||
frame->GetNextSibling(aFromLine->mFirstChild);
|
||||
if (0 != --fromLine->mChildCount) {
|
||||
frame->GetNextSibling(fromLine->mFirstChild);
|
||||
}
|
||||
else {
|
||||
aFromLine->mFirstChild = nsnull;
|
||||
// Free up the fromLine now that it's empty
|
||||
*aFromList = fromLine->mNext;
|
||||
fromLine->mFirstChild = nsnull;
|
||||
fromLine->mNext = aState.mFreeList;
|
||||
aState.mFreeList = fromLine;
|
||||
}
|
||||
|
||||
// Change geometric parents
|
||||
|
@ -2346,28 +2401,6 @@ nsCSSBlockFrame::PushLines(nsCSSBlockReflowState& aState)
|
|||
LineData* lastLine = aState.mPrevLine;
|
||||
LineData* nextLine = lastLine->mNext;
|
||||
|
||||
#if XXX
|
||||
// Strip out empty lines
|
||||
LineData** lp = &nextLine;
|
||||
for (;;) {
|
||||
LineData* line = *lp;
|
||||
if (nsnull == line) {
|
||||
break;
|
||||
}
|
||||
if (0 == line->mChildCount) {
|
||||
NS_ASSERTION(nsnull == line->mFirstChild, "bad line");
|
||||
*lp = line->mNext;
|
||||
line->mNext = aState.mFreeList;
|
||||
aState.mFreeList = line;
|
||||
continue;
|
||||
}
|
||||
lp = &line->mNext;
|
||||
}
|
||||
if (nsnull == nextLine) {
|
||||
// Nothing to push: they were all empty
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
lastLine->mNext = nsnull;
|
||||
mOverflowLines = nextLine;
|
||||
|
||||
|
@ -2428,6 +2461,9 @@ nsCSSBlockFrame::DrainOverflowLines()
|
|||
lastLine->mNext = mLines;
|
||||
mLines = line;
|
||||
}
|
||||
|
||||
// Update our first-content-index now that we have a new first child
|
||||
mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2442,11 +2478,17 @@ nsCSSBlockFrame::DrainOverflowLines()
|
|||
LineData* lastLine = LastLine(mLines);
|
||||
if (nsnull == lastLine) {
|
||||
mLines = mOverflowLines;
|
||||
// Update our first-content-index now that we have a new first child
|
||||
mLines->mFirstChild->GetContentIndex(mFirstContentOffset);
|
||||
}
|
||||
else {
|
||||
lastLine->mNext = mOverflowLines;
|
||||
nsIFrame* lastFrame = lastLine->LastChild();
|
||||
lastFrame->SetNextSibling(mOverflowLines->mFirstChild);
|
||||
|
||||
// Update our last-content-index now that we have a new last child
|
||||
lastLine = LastLine(mOverflowLines);
|
||||
lastLine->LastChild()->GetContentIndex(mLastContentOffset);
|
||||
}
|
||||
mOverflowLines = nsnull;
|
||||
}
|
||||
|
@ -2459,6 +2501,7 @@ nsCSSBlockFrame::DrainOverflowLines()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX a copy of nsHTMLContainerFrame's
|
||||
NS_IMETHODIMP
|
||||
nsCSSBlockFrame::ContentAppended(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
|
|
|
@ -29,11 +29,6 @@
|
|||
// test: <b>...<br></b> : make sure that it works in pullup case and
|
||||
// non-pullup case
|
||||
|
||||
// XXX As coded today, the reflow-status is mapped into
|
||||
// complete/not-complete before returning. If we want to support other
|
||||
// kinds of breaks we need to return the complete breaking status
|
||||
// outward properly.
|
||||
|
||||
// content appended INCREMENTAL reflow
|
||||
// content inserted INCREMENTAL reflow
|
||||
// content deleted INCREMENTAL reflow
|
||||
|
@ -159,6 +154,8 @@ nsCSSInlineFrame::CreateContinuingFrame(nsIPresContext* aCX,
|
|||
}
|
||||
PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
|
||||
aContinuingFrame = cf;
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("nsCSSInlineFrame::CreateContinuingFrame: newFrame=%p", cf));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -169,7 +166,8 @@ nsCSSInlineFrame::DeleteNextInFlowsFor(nsIFrame* aChild)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
|
||||
nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout,
|
||||
nsIReflowCommand* aReflowCommand)
|
||||
{
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsCSSInlineFrame::FindTextRuns [%d,%d,%c]",
|
||||
|
@ -179,11 +177,31 @@ nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
|
|||
PRInt32 n;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Create any new frames first
|
||||
if (mNextInFlow == nsnull) {
|
||||
rv = CreateNewFrames(aLineLayout);
|
||||
if (NS_OK != rv) {
|
||||
goto done;
|
||||
// Gather up children from the overflow lists
|
||||
DrainOverflowLists();
|
||||
|
||||
// Create new frames if necessary
|
||||
if (NS_FRAME_FIRST_REFLOW & mState) {
|
||||
if ((nsnull == mPrevInFlow) && (nsnull == mNextInFlow) &&
|
||||
(0 == mChildCount)) {
|
||||
rv = CreateNewFrames(aLineLayout.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nsnull != aReflowCommand) {
|
||||
nsIFrame* target;
|
||||
aReflowCommand->GetTarget(target);
|
||||
if (this == target) {
|
||||
nsIReflowCommand::ReflowType type;
|
||||
aReflowCommand->GetType(type);
|
||||
if (nsIReflowCommand::FrameAppended == type) {
|
||||
rv = CreateNewFrames(aLineLayout.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +212,7 @@ nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
|
|||
nsIInlineReflow* inlineReflow;
|
||||
if (NS_OK == frame->QueryInterface(kIInlineReflowIID,
|
||||
(void**)&inlineReflow)) {
|
||||
rv = inlineReflow->FindTextRuns(aLineLayout);
|
||||
rv = inlineReflow->FindTextRuns(aLineLayout, aReflowCommand);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -244,8 +262,8 @@ nsCSSInlineFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
|
|||
PRBool(nsnull != aMetrics.maxElementSize));
|
||||
nsresult rv = NS_OK;
|
||||
if (eReflowReason_Initial == state.reason) {
|
||||
MoveOverflowToChildList();
|
||||
rv = FrameAppendedReflow(state);
|
||||
DrainOverflowLists();
|
||||
rv = InitialReflow(state);
|
||||
mState &= ~NS_FRAME_FIRST_REFLOW;
|
||||
}
|
||||
else if (eReflowReason_Incremental == state.reason) {
|
||||
|
@ -275,7 +293,7 @@ nsCSSInlineFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
|
|||
}
|
||||
}
|
||||
else if (eReflowReason_Resize == state.reason) {
|
||||
MoveOverflowToChildList();
|
||||
DrainOverflowLists();
|
||||
rv = ResizeReflow(state);
|
||||
}
|
||||
ComputeFinalSize(state, aMetrics);
|
||||
|
@ -364,7 +382,30 @@ nsCSSInlineFrame::ComputeFinalSize(nsCSSInlineReflowState& aState,
|
|||
}
|
||||
}
|
||||
|
||||
// XXX this isn't very incremental; we can do better SOMEDAY
|
||||
nsInlineReflowStatus
|
||||
nsCSSInlineFrame::InitialReflow(nsCSSInlineReflowState& aState)
|
||||
{
|
||||
NS_PRECONDITION(nsnull == mNextInFlow, "bad frame-appended-reflow");
|
||||
NS_PRECONDITION(mLastContentIsComplete == PR_TRUE, "bad state");
|
||||
|
||||
// Create any frames that need creating; note that they should have been
|
||||
if ((nsnull == mPrevInFlow) && (nsnull == mNextInFlow) &&
|
||||
(0 == mChildCount)) {
|
||||
nsresult rv = CreateNewFrames(aState.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsInlineReflowStatus rs = NS_FRAME_COMPLETE;
|
||||
if (0 != mChildCount) {
|
||||
if (!ReflowMapped(aState, rs)) {
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
nsInlineReflowStatus
|
||||
nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
|
||||
{
|
||||
|
@ -372,9 +413,9 @@ nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
|
|||
NS_PRECONDITION(mLastContentIsComplete == PR_TRUE, "bad state");
|
||||
|
||||
// Create any frames that need creating
|
||||
nsresult rv = CreateNewFrames(aState.mInlineLayout.mLineLayout);
|
||||
nsresult rv = CreateNewFrames(aState.mPresContext);
|
||||
if (NS_OK != rv) {
|
||||
return nsInlineReflowStatus(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsInlineReflowStatus rs = NS_FRAME_COMPLETE;
|
||||
|
@ -387,8 +428,12 @@ nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCSSInlineFrame::CreateNewFrames(nsCSSLineLayout& aLineLayout)
|
||||
nsCSSInlineFrame::CreateNewFrames(nsIPresContext* aPresContext)
|
||||
{
|
||||
// reason: initial: (a) null nif, pif: create frames
|
||||
// (b) pullup: don't create frames
|
||||
// reason: incremental: (a) append targetted at us => create frames
|
||||
|
||||
// Get the childPrevInFlow for our eventual first child if we are a
|
||||
// continuation and we have no children and the last child in our
|
||||
// prev-in-flow is incomplete. While we are at it, we also compute
|
||||
|
@ -427,8 +472,8 @@ nsCSSInlineFrame::CreateNewFrames(nsCSSLineLayout& aLineLayout)
|
|||
|
||||
// Create child
|
||||
nsIFrame* child;
|
||||
rv = nsHTMLBase::CreateFrame(aLineLayout.mPresContext, this, kid,
|
||||
childPrevInFlow, child);
|
||||
rv = nsHTMLBase::CreateFrame(aPresContext, this, kid, childPrevInFlow,
|
||||
child);
|
||||
NS_RELEASE(kid);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
|
@ -775,12 +820,16 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState,
|
|||
keepGoing = PR_TRUE;
|
||||
|
||||
done:;
|
||||
// XXX Why bother? Assuming our offsets are correct then our
|
||||
// next-in-flow will pick up where we left off.
|
||||
#if XXX
|
||||
nextInFlow = (nsCSSInlineFrame*) mNextInFlow;
|
||||
if ((nsnull != nextInFlow) && (nsnull == nextInFlow->mFirstChild)) {
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus)) {
|
||||
AdjustOffsetOfEmptyNextInFlows();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsCSSInlineFrame::PullUpChildren: childCount=%d rs=%x",
|
||||
|
@ -813,15 +862,11 @@ nsCSSInlineFrame::PullOneChild(nsCSSInlineFrame* aNextInFlow,
|
|||
kidFrame, aNextInFlow->mChildCount - 1));
|
||||
|
||||
// Take the frame away from the next-in-flow. Update it's first
|
||||
// content offset and propagate upward the offset if the
|
||||
// next-in-flow is a pseudo-frame.
|
||||
// content offset.
|
||||
kidFrame->GetNextSibling(aNextInFlow->mFirstChild);
|
||||
aNextInFlow->mChildCount--;
|
||||
if (nsnull != aNextInFlow->mFirstChild) {
|
||||
aNextInFlow->SetFirstContentOffset(aNextInFlow->mFirstChild);
|
||||
if (aNextInFlow->IsPseudoFrame()) {
|
||||
aNextInFlow->PropagateContentOffsets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -864,8 +909,11 @@ nsCSSInlineFrame::MaybeCreateNextInFlow(nsCSSInlineReflowState& aState,
|
|||
|
||||
void
|
||||
nsCSSInlineFrame::PushKids(nsCSSInlineReflowState& aState,
|
||||
nsIFrame* aPrevChild, nsIFrame* aPushedChild)
|
||||
nsIFrame* aPrevChild,
|
||||
nsIFrame* aPushedChild)
|
||||
{
|
||||
NS_ASSERTION(nsnull == mOverflowList, "bad overflow list");
|
||||
|
||||
// Count how many children are being pushed
|
||||
PRInt32 pushCount = mChildCount - aState.mInlineLayout.mFrameNum;
|
||||
|
||||
|
@ -874,11 +922,99 @@ nsCSSInlineFrame::PushKids(nsCSSInlineReflowState& aState,
|
|||
if (0 != pushCount) {
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_PUSH_PULL,
|
||||
("nsCSSInlineFrame::PushKids: pushing %d children", pushCount));
|
||||
PushChildren(aPushedChild, aPrevChild, PR_TRUE/* XXX ignored! */);
|
||||
// Break sibling list
|
||||
aPrevChild->SetNextSibling(nsnull);
|
||||
mChildCount -= pushCount;
|
||||
|
||||
// Place overflow frames on our overflow list; our next-in-flow
|
||||
// will pick them up when it is reflowed
|
||||
mOverflowList = aPushedChild;
|
||||
}
|
||||
#ifdef NS_DEBUG
|
||||
PRInt32 len = LengthOf(mFirstChild);
|
||||
NS_ASSERTION(len == mChildCount, "child count is wrong");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSInlineFrame::DrainOverflowLists()
|
||||
{
|
||||
// Our prev-in-flows overflow list goes before my children and must
|
||||
// be re-parented.
|
||||
if (nsnull != mPrevInFlow) {
|
||||
nsCSSInlineFrame* prevInFlow = (nsCSSInlineFrame*) mPrevInFlow;
|
||||
if (nsnull != prevInFlow->mOverflowList) {
|
||||
nsIFrame* frame = prevInFlow->mOverflowList;
|
||||
nsIFrame* lastFrame = nsnull;
|
||||
PRInt32 count = 0;
|
||||
while (nsnull != frame) {
|
||||
// Reparent the frame
|
||||
frame->SetGeometricParent(this);
|
||||
nsIFrame* contentParent;
|
||||
frame->GetContentParent(contentParent);
|
||||
if (prevInFlow == contentParent) {
|
||||
frame->SetContentParent(this);
|
||||
}
|
||||
|
||||
// Advance through the list
|
||||
count++;
|
||||
lastFrame = frame;
|
||||
frame->GetNextSibling(frame);
|
||||
}
|
||||
|
||||
// Join the two frame lists together and update our child count
|
||||
#if XXX
|
||||
if (nsnull == mFirstChild) {
|
||||
// We are a continuation of our prev-in-flow; we assume that
|
||||
// the last child was complete.
|
||||
mLastContentIsComplete = PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
nsIFrame* newFirstChild = prevInFlow->mOverflowList;
|
||||
newFirstChild->GetContentIndex(mFirstContentOffset);
|
||||
lastFrame->SetNextSibling(mFirstChild);
|
||||
mFirstChild = newFirstChild;
|
||||
prevInFlow->mOverflowList = nsnull;
|
||||
mChildCount += count;
|
||||
}
|
||||
}
|
||||
|
||||
// Our overflow list goes to the end of our child list
|
||||
if (nsnull != mOverflowList) {
|
||||
// Append the overflow list to the end of our child list
|
||||
nsIFrame* lastFrame;
|
||||
LastChild(lastFrame);
|
||||
if (nsnull == lastFrame) {
|
||||
mFirstChild = mOverflowList;
|
||||
mFirstChild->GetContentIndex(mFirstContentOffset);
|
||||
}
|
||||
else {
|
||||
lastFrame->SetNextSibling(mOverflowList);
|
||||
}
|
||||
|
||||
// Count how many frames are on the overflow list and then update
|
||||
// our count
|
||||
nsIFrame* frame = mOverflowList;
|
||||
PRInt32 count = 0;
|
||||
while (nsnull != frame) {
|
||||
count++;
|
||||
frame->GetNextSibling(frame);
|
||||
}
|
||||
mChildCount += count;
|
||||
mOverflowList = nsnull;
|
||||
#if XXX
|
||||
// We get here when we pushed some children to a potential
|
||||
// next-in-flow and then our parent decided to reflow us instead
|
||||
// of continuing us.
|
||||
NS_ASSERTION(nsnull == mNextInFlow, "huh?");
|
||||
mLastContentIsComplete = PR_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
// XXX What do we set mLastContentIsComplete to?
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRInt32 len = LengthOf(mFirstChild);
|
||||
NS_ASSERTION(len == mChildCount, "child count is wrong");
|
||||
#endif
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче