зеркало из https://github.com/mozilla/pjs.git
Track which frames were float continuations that need to be pulled to the next block rather than figuring it out again when it's time to pull them. (This allows first-in-flows to be float continuations.) (Bug 563584, patch 12) r=roc
This commit is contained in:
Родитель
26d3ed4c0d
Коммит
4e69b44c43
|
@ -1014,8 +1014,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
NS_MergeReflowStatusInto(&state.mReflowStatus, fcStatus);
|
||||
|
||||
// Put continued floats at the end of mFloats
|
||||
if (state.mFloatContinuations.NotEmpty())
|
||||
if (state.mFloatContinuations.NotEmpty()) {
|
||||
mFloats.AppendFrames(nsnull, state.mFloatContinuations);
|
||||
}
|
||||
|
||||
// If we end in a BR with clear and affected floats continue,
|
||||
// we need to continue, too.
|
||||
|
@ -1768,7 +1769,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
// reflow it or if its previous margin is dirty
|
||||
PRBool needToRecoverState = PR_FALSE;
|
||||
// Float continuations were reflowed in ReflowFloatContinuations
|
||||
PRBool reflowedFloat = mFloats.NotEmpty() && mFloats.FirstChild()->GetPrevInFlow();
|
||||
PRBool reflowedFloat = mFloats.NotEmpty() &&
|
||||
(mFloats.FirstChild()->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION);
|
||||
PRBool lastLineMovedUp = PR_FALSE;
|
||||
// We save up information about BR-clearance here
|
||||
PRUint8 inlineFloatBreakType = aState.mFloatBreakType;
|
||||
|
@ -3894,8 +3896,16 @@ nsBlockFrame::SplitFloat(nsBlockReflowState& aState,
|
|||
nsIFrame* aFloat,
|
||||
nsReflowStatus aFloatStatus)
|
||||
{
|
||||
nsIFrame* nextInFlow = nsnull;
|
||||
if (!aFloat->GetNextInFlow()) {
|
||||
nsIFrame* nextInFlow = aFloat->GetNextInFlow();
|
||||
if (nextInFlow) {
|
||||
nsContainerFrame *oldParent =
|
||||
static_cast<nsContainerFrame*>(nextInFlow->GetParent());
|
||||
nsresult rv = oldParent->StealFrame(aState.mPresContext, nextInFlow);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame failed");
|
||||
if (oldParent != this) {
|
||||
ReparentFrame(nextInFlow, oldParent, this);
|
||||
}
|
||||
} else {
|
||||
nsresult rv = aState.mPresContext->PresShell()->FrameConstructor()->
|
||||
CreateContinuingFrame(aState.mPresContext, aFloat, this, &nextInFlow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -3916,10 +3926,7 @@ nsBlockFrame::SplitFloat(nsBlockReflowState& aState,
|
|||
aState.mFloatManager->SetSplitRightFloatAcrossBreak();
|
||||
}
|
||||
|
||||
if (nextInFlow) {
|
||||
// Next in flow was created above.
|
||||
aState.AppendFloatContinuation(nextInFlow);
|
||||
}
|
||||
aState.AppendFloatContinuation(nextInFlow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3936,8 +3943,12 @@ GetLastFloat(nsLineBox* aLine)
|
|||
static PRBool
|
||||
CheckPlaceholderInLine(nsIFrame* aBlock, nsLineBox* aLine, nsFloatCache* aFC)
|
||||
{
|
||||
if (!aFC || aFC->mFloat->GetPrevInFlow())
|
||||
if (!aFC)
|
||||
return PR_TRUE;
|
||||
NS_ASSERTION(!aFC->mFloat->GetPrevContinuation(),
|
||||
"float in a line should never be a continuation");
|
||||
NS_ASSERTION(!(aFC->mFloat->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION),
|
||||
"float in a line should never be a pushed float");
|
||||
nsIFrame* ph = aBlock->PresContext()->FrameManager()->
|
||||
GetPlaceholderFrameFor(aFC->mFloat->GetFirstInFlow());
|
||||
for (nsIFrame* f = ph; f; f = f->GetParent()) {
|
||||
|
@ -4435,53 +4446,56 @@ nsBlockFrame::DrainOverflowLines(nsBlockReflowState& aState)
|
|||
}
|
||||
|
||||
// This function assumes our prev-in-flow has completed reflow and its
|
||||
// mFloats contains at most two frames that belong to the same flow chain,
|
||||
// the second one being a last-in-flow continuation intended for this block.
|
||||
// mFloats may contain frames at the end of its float list, marked with
|
||||
// NS_FRAME_IS_FLOAT_CONTINUATION, that should be pulled to this block.
|
||||
void
|
||||
nsBlockFrame::DrainFloatContinuations(nsBlockReflowState& aState)
|
||||
{
|
||||
// Cache any continuations of our own floats that we're still holding onto
|
||||
// so they're out of the way. This should only happen if we're re-Reflow'd
|
||||
// before our next-in-flow gets a chance to pull these continuations.
|
||||
nsFrameList floatContinuations;
|
||||
nsPresContext* presContext = PresContext();
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
nsIFrame* nif = f->GetNextInFlow();
|
||||
if (!nif) continue;
|
||||
if (nif->GetParent() == this) {
|
||||
NS_ASSERTION(!nif->GetNextInFlow(),
|
||||
"Unexpected next-in-flow for float continuation");
|
||||
StealFrame(presContext, nif);
|
||||
floatContinuations.AppendFrame(nsnull, nif);
|
||||
// However, if it's a "continuation" that's not actually a continuation,
|
||||
// put it back on the floats list.
|
||||
// FIXME: This is not compatible with doing float breaking in dynamic
|
||||
// situations, since in those situations we could have current
|
||||
// continuations at the end of our float list that were actually
|
||||
// continuations from a previous frame to this one. (However, it's
|
||||
// not clear to me that we really need this code in the first place;
|
||||
// the best solution might just be to remove it.)
|
||||
nsIFrame *f = mFloats.LastChild();
|
||||
if (f && (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION)) {
|
||||
do {
|
||||
f = f->GetPrevSibling();
|
||||
} while (f && (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION));
|
||||
aState.SetupFloatContinuationList();
|
||||
// RemoveFramesAfter(nsnull) removes the whole list
|
||||
nsFrameList floatContinuations = mFloats.RemoveFramesAfter(f);
|
||||
while (floatContinuations.NotEmpty()) {
|
||||
nsIFrame *f = floatContinuations.RemoveFirstChild();
|
||||
if (f->GetPrevContinuation()) {
|
||||
aState.mFloatContinuations.AppendFrame(nsnull, f);
|
||||
} else {
|
||||
f->RemoveStateBits(NS_FRAME_IS_FLOAT_CONTINUATION);
|
||||
mFloats.AppendFrame(nsnull, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (floatContinuations.NotEmpty()) {
|
||||
aState.SetupFloatContinuationList();
|
||||
aState.mFloatContinuations.AppendFrames(nsnull, floatContinuations);
|
||||
}
|
||||
|
||||
// Walk our prev-in-flow's floats and prepend their continuations to our
|
||||
// floats list. This pulls any continuations we need to take from our
|
||||
// prev-in-flow and makes sure our continuations of its floats are in the
|
||||
// proper order.
|
||||
// Take any continuations we need to take from our prev-in-flow.
|
||||
nsBlockFrame* prevBlock = static_cast<nsBlockFrame*>(GetPrevInFlow());
|
||||
if (!prevBlock)
|
||||
return;
|
||||
for (nsIFrame* pf = prevBlock->mFloats.FirstChild(); pf; pf = pf->GetNextSibling()) {
|
||||
nsIFrame* nif = pf->GetNextInFlow();
|
||||
if (!nif)
|
||||
continue;
|
||||
nsContainerFrame* nifParent = static_cast<nsContainerFrame*>(nif->GetParent());
|
||||
nifParent->StealFrame(presContext, nif);
|
||||
if (nif->GetParent() != this) {
|
||||
NS_ASSERTION(!nif->GetNextInFlow(),
|
||||
"Unexpected next-in-flow for float continuation");
|
||||
ReparentFrame(nif, nifParent, this);
|
||||
}
|
||||
floatContinuations.AppendFrame(this, nif);
|
||||
}
|
||||
if (floatContinuations.NotEmpty())
|
||||
f = prevBlock->mFloats.LastChild();
|
||||
if (f && (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION)) {
|
||||
do {
|
||||
ReparentFrame(f, prevBlock, this);
|
||||
f = f->GetPrevSibling();
|
||||
} while (f && (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION));
|
||||
|
||||
// RemoveFramesAfter(nsnull) removes the whole list
|
||||
nsFrameList floatContinuations = prevBlock->mFloats.RemoveFramesAfter(f);
|
||||
mFloats.InsertFrames(nsnull, nsnull, floatContinuations);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f ; f = f->GetNextSibling()) {
|
||||
|
@ -5719,7 +5733,8 @@ nsBlockFrame::ReflowFloatContinuations(nsBlockReflowState& aState,
|
|||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f && f->GetPrevInFlow();
|
||||
for (nsIFrame* f = mFloats.FirstChild();
|
||||
f && (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION);
|
||||
f = f->GetNextSibling()) {
|
||||
if (NS_SUBTREE_DIRTY(f) || aState.mReflowState.ShouldReflowAllKids()) {
|
||||
// Cache old bounds
|
||||
|
@ -6044,7 +6059,7 @@ nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
if (GetPrevInFlow()) {
|
||||
DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
if (f->GetPrevInFlow())
|
||||
if (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION)
|
||||
BuildDisplayListForChild(aBuilder, f, aDirtyRect, aLists);
|
||||
}
|
||||
}
|
||||
|
@ -6664,19 +6679,30 @@ void nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
|
|||
aFrame->GetType() == nsGkAtoms::placeholderFrame ?
|
||||
nsLayoutUtils::GetFloatFromPlaceholder(aFrame) : nsnull;
|
||||
if (outOfFlowFrame) {
|
||||
// Make sure that its parent is us. Otherwise we don't want
|
||||
// to mess around with it because it belongs to someone
|
||||
// else. I think this could happen if the overflow lines
|
||||
// contain a block descendant which owns its own floats.
|
||||
NS_ASSERTION(outOfFlowFrame->GetParent() == this,
|
||||
"Out of flow frame doesn't have the expected parent");
|
||||
if (aFromOverflow) {
|
||||
nsAutoOOFFrameList oofs(this);
|
||||
oofs.mList.RemoveFrame(outOfFlowFrame);
|
||||
if (outOfFlowFrame->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION) {
|
||||
if (outOfFlowFrame->GetParent() == this) {
|
||||
nsFrameList* list = GetPropTableFrames(PresContext(),
|
||||
FloatContinuationProperty());
|
||||
if (!list || !list->RemoveFrameIfPresent(outOfFlowFrame)) {
|
||||
mFloats.RemoveFrame(outOfFlowFrame);
|
||||
}
|
||||
aList.AppendFrame(nsnull, outOfFlowFrame);
|
||||
}
|
||||
} else {
|
||||
mFloats.RemoveFrame(outOfFlowFrame);
|
||||
// Make sure that its parent is us. Otherwise we don't want
|
||||
// to mess around with it because it belongs to someone
|
||||
// else. I think this could happen if the overflow lines
|
||||
// contain a block descendant which owns its own floats.
|
||||
NS_ASSERTION(outOfFlowFrame->GetParent() == this,
|
||||
"Out of flow frame doesn't have the expected parent");
|
||||
if (aFromOverflow) {
|
||||
nsAutoOOFFrameList oofs(this);
|
||||
oofs.mList.RemoveFrame(outOfFlowFrame);
|
||||
} else {
|
||||
mFloats.RemoveFrame(outOfFlowFrame);
|
||||
}
|
||||
aList.AppendFrame(nsnull, outOfFlowFrame);
|
||||
}
|
||||
aList.AppendFrame(nsnull, outOfFlowFrame);
|
||||
}
|
||||
|
||||
CollectFloats(aFrame->GetFirstChild(nsnull),
|
||||
|
@ -6722,7 +6748,7 @@ nsBlockFrame::CheckFloats(nsBlockReflowState& aState)
|
|||
PRBool equal = PR_TRUE;
|
||||
PRUint32 i = 0;
|
||||
for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
if (f->GetPrevInFlow())
|
||||
if (f->GetStateBits() & NS_FRAME_IS_FLOAT_CONTINUATION)
|
||||
continue;
|
||||
storedFloats.AppendElement(f);
|
||||
if (i < lineFloats.Length() && lineFloats.ElementAt(i) != f) {
|
||||
|
|
|
@ -97,7 +97,17 @@ class nsIntervalSet;
|
|||
* nsBlockReflowState. This list contains continuations for
|
||||
* floats whose prev-in-flow is in the block's regular float
|
||||
* list. The list is always empty/nonexistent after the
|
||||
* block has been reflowed.
|
||||
* block has been reflowed. (However, after it has been
|
||||
* reflowed and before the continuations are moved to the
|
||||
* next block, they are temporarily at the end of the
|
||||
* block's float list. FIXME: This temporary storage
|
||||
* situation is not compatible with doing float breaking in
|
||||
* dynamic cases, since we can't distinguish unflushed
|
||||
* temporary storage (floats being transferred from the
|
||||
* frame) in a case where we need a second reflow from
|
||||
* frames previously transferred to the frame; fixing this
|
||||
* would require an additional frame list for this temporary
|
||||
* storage.)
|
||||
* -- In all these frame lists, if there are two frames for
|
||||
* the same content appearing in the list, then the frames
|
||||
* appear with the prev-in-flow before the next-in-flow.
|
||||
|
|
|
@ -233,6 +233,7 @@ public:
|
|||
// Use this method to append to mFloatContinuations.
|
||||
void AppendFloatContinuation(nsIFrame* aFloatCont) {
|
||||
SetupFloatContinuationList();
|
||||
aFloatCont->AddStateBits(NS_FRAME_IS_FLOAT_CONTINUATION);
|
||||
mFloatContinuations.AppendFrame(mBlock, aFloatCont);
|
||||
}
|
||||
|
||||
|
|
|
@ -256,6 +256,12 @@ typedef PRUint64 nsFrameState;
|
|||
// Bits 20-31 of the frame state are reserved for implementations.
|
||||
#define NS_FRAME_IMPL_RESERVED nsFrameState(0xFFF00000)
|
||||
|
||||
// This bit is set on floats whose parent does not contain their
|
||||
// placeholder. This can happen for two reasons: (1) the float was
|
||||
// split, and this piece is the continuation, or (2) the entire float
|
||||
// didn't fit on the page.
|
||||
#define NS_FRAME_IS_FLOAT_CONTINUATION NS_FRAME_STATE_BIT(32)
|
||||
|
||||
// The lower 20 bits and upper 32 bits of the frame state are reserved
|
||||
// by this API.
|
||||
#define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED
|
||||
|
|
Загрузка…
Ссылка в новой задаче