зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5ebef36b9a
Коммит
3a3ac38479
|
@ -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, ¤t);
|
||||
CollectFloats(overflowLines->front()->mFirstChild,
|
||||
this, &head, ¤t);
|
||||
|
||||
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, ¤t);
|
||||
CollectFloats(overflowLines->front()->mFirstChild,
|
||||
this, &head, ¤t);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче