mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
7c80834b1e
commit
99f4849c65
@ -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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (floatContinuations.NotEmpty()) {
|
||||
// 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();
|
||||
aState.mFloatContinuations.AppendFrames(nsnull, floatContinuations);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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,6 +6679,16 @@ void nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
|
||||
aFrame->GetType() == nsGkAtoms::placeholderFrame ?
|
||||
nsLayoutUtils::GetFloatFromPlaceholder(aFrame) : nsnull;
|
||||
if (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 {
|
||||
// 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
|
||||
@ -6678,6 +6703,7 @@ void nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
|
||||
}
|
||||
aList.AppendFrame(nsnull, outOfFlowFrame);
|
||||
}
|
||||
}
|
||||
|
||||
CollectFloats(aFrame->GetFirstChild(nsnull),
|
||||
aList, aFromOverflow, PR_TRUE);
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user