Bug 257216. Fix sundry block issues for columns. In particular, remove overflowing floats from the space manager before we compute the space manager's XMost and YMost to include in the block size. r+sr=dbaron

This commit is contained in:
roc+%cs.cmu.edu 2004-09-13 13:35:46 +00:00
Родитель 5ebef36b9a
Коммит 3a3ac38479
16 изменённых файлов: 286 добавлений и 116 удалений

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsCSSPseudoElements.h"
#include "nsIView.h"
#include "nsIScrollableView.h"
#include "nsPlaceholderFrame.h"
/**
* A namespace class for static layout utilities.
@ -174,6 +175,23 @@ nsLayoutUtils::GetPageFrame(nsIFrame* aFrame)
return nsnull;
}
nsIFrame*
nsLayoutUtils::GetFloatFromPlaceholder(nsIFrame* aFrame) {
if (nsLayoutAtoms::placeholderFrame != aFrame->GetType()) {
return nsnull;
}
nsIFrame *outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*, aFrame)->GetOutOfFlowFrame();
// This is a hack.
if (outOfFlowFrame &&
!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
return outOfFlowFrame;
}
return nsnull;
}
// static
PRBool
nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent,

Просмотреть файл

@ -199,7 +199,12 @@ public:
}
return pseudoContext != nsnull;
}
/**
* If this frame is a placeholder for a float, then return the float,
* otherwise return nsnull.
*/
static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPossiblePlaceholder);
};
#endif // nsLayoutUtils_h__

Просмотреть файл

@ -199,7 +199,12 @@ public:
}
return pseudoContext != nsnull;
}
/**
* If this frame is a placeholder for a float, then return the float,
* otherwise return nsnull.
*/
static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPossiblePlaceholder);
};
#endif // nsLayoutUtils_h__

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsCSSPseudoElements.h"
#include "nsIView.h"
#include "nsIScrollableView.h"
#include "nsPlaceholderFrame.h"
/**
* A namespace class for static layout utilities.
@ -174,6 +175,23 @@ nsLayoutUtils::GetPageFrame(nsIFrame* aFrame)
return nsnull;
}
nsIFrame*
nsLayoutUtils::GetFloatFromPlaceholder(nsIFrame* aFrame) {
if (nsLayoutAtoms::placeholderFrame != aFrame->GetType()) {
return nsnull;
}
nsIFrame *outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*, aFrame)->GetOutOfFlowFrame();
// This is a hack.
if (outOfFlowFrame &&
!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
return outOfFlowFrame;
}
return nsnull;
}
// static
PRBool
nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent,

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIPresShell.h"
#include "nsMemory.h"
#include "nsHTMLReflowState.h"
#include "nsHashSets.h"
#ifdef DEBUG
#include "nsIFrameDebug.h"
#endif
@ -105,7 +106,6 @@ MOZ_DECL_CTOR_COUNTER(nsSpaceManager)
nsSpaceManager::nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame)
: mFrame(aFrame),
mXMost(0),
mLowestTop(NSCOORD_MIN),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell)
{
@ -199,7 +199,11 @@ void nsSpaceManager::Shutdown()
PRBool
nsSpaceManager::XMost(nscoord& aXMost) const
{
aXMost = mXMost;
nscoord xMost = 0;
for (FrameInfo* fi = mFrameInfoMap; fi; fi = fi->mNext) {
xMost = PR_MAX(xMost, fi->mRect.XMost());
}
aXMost = xMost;
return !mBandList.IsEmpty();
}
@ -813,10 +817,6 @@ nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace)
nsRect rect(aUnavailableSpace.x + mX, aUnavailableSpace.y + mY,
aUnavailableSpace.width, aUnavailableSpace.height);
nscoord xmost = rect.XMost();
if (xmost > mXMost)
mXMost = xmost;
if (rect.y > mLowestTop)
mLowestTop = rect.y;
@ -843,6 +843,30 @@ nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace)
return NS_OK;
}
nsresult
nsSpaceManager::RemoveTrailingRegions(nsIFrame* aFrameList) {
nsVoidHashSet frameSet;
frameSet.Init(1);
for (nsIFrame* f = aFrameList; f; f = f->GetNextSibling()) {
frameSet.Put(f);
}
// Pop frame regions off as long as they're in the set of frames to
// remove
while (mFrameInfoMap && frameSet.Contains(mFrameInfoMap->mFrame)) {
RemoveRegion(mFrameInfoMap->mFrame);
}
#ifdef DEBUG
for (FrameInfo* frameInfo = mFrameInfoMap; frameInfo;
frameInfo = frameInfo->mNext) {
NS_ASSERTION(!frameSet.Contains(frameInfo->mFrame),
"Frame region deletion was requested but we couldn't delete it");
}
#endif
}
nsresult
nsSpaceManager::RemoveRegion(nsIFrame* aFrame)
{
@ -995,7 +1019,6 @@ nsSpaceManager::PushState()
state->mX = mX;
state->mY = mY;
state->mXMost = mXMost;
state->mLowestTop = mLowestTop;
if (mFrameInfoMap) {
@ -1042,7 +1065,6 @@ nsSpaceManager::PopState()
mX = mSavedStates->mX;
mY = mSavedStates->mY;
mXMost = mSavedStates->mXMost;
mLowestTop = mSavedStates->mLowestTop;
// Now that we've restored our state, pop the topmost

Просмотреть файл

@ -251,13 +251,28 @@ public:
nsresult AddRectRegion(nsIFrame* aFrame,
const nsRect& aUnavailableSpace);
/**
* Remove the regions associated with this floating frame and its
* next-sibling list. Some of the frames may never have been added;
* we just skip those. This is not fully general; it only works as
* long as the N frames to be removed are the last N frames to have
* been added; if there's a frame in the middle of them that should
* not be removed, YOU LOSE.
*
* This can only be done at the end of the life of this space manager. The only
* methods it is safe to call after this are XMost() and YMost().
*/
nsresult RemoveTrailingRegions(nsIFrame* aFrameList);
protected:
/**
* Remove the region associated with aFrane.
*
* doesn't work in the general case!
*
* Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
protected: /* doesn't work in the general case */
nsresult RemoveRegion(nsIFrame* aFrame);
public:
@ -335,7 +350,6 @@ protected:
struct SpaceManagerState {
nscoord mX, mY;
nsIFrame *mLastFrame;
nscoord mXMost;
nscoord mLowestTop;
SpaceManagerState *mNext;
};
@ -408,7 +422,6 @@ protected:
nsIFrame* const mFrame; // frame associated with the space manager
nscoord mX, mY; // translation from local to global coordinate space
BandList mBandList; // header/sentinel for circular linked list of band rects
nscoord mXMost;
nscoord mLowestTop; // the lowest *top*
FrameInfo* mFrameInfoMap;
nsIntervalSet mFloatDamage;

Просмотреть файл

@ -78,6 +78,7 @@
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
#include "nsLayoutUtils.h"
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
@ -658,6 +659,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
FinishAndStoreOverflow(&aMetrics);
#ifdef DEBUG
if (gNoisy) {
gNoiseIndent--;
}
#endif
return NS_OK;
}
}
@ -921,8 +928,8 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// XXX_perf get rid of this! This is one of the things that makes
// incremental reflow O(N^2).
BuildFloatList();
BuildFloatList(state);
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
FinishAndStoreOverflow(&aMetrics);
@ -2066,6 +2073,20 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
return rv;
}
if (!keepGoing) {
#ifdef DEBUG
if (gNoisyReflow) {
gNoiseIndent--;
nsRect lca(line->GetCombinedArea());
IndentBy(stdout, gNoiseIndent);
printf("line=%p mY=%d newBounds={%d,%d,%d,%d} newCombinedArea={%d,%d,%d,%d} deltaY=%d mPrevBottomMargin=%d childCount=%d\n",
NS_STATIC_CAST(void*, line.get()), aState.mY,
line->mBounds.x, line->mBounds.y,
line->mBounds.width, line->mBounds.height,
lca.x, lca.y, lca.width, lca.height,
deltaY, aState.mPrevBottomMargin.get(),
line->GetChildCount());
}
#endif
if (0 == line->GetChildCount()) {
DeleteLine(aState, line, line_end);
}
@ -6479,38 +6500,30 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
// This is used to scan overflow frames for any float placeholders,
// and add their floats to the list represented by aHead and aTail. We
// only search the inline descendants.
static void CollectOverflowFloats(nsIFrame* aFrame, nsIFrame* aBlockParent,
nsIFrame** aHead, nsIFrame** aTail) {
static void CollectFloats(nsIFrame* aFrame, nsIFrame* aBlockParent,
nsIFrame** aHead, nsIFrame** aTail) {
while (aFrame) {
// Don't descend into block children
if (!aFrame->GetStyleDisplay()->IsBlockLevel()) {
if (nsLayoutAtoms::placeholderFrame == aFrame->GetType()) {
nsIFrame *outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*, aFrame)->GetOutOfFlowFrame();
nsIFrame *outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
if (outOfFlowFrame) {
// Make sure that its parent is the block we care
// about. 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.
if (outOfFlowFrame &&
!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
NS_ASSERTION(outOfFlowFrame->GetParent() == aBlockParent,
"Out of flow frame doesn't have the expected parent");
// It's not an absolute or fixed positioned frame, so it must
// be a float!
// XXX This is a lame-o way of detecting a float, but it's the
// only way apparently
if (!*aHead) {
*aHead = *aTail = outOfFlowFrame;
} else {
(*aTail)->SetNextSibling(outOfFlowFrame);
*aTail = outOfFlowFrame;
}
NS_ASSERTION(outOfFlowFrame->GetParent() == aBlockParent,
"Out of flow frame doesn't have the expected parent");
if (!*aHead) {
*aHead = *aTail = outOfFlowFrame;
} else {
(*aTail)->SetNextSibling(outOfFlowFrame);
*aTail = outOfFlowFrame;
}
}
CollectOverflowFloats(aFrame->GetFirstChild(nsnull), aBlockParent,
aHead, aTail);
CollectFloats(aFrame->GetFirstChild(nsnull), aBlockParent,
aHead, aTail);
}
aFrame = aFrame->GetNextSibling();
@ -6519,7 +6532,7 @@ static void CollectOverflowFloats(nsIFrame* aFrame, nsIFrame* aBlockParent,
//XXX get rid of this -- its slow
void
nsBlockFrame::BuildFloatList()
nsBlockFrame::BuildFloatList(nsBlockReflowState& aState)
{
// Accumulate float list into mFloats.
// Use the float cache to speed up searching the lines for floats.
@ -6558,11 +6571,24 @@ nsBlockFrame::BuildFloatList()
head = nsnull;
current = nsnull;
CollectOverflowFloats(overflowLines->front()->mFirstChild,
this, &head, &current);
CollectFloats(overflowLines->front()->mFirstChild,
this, &head, &current);
if (current) {
current->SetNextSibling(nsnull);
// Floats that were pushed should be removed from our space
// manager. Otherwise the space manager's YMost or XMost might
// be larger than necessary, causing this block to get an
// incorrect desired height (or width). Some of these floats
// may not actually have been added to the space manager because
// they weren't reflowed before being pushed; that's OK,
// RemoveRegions will ignore them. It is safe to do this here
// because we know from here on the space manager will only be
// used for its XMost and YMost, not to place new floats and
// lines.
aState.mSpaceManager->RemoveTrailingRegions(head);
nsFrameList* frameList = new nsFrameList(head);
if (frameList) {
SetOverflowOutOfFlows(frameList);

Просмотреть файл

@ -518,7 +518,7 @@ protected:
nsLineBox* aLine,
nscoord aDeltaY);
void BuildFloatList();
void BuildFloatList(nsBlockReflowState& aState);
//----------------------------------------
// List handling kludge

Просмотреть файл

@ -818,7 +818,7 @@ nsBlockReflowState::CanPlaceFloat(const nsRect& aFloatRect,
}
void
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool* aIsLeftFloat,
nsReflowStatus& aReflowStatus)
{
@ -858,6 +858,9 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
GetAvailableSpace();
}
NS_ASSERTION(floatFrame->GetParent() == mBlock,
"Float frame has wrong parent");
// Reflow the float
mBlock->ReflowFloat(*this, placeholder, aFloatCache, aReflowStatus);

Просмотреть файл

@ -65,6 +65,7 @@
#include "nsHTMLAtoms.h"
#include "nsTextFragment.h"
#include "nsBidiUtils.h"
#include "nsLayoutUtils.h"
#ifdef DEBUG
#undef NOISY_HORIZONTAL_ALIGN
@ -1003,25 +1004,22 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
if (frameType) {
if (nsLayoutAtoms::placeholderFrame == frameType) {
pfd->SetFlag(PFD_ISPLACEHOLDERFRAME, PR_TRUE);
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)aFrame)->GetOutOfFlowFrame();
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
if (outOfFlowFrame) {
// Make sure it's floated and not absolutely positioned
const nsStyleDisplay* display = outOfFlowFrame->GetStyleDisplay();
if (!display->IsAbsolutelyPositioned()) {
if (eReflowReason_Incremental == reason) {
InitFloat((nsPlaceholderFrame*)aFrame, aReflowStatus);
}
else {
AddFloat((nsPlaceholderFrame*)aFrame, aReflowStatus);
}
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
// An incomplete reflow status means we should split the
// float if the height is constrained (bug 145305). We
// never split floating first letters.
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
aReflowStatus = NS_FRAME_COMPLETE;
}
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
if (eReflowReason_Incremental == reason) {
InitFloat(placeholder, aReflowStatus);
}
else {
AddFloat(placeholder, aReflowStatus);
}
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
// An incomplete reflow status means we should split the
// float if the height is constrained (bug 145305). We
// never split floating first letters.
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
aReflowStatus = NS_FRAME_COMPLETE;
}
}
}

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIPresShell.h"
#include "nsMemory.h"
#include "nsHTMLReflowState.h"
#include "nsHashSets.h"
#ifdef DEBUG
#include "nsIFrameDebug.h"
#endif
@ -105,7 +106,6 @@ MOZ_DECL_CTOR_COUNTER(nsSpaceManager)
nsSpaceManager::nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame)
: mFrame(aFrame),
mXMost(0),
mLowestTop(NSCOORD_MIN),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell)
{
@ -199,7 +199,11 @@ void nsSpaceManager::Shutdown()
PRBool
nsSpaceManager::XMost(nscoord& aXMost) const
{
aXMost = mXMost;
nscoord xMost = 0;
for (FrameInfo* fi = mFrameInfoMap; fi; fi = fi->mNext) {
xMost = PR_MAX(xMost, fi->mRect.XMost());
}
aXMost = xMost;
return !mBandList.IsEmpty();
}
@ -813,10 +817,6 @@ nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace)
nsRect rect(aUnavailableSpace.x + mX, aUnavailableSpace.y + mY,
aUnavailableSpace.width, aUnavailableSpace.height);
nscoord xmost = rect.XMost();
if (xmost > mXMost)
mXMost = xmost;
if (rect.y > mLowestTop)
mLowestTop = rect.y;
@ -843,6 +843,30 @@ nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace)
return NS_OK;
}
nsresult
nsSpaceManager::RemoveTrailingRegions(nsIFrame* aFrameList) {
nsVoidHashSet frameSet;
frameSet.Init(1);
for (nsIFrame* f = aFrameList; f; f = f->GetNextSibling()) {
frameSet.Put(f);
}
// Pop frame regions off as long as they're in the set of frames to
// remove
while (mFrameInfoMap && frameSet.Contains(mFrameInfoMap->mFrame)) {
RemoveRegion(mFrameInfoMap->mFrame);
}
#ifdef DEBUG
for (FrameInfo* frameInfo = mFrameInfoMap; frameInfo;
frameInfo = frameInfo->mNext) {
NS_ASSERTION(!frameSet.Contains(frameInfo->mFrame),
"Frame region deletion was requested but we couldn't delete it");
}
#endif
}
nsresult
nsSpaceManager::RemoveRegion(nsIFrame* aFrame)
{
@ -995,7 +1019,6 @@ nsSpaceManager::PushState()
state->mX = mX;
state->mY = mY;
state->mXMost = mXMost;
state->mLowestTop = mLowestTop;
if (mFrameInfoMap) {
@ -1042,7 +1065,6 @@ nsSpaceManager::PopState()
mX = mSavedStates->mX;
mY = mSavedStates->mY;
mXMost = mSavedStates->mXMost;
mLowestTop = mSavedStates->mLowestTop;
// Now that we've restored our state, pop the topmost

Просмотреть файл

@ -251,13 +251,28 @@ public:
nsresult AddRectRegion(nsIFrame* aFrame,
const nsRect& aUnavailableSpace);
/**
* Remove the regions associated with this floating frame and its
* next-sibling list. Some of the frames may never have been added;
* we just skip those. This is not fully general; it only works as
* long as the N frames to be removed are the last N frames to have
* been added; if there's a frame in the middle of them that should
* not be removed, YOU LOSE.
*
* This can only be done at the end of the life of this space manager. The only
* methods it is safe to call after this are XMost() and YMost().
*/
nsresult RemoveTrailingRegions(nsIFrame* aFrameList);
protected:
/**
* Remove the region associated with aFrane.
*
* doesn't work in the general case!
*
* Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
protected: /* doesn't work in the general case */
nsresult RemoveRegion(nsIFrame* aFrame);
public:
@ -335,7 +350,6 @@ protected:
struct SpaceManagerState {
nscoord mX, mY;
nsIFrame *mLastFrame;
nscoord mXMost;
nscoord mLowestTop;
SpaceManagerState *mNext;
};
@ -408,7 +422,6 @@ protected:
nsIFrame* const mFrame; // frame associated with the space manager
nscoord mX, mY; // translation from local to global coordinate space
BandList mBandList; // header/sentinel for circular linked list of band rects
nscoord mXMost;
nscoord mLowestTop; // the lowest *top*
FrameInfo* mFrameInfoMap;
nsIntervalSet mFloatDamage;

Просмотреть файл

@ -78,6 +78,7 @@
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
#include "nsLayoutUtils.h"
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
@ -658,6 +659,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
FinishAndStoreOverflow(&aMetrics);
#ifdef DEBUG
if (gNoisy) {
gNoiseIndent--;
}
#endif
return NS_OK;
}
}
@ -921,8 +928,8 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// XXX_perf get rid of this! This is one of the things that makes
// incremental reflow O(N^2).
BuildFloatList();
BuildFloatList(state);
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
FinishAndStoreOverflow(&aMetrics);
@ -2066,6 +2073,20 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
return rv;
}
if (!keepGoing) {
#ifdef DEBUG
if (gNoisyReflow) {
gNoiseIndent--;
nsRect lca(line->GetCombinedArea());
IndentBy(stdout, gNoiseIndent);
printf("line=%p mY=%d newBounds={%d,%d,%d,%d} newCombinedArea={%d,%d,%d,%d} deltaY=%d mPrevBottomMargin=%d childCount=%d\n",
NS_STATIC_CAST(void*, line.get()), aState.mY,
line->mBounds.x, line->mBounds.y,
line->mBounds.width, line->mBounds.height,
lca.x, lca.y, lca.width, lca.height,
deltaY, aState.mPrevBottomMargin.get(),
line->GetChildCount());
}
#endif
if (0 == line->GetChildCount()) {
DeleteLine(aState, line, line_end);
}
@ -6479,38 +6500,30 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
// This is used to scan overflow frames for any float placeholders,
// and add their floats to the list represented by aHead and aTail. We
// only search the inline descendants.
static void CollectOverflowFloats(nsIFrame* aFrame, nsIFrame* aBlockParent,
nsIFrame** aHead, nsIFrame** aTail) {
static void CollectFloats(nsIFrame* aFrame, nsIFrame* aBlockParent,
nsIFrame** aHead, nsIFrame** aTail) {
while (aFrame) {
// Don't descend into block children
if (!aFrame->GetStyleDisplay()->IsBlockLevel()) {
if (nsLayoutAtoms::placeholderFrame == aFrame->GetType()) {
nsIFrame *outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*, aFrame)->GetOutOfFlowFrame();
nsIFrame *outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
if (outOfFlowFrame) {
// Make sure that its parent is the block we care
// about. 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.
if (outOfFlowFrame &&
!outOfFlowFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) {
NS_ASSERTION(outOfFlowFrame->GetParent() == aBlockParent,
"Out of flow frame doesn't have the expected parent");
// It's not an absolute or fixed positioned frame, so it must
// be a float!
// XXX This is a lame-o way of detecting a float, but it's the
// only way apparently
if (!*aHead) {
*aHead = *aTail = outOfFlowFrame;
} else {
(*aTail)->SetNextSibling(outOfFlowFrame);
*aTail = outOfFlowFrame;
}
NS_ASSERTION(outOfFlowFrame->GetParent() == aBlockParent,
"Out of flow frame doesn't have the expected parent");
if (!*aHead) {
*aHead = *aTail = outOfFlowFrame;
} else {
(*aTail)->SetNextSibling(outOfFlowFrame);
*aTail = outOfFlowFrame;
}
}
CollectOverflowFloats(aFrame->GetFirstChild(nsnull), aBlockParent,
aHead, aTail);
CollectFloats(aFrame->GetFirstChild(nsnull), aBlockParent,
aHead, aTail);
}
aFrame = aFrame->GetNextSibling();
@ -6519,7 +6532,7 @@ static void CollectOverflowFloats(nsIFrame* aFrame, nsIFrame* aBlockParent,
//XXX get rid of this -- its slow
void
nsBlockFrame::BuildFloatList()
nsBlockFrame::BuildFloatList(nsBlockReflowState& aState)
{
// Accumulate float list into mFloats.
// Use the float cache to speed up searching the lines for floats.
@ -6558,11 +6571,24 @@ nsBlockFrame::BuildFloatList()
head = nsnull;
current = nsnull;
CollectOverflowFloats(overflowLines->front()->mFirstChild,
this, &head, &current);
CollectFloats(overflowLines->front()->mFirstChild,
this, &head, &current);
if (current) {
current->SetNextSibling(nsnull);
// Floats that were pushed should be removed from our space
// manager. Otherwise the space manager's YMost or XMost might
// be larger than necessary, causing this block to get an
// incorrect desired height (or width). Some of these floats
// may not actually have been added to the space manager because
// they weren't reflowed before being pushed; that's OK,
// RemoveRegions will ignore them. It is safe to do this here
// because we know from here on the space manager will only be
// used for its XMost and YMost, not to place new floats and
// lines.
aState.mSpaceManager->RemoveTrailingRegions(head);
nsFrameList* frameList = new nsFrameList(head);
if (frameList) {
SetOverflowOutOfFlows(frameList);

Просмотреть файл

@ -518,7 +518,7 @@ protected:
nsLineBox* aLine,
nscoord aDeltaY);
void BuildFloatList();
void BuildFloatList(nsBlockReflowState& aState);
//----------------------------------------
// List handling kludge

Просмотреть файл

@ -818,7 +818,7 @@ nsBlockReflowState::CanPlaceFloat(const nsRect& aFloatRect,
}
void
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool* aIsLeftFloat,
nsReflowStatus& aReflowStatus)
{
@ -858,6 +858,9 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
GetAvailableSpace();
}
NS_ASSERTION(floatFrame->GetParent() == mBlock,
"Float frame has wrong parent");
// Reflow the float
mBlock->ReflowFloat(*this, placeholder, aFloatCache, aReflowStatus);

Просмотреть файл

@ -65,6 +65,7 @@
#include "nsHTMLAtoms.h"
#include "nsTextFragment.h"
#include "nsBidiUtils.h"
#include "nsLayoutUtils.h"
#ifdef DEBUG
#undef NOISY_HORIZONTAL_ALIGN
@ -1003,25 +1004,22 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
if (frameType) {
if (nsLayoutAtoms::placeholderFrame == frameType) {
pfd->SetFlag(PFD_ISPLACEHOLDERFRAME, PR_TRUE);
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)aFrame)->GetOutOfFlowFrame();
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
if (outOfFlowFrame) {
// Make sure it's floated and not absolutely positioned
const nsStyleDisplay* display = outOfFlowFrame->GetStyleDisplay();
if (!display->IsAbsolutelyPositioned()) {
if (eReflowReason_Incremental == reason) {
InitFloat((nsPlaceholderFrame*)aFrame, aReflowStatus);
}
else {
AddFloat((nsPlaceholderFrame*)aFrame, aReflowStatus);
}
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
// An incomplete reflow status means we should split the
// float if the height is constrained (bug 145305). We
// never split floating first letters.
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
aReflowStatus = NS_FRAME_COMPLETE;
}
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
if (eReflowReason_Incremental == reason) {
InitFloat(placeholder, aReflowStatus);
}
else {
AddFloat(placeholder, aReflowStatus);
}
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
// An incomplete reflow status means we should split the
// float if the height is constrained (bug 145305). We
// never split floating first letters.
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
aReflowStatus = NS_FRAME_COMPLETE;
}
}
}