Replace NS_BLOCK_WRAP_SIZE with making unconstrained-width reflow of frames with NS_BLOCK_SPACE_MGR consider the floats. This means we no longer use the overflow area for layout (other than the overflow property). Handle right floaters in unconstrained width reflow by just treating them as left floaters. b=172896 r+sr=roc

This commit is contained in:
dbaron%fas.harvard.edu 2002-12-19 00:12:08 +00:00
Родитель 1afcc02c0a
Коммит 69151bc05f
14 изменённых файлов: 170 добавлений и 278 удалений

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

@ -106,6 +106,7 @@ MOZ_DECL_CTOR_COUNTER(nsSpaceManager)
nsSpaceManager::nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame)
: mFrame(aFrame),
mXMost(0),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell)
{
MOZ_COUNT_CTOR(nsSpaceManager);
@ -195,6 +196,12 @@ void nsSpaceManager::Shutdown()
sCachedSpaceManagerCount = -1;
}
PRBool
nsSpaceManager::XMost(nscoord& aXMost) const
{
aXMost = mXMost;
return !mBandList.IsEmpty();
}
PRBool
nsSpaceManager::YMost(nscoord& aYMost) const
@ -806,6 +813,10 @@ 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;
// Create a frame info structure
frameInfo = CreateFrameInfo(aFrame, rect);
if (nsnull == frameInfo) {
@ -1026,6 +1037,7 @@ nsSpaceManager::PushState()
state->mX = mX;
state->mY = mY;
state->mXMost = mXMost;
if (mFrameInfoMap) {
state->mLastFrame = mFrameInfoMap->mFrame;
@ -1069,6 +1081,7 @@ nsSpaceManager::PopState()
mX = mSavedStates->mX;
mY = mSavedStates->mY;
mXMost = mSavedStates->mXMost;
// Now that we've restored our state, pop the topmost
// state and delete it.

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

@ -194,6 +194,14 @@ public:
*/
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
/**
* Returns the x-most rect in the space manager, or 0 if there are no
* rects.
*
* @return PR_TRUE if there are bands and PR_FALSE if there are no bands
*/
PRBool XMost(nscoord& aXMost) const;
/**
* Returns the y-most of the bottommost band or 0 if there are no bands.
*
@ -335,6 +343,7 @@ protected:
struct SpaceManagerState {
nscoord mX, mY;
nsIFrame *mLastFrame;
nscoord mXMost;
SpaceManagerState *mNext;
SpaceManagerState() : mX(0), mY(0), mLastFrame(nsnull), mNext(nsnull) {}
@ -409,6 +418,7 @@ 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;
FrameInfo* mFrameInfoMap;
nsIntervalSet mFloatDamage;

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

@ -1182,6 +1182,8 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
{
const nsHTMLReflowState* rs = &aReflowState;
if (NS_UNCONSTRAINEDSIZE == rs->mComputedWidth) {
// XXXldb Why isn't this always true for the cases where this
// function returns true?
return PR_TRUE;
}
const nsStylePosition* pos = rs->mStylePosition;
@ -1297,37 +1299,33 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
maxWidth = aMetrics.width;
}
else {
nscoord minWidth = aState.mKidXMost + borderPadding.right;
nscoord computedWidth = minWidth;
PRBool compact = PR_FALSE;
#if 0
if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) {
// If we are display: compact AND we have no lines or we have
// exactly one line and that line is not a block line AND that
// line doesn't end in a BR of any sort THEN we remain a compact
// frame.
if ((mLines.empty()) ||
((mLines.front() == mLines.back()) && !mLines.front()->IsBlock() &&
(NS_STYLE_CLEAR_NONE == mLines.front()->GetBreakType())
/*XXX && (computedWidth <= aState.mCompactMarginWidth) */
)) {
compact = PR_TRUE;
}
}
#endif
nscoord computedWidth;
// XXX Misleading comment:
// There are two options here. We either shrink wrap around our
// contents or we fluff out to the maximum block width. Note:
// We always shrink wrap when given an unconstrained width.
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) &&
!aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
!compact) {
!aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
// XXX Misleading comment:
// Set our width to the max width if we aren't already that
// wide. Note that the max-width has nothing to do with our
// contents (CSS2 section XXX)
// XXXldb In what cases do we reach this code?
computedWidth = borderPadding.left + aState.mContentArea.width +
borderPadding.right;
} else {
computedWidth = aState.mKidXMost;
if (NS_BLOCK_SPACE_MGR & mState) {
// Include the space manager's state to properly account for the
// extent of floated elements.
nscoord xmost;
if (aReflowState.mSpaceManager->XMost(xmost) &&
computedWidth < xmost)
computedWidth = xmost;
}
computedWidth += borderPadding.right;
}
// See if we should compute our max element size
@ -1337,6 +1335,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
maxWidth = aState.mMaxElementSize.width +
borderPadding.left + borderPadding.right;
if (computedWidth < maxWidth) {
// XXXldb It's *compute* max-element-size, not *change size
// based on* max-element-size...
computedWidth = maxWidth;
}
}
@ -1374,6 +1374,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
if (!parentIsShrinkWrapWidth) {
// XXX Is this only used on things that are already NS_BLOCK_SPACE_MGR
// and NS_BLOCK_MARGIN_ROOT?
nsHTMLReflowState reflowState(aReflowState);
reflowState.mComputedWidth = aMetrics.width - borderPadding.left -
@ -1393,15 +1395,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
}
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
PRBool parentIsShrinkWrapWidth = PR_FALSE;
if (aReflowState.parentReflowState) {
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
parentIsShrinkWrapWidth = PR_TRUE;
}
}
}
// Compute final height
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) {
if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
@ -1452,16 +1445,16 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
// XXX check for a fit
autoHeight += aState.mPrevBottomMargin.get();
}
autoHeight += borderPadding.bottom;
if (NS_BLOCK_SPACE_MGR & mState) {
// Include the space manager's state to properly account for the
// bottom margin of any floated elements; e.g., inside a table cell.
nscoord ymost;
aReflowState.mSpaceManager->YMost(ymost);
if (ymost > autoHeight)
if (aReflowState.mSpaceManager->YMost(ymost) &&
autoHeight < ymost)
autoHeight = ymost;
}
autoHeight += borderPadding.bottom;
// Apply min/max values
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) {
@ -1565,32 +1558,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
if (NS_BLOCK_WRAP_SIZE & mState) {
// When the area frame is supposed to wrap around all in-flow
// children, make sure it is big enough to include those that stick
// outside the box.
if (NS_FRAME_OUTSIDE_CHILDREN & mState) {
nscoord xMost = aMetrics.mOverflowArea.XMost();
if (xMost > aMetrics.width) {
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
printf(": changing desired width from %d to %d\n", aMetrics.width, xMost);
#endif
aMetrics.width = xMost;
}
nscoord yMost = aMetrics.mOverflowArea.YMost();
if (yMost > aMetrics.height) {
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
printf(": changing desired height from %d to %d\n", aMetrics.height, yMost);
#endif
aMetrics.height = yMost;
// adjust descent to absorb any excess difference
aMetrics.descent = aMetrics.height - aMetrics.ascent;
}
}
}
}
void
@ -2659,9 +2626,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
#if defined(DEBUG_waterson) || defined(DEBUG_dbaron)
// XXXwaterson if oldUnconstrainedWidth was set, why do we need
// to do the second reflow, below?
if (oldUnconstrainedWidth)
printf("*** oldUnconstrainedWidth was already set.\n"
"*** This code (%s:%d) could be optimized a lot!\n",
"*** This code (%s:%d) could be optimized a lot!\n"
"+++ possibly doing an unnecessary second-pass unconstrained "
"reflow\n",
__FILE__, __LINE__);
#endif
@ -2678,13 +2650,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
aState.mSpaceManager->PopState();
#ifdef DEBUG_waterson
// XXXwaterson if oldUnconstrainedWidth was set, why do we need
// to do the second reflow, below?
if (oldUnconstrainedWidth)
printf("+++ possibly doing an unnecessary second-pass unconstrained reflow\n");
#endif
// Update the line's maximum width
aLine->mMaximumWidth = aLine->mBounds.XMost();
#ifdef NOISY_MAXIMUM_WIDTH
@ -3707,7 +3672,6 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// Forget all of the floaters on the line
aLine->FreeFloaters(aState.mFloaterCacheFreeList);
aState.mFloaterCombinedArea.SetRect(0, 0, 0, 0);
aState.mRightFloaterCombinedArea.SetRect(0, 0, 0, 0);
// Setup initial coordinate system for reflowing the inline frames
// into. Apply a previous block frame's bottom margin first.
@ -4413,9 +4377,8 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
printf("PASS1 ");
}
ListTag(stdout);
printf(": line.floaters=%s band.floaterCount=%d\n",
printf(": band.floaterCount=%d\n",
//aLine->mFloaters.NotEmpty() ? "yes" : "no",
aState.mHaveRightFloaters ? "(have right floaters)" : "",
aState.mBand.GetFloaterCount());
}
#endif
@ -4488,42 +4451,12 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#endif
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
if (aState.mHaveRightFloaters &&
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
// We are reflowing in an unconstrained situation or shrink wrapping and
// have some right floaters. They were placed at the infinite right edge
// which will cause the combined area to be unusable.
//
// To solve this issue, we pretend that the right floaters ended up just
// past the end of the line. Note that the right floater combined area
// we computed as we were going will have as its X coordinate the left
// most edge of all the right floaters. Therefore, to accomplish our goal
// all we do is set that X value to the lines XMost value.
#ifdef NOISY_COMBINED_AREA
printf(" ==> rightFloaterCA=%d,%d,%d,%d lineXMost=%d\n",
aState.mRightFloaterCombinedArea.x,
aState.mRightFloaterCombinedArea.y,
aState.mRightFloaterCombinedArea.width,
aState.mRightFloaterCombinedArea.height,
aLine->mBounds.XMost());
#endif
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
// Mark the line dirty so we come back and re-place the floater once
// the shrink wrap width is determined
aLine->MarkDirty();
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
}
}
aLine->SetCombinedArea(lineCombinedArea);
#ifdef NOISY_COMBINED_AREA
printf(" ==> final lineCA=%d,%d,%d,%d\n",
lineCombinedArea.x, lineCombinedArea.y,
lineCombinedArea.width, lineCombinedArea.height);
#endif
aState.mHaveRightFloaters = PR_FALSE;
}
// Apply break-after clearing if necessary

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

@ -124,7 +124,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mContentArea.width = PR_MAX(0, aReflowState.availableWidth - lr);
}
}
mHaveRightFloaters = PR_FALSE;
// Compute content area height. Unlike the width, if we have a
// specified style height we ignore it since extra content is
@ -1007,7 +1006,6 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// coordinates are computed <b>relative to the translation in the
// spacemanager</b> which means that the impacted region will be
// <b>inside</b> the border/padding area.
PRBool okToAddRectRegion = PR_TRUE;
PRBool isLeftFloater;
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
isLeftFloater = PR_TRUE;
@ -1031,8 +1029,10 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
}
else {
okToAddRectRegion = PR_FALSE;
region.x = NS_UNCONSTRAINEDSIZE - region.width;
// For unconstrained reflows, pretend that a right floater is
// instead a left floater. This will make us end up with the
// correct unconstrained width, and we'll place it later.
region.x = mAvailSpaceRect.x;
}
}
*aIsLeftFloater = isLeftFloater;
@ -1048,18 +1048,16 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
// Place the floater in the space manager
if (okToAddRectRegion) {
// if the floater split, then take up all of the vertical height
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
region.height = PR_MAX(region.height, mContentArea.height);
}
#ifdef DEBUG
nsresult rv =
#endif
mSpaceManager->AddRectRegion(floater, region);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad floater placement");
// if the floater split, then take up all of the vertical height
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
region.height = PR_MAX(region.height, mContentArea.height);
}
#ifdef DEBUG
nsresult rv =
#endif
mSpaceManager->AddRectRegion(floater, region);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad floater placement");
// If the floater's dimensions have changed, note the damage in the
// space manager.
@ -1116,23 +1114,21 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
nsRect combinedArea = aFloaterCache->mCombinedArea;
combinedArea.x += x;
combinedArea.y += y;
if (!isLeftFloater &&
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
// When we are placing a right floater in an unconstrained situation or
// when shrink wrapping, we don't apply it to the floater combined area
// immediately. Otherwise we end up with an infinitely wide combined
// area. Instead, we save it away in mRightFloaterCombinedArea so that
// later on when we know the width of a line we can compute a better value.
if (!mHaveRightFloaters) {
mRightFloaterCombinedArea = combinedArea;
mHaveRightFloaters = PR_TRUE;
}
else {
nsBlockFrame::CombineRects(combinedArea, mRightFloaterCombinedArea);
}
}
else {
// When we are placing a right floater in an unconstrained situation or
// when shrink wrapping, we don't apply it to the floater combined area
// immediately, since there's no need to since we're guaranteed another
// reflow, and since there's no need to change the code that was
// necessary back when the floater was positioned relative to
// NS_UNCONSTRAINEDSIZE.
if (isLeftFloater ||
!GetFlag(BRS_UNCONSTRAINEDWIDTH) ||
!GetFlag(BRS_SHRINKWRAPWIDTH)) {
nsBlockFrame::CombineRects(combinedArea, mFloaterCombinedArea);
} else if (GetFlag(BRS_SHRINKWRAPWIDTH)) {
// Mark the line dirty so we come back and re-place the floater once
// the shrink wrap width is determined
mCurrentLine->MarkDirty();
SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
}
// Remember the y-coordinate of the floater we've just placed

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

@ -192,11 +192,6 @@ public:
// to enforce 9.5.1 rule [2]
nscoord mLastFloaterY;
// For unconstained-width reflow, we keep the right floaters
// combined area stored seperately.
PRBool mHaveRightFloaters;
nsRect mRightFloaterCombinedArea;
nsFloaterCacheFreeList mFloaterCacheFreeList;
// Previous child. This is used when pulling up a frame to update

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

@ -69,7 +69,6 @@ class nsIChannel;
#define NS_BLOCK_NO_AUTO_MARGINS 0x00200000
#define NS_BLOCK_MARGIN_ROOT 0x00400000
#define NS_BLOCK_SPACE_MGR 0x00800000
#define NS_BLOCK_WRAP_SIZE 0x01000000
#define NS_BLOCK_FLAGS_MASK 0xFFF00000
// Factory method for creating a content iterator for generated
@ -108,7 +107,7 @@ NS_NewAttributeContent(nsIContent ** aResult);
// By default, area frames will extend
// their height to cover any children that "stick out".
extern nsresult NS_NewSelectsAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
PRUint32 aFlags = NS_BLOCK_WRAP_SIZE);
PRUint32 aFlags);
// Create a basic area frame.
extern nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
@ -117,7 +116,7 @@ extern nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
// These AreaFrame's shrink wrap around their contents
inline nsresult NS_NewTableCellInnerFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) {
return NS_NewBlockFrame(aPresShell, aNewFrame,
NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE|NS_BLOCK_MARGIN_ROOT);
NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
}
// This type of AreaFrame is the document root, a margin root, and the

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

@ -106,6 +106,7 @@ MOZ_DECL_CTOR_COUNTER(nsSpaceManager)
nsSpaceManager::nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame)
: mFrame(aFrame),
mXMost(0),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell)
{
MOZ_COUNT_CTOR(nsSpaceManager);
@ -195,6 +196,12 @@ void nsSpaceManager::Shutdown()
sCachedSpaceManagerCount = -1;
}
PRBool
nsSpaceManager::XMost(nscoord& aXMost) const
{
aXMost = mXMost;
return !mBandList.IsEmpty();
}
PRBool
nsSpaceManager::YMost(nscoord& aYMost) const
@ -806,6 +813,10 @@ 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;
// Create a frame info structure
frameInfo = CreateFrameInfo(aFrame, rect);
if (nsnull == frameInfo) {
@ -1026,6 +1037,7 @@ nsSpaceManager::PushState()
state->mX = mX;
state->mY = mY;
state->mXMost = mXMost;
if (mFrameInfoMap) {
state->mLastFrame = mFrameInfoMap->mFrame;
@ -1069,6 +1081,7 @@ nsSpaceManager::PopState()
mX = mSavedStates->mX;
mY = mSavedStates->mY;
mXMost = mSavedStates->mXMost;
// Now that we've restored our state, pop the topmost
// state and delete it.

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

@ -194,6 +194,14 @@ public:
*/
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
/**
* Returns the x-most rect in the space manager, or 0 if there are no
* rects.
*
* @return PR_TRUE if there are bands and PR_FALSE if there are no bands
*/
PRBool XMost(nscoord& aXMost) const;
/**
* Returns the y-most of the bottommost band or 0 if there are no bands.
*
@ -335,6 +343,7 @@ protected:
struct SpaceManagerState {
nscoord mX, mY;
nsIFrame *mLastFrame;
nscoord mXMost;
SpaceManagerState *mNext;
SpaceManagerState() : mX(0), mY(0), mLastFrame(nsnull), mNext(nsnull) {}
@ -409,6 +418,7 @@ 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;
FrameInfo* mFrameInfoMap;
nsIntervalSet mFloatDamage;

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

@ -1182,6 +1182,8 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
{
const nsHTMLReflowState* rs = &aReflowState;
if (NS_UNCONSTRAINEDSIZE == rs->mComputedWidth) {
// XXXldb Why isn't this always true for the cases where this
// function returns true?
return PR_TRUE;
}
const nsStylePosition* pos = rs->mStylePosition;
@ -1297,37 +1299,33 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
maxWidth = aMetrics.width;
}
else {
nscoord minWidth = aState.mKidXMost + borderPadding.right;
nscoord computedWidth = minWidth;
PRBool compact = PR_FALSE;
#if 0
if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) {
// If we are display: compact AND we have no lines or we have
// exactly one line and that line is not a block line AND that
// line doesn't end in a BR of any sort THEN we remain a compact
// frame.
if ((mLines.empty()) ||
((mLines.front() == mLines.back()) && !mLines.front()->IsBlock() &&
(NS_STYLE_CLEAR_NONE == mLines.front()->GetBreakType())
/*XXX && (computedWidth <= aState.mCompactMarginWidth) */
)) {
compact = PR_TRUE;
}
}
#endif
nscoord computedWidth;
// XXX Misleading comment:
// There are two options here. We either shrink wrap around our
// contents or we fluff out to the maximum block width. Note:
// We always shrink wrap when given an unconstrained width.
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) &&
!aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
!compact) {
!aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
// XXX Misleading comment:
// Set our width to the max width if we aren't already that
// wide. Note that the max-width has nothing to do with our
// contents (CSS2 section XXX)
// XXXldb In what cases do we reach this code?
computedWidth = borderPadding.left + aState.mContentArea.width +
borderPadding.right;
} else {
computedWidth = aState.mKidXMost;
if (NS_BLOCK_SPACE_MGR & mState) {
// Include the space manager's state to properly account for the
// extent of floated elements.
nscoord xmost;
if (aReflowState.mSpaceManager->XMost(xmost) &&
computedWidth < xmost)
computedWidth = xmost;
}
computedWidth += borderPadding.right;
}
// See if we should compute our max element size
@ -1337,6 +1335,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
maxWidth = aState.mMaxElementSize.width +
borderPadding.left + borderPadding.right;
if (computedWidth < maxWidth) {
// XXXldb It's *compute* max-element-size, not *change size
// based on* max-element-size...
computedWidth = maxWidth;
}
}
@ -1374,6 +1374,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
if (!parentIsShrinkWrapWidth) {
// XXX Is this only used on things that are already NS_BLOCK_SPACE_MGR
// and NS_BLOCK_MARGIN_ROOT?
nsHTMLReflowState reflowState(aReflowState);
reflowState.mComputedWidth = aMetrics.width - borderPadding.left -
@ -1393,15 +1395,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
}
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
PRBool parentIsShrinkWrapWidth = PR_FALSE;
if (aReflowState.parentReflowState) {
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
parentIsShrinkWrapWidth = PR_TRUE;
}
}
}
// Compute final height
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) {
if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
@ -1452,16 +1445,16 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
// XXX check for a fit
autoHeight += aState.mPrevBottomMargin.get();
}
autoHeight += borderPadding.bottom;
if (NS_BLOCK_SPACE_MGR & mState) {
// Include the space manager's state to properly account for the
// bottom margin of any floated elements; e.g., inside a table cell.
nscoord ymost;
aReflowState.mSpaceManager->YMost(ymost);
if (ymost > autoHeight)
if (aReflowState.mSpaceManager->YMost(ymost) &&
autoHeight < ymost)
autoHeight = ymost;
}
autoHeight += borderPadding.bottom;
// Apply min/max values
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) {
@ -1565,32 +1558,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
else {
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
}
if (NS_BLOCK_WRAP_SIZE & mState) {
// When the area frame is supposed to wrap around all in-flow
// children, make sure it is big enough to include those that stick
// outside the box.
if (NS_FRAME_OUTSIDE_CHILDREN & mState) {
nscoord xMost = aMetrics.mOverflowArea.XMost();
if (xMost > aMetrics.width) {
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
printf(": changing desired width from %d to %d\n", aMetrics.width, xMost);
#endif
aMetrics.width = xMost;
}
nscoord yMost = aMetrics.mOverflowArea.YMost();
if (yMost > aMetrics.height) {
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
printf(": changing desired height from %d to %d\n", aMetrics.height, yMost);
#endif
aMetrics.height = yMost;
// adjust descent to absorb any excess difference
aMetrics.descent = aMetrics.height - aMetrics.ascent;
}
}
}
}
void
@ -2659,9 +2626,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
#if defined(DEBUG_waterson) || defined(DEBUG_dbaron)
// XXXwaterson if oldUnconstrainedWidth was set, why do we need
// to do the second reflow, below?
if (oldUnconstrainedWidth)
printf("*** oldUnconstrainedWidth was already set.\n"
"*** This code (%s:%d) could be optimized a lot!\n",
"*** This code (%s:%d) could be optimized a lot!\n"
"+++ possibly doing an unnecessary second-pass unconstrained "
"reflow\n",
__FILE__, __LINE__);
#endif
@ -2678,13 +2650,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
aState.mSpaceManager->PopState();
#ifdef DEBUG_waterson
// XXXwaterson if oldUnconstrainedWidth was set, why do we need
// to do the second reflow, below?
if (oldUnconstrainedWidth)
printf("+++ possibly doing an unnecessary second-pass unconstrained reflow\n");
#endif
// Update the line's maximum width
aLine->mMaximumWidth = aLine->mBounds.XMost();
#ifdef NOISY_MAXIMUM_WIDTH
@ -3707,7 +3672,6 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// Forget all of the floaters on the line
aLine->FreeFloaters(aState.mFloaterCacheFreeList);
aState.mFloaterCombinedArea.SetRect(0, 0, 0, 0);
aState.mRightFloaterCombinedArea.SetRect(0, 0, 0, 0);
// Setup initial coordinate system for reflowing the inline frames
// into. Apply a previous block frame's bottom margin first.
@ -4413,9 +4377,8 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
printf("PASS1 ");
}
ListTag(stdout);
printf(": line.floaters=%s band.floaterCount=%d\n",
printf(": band.floaterCount=%d\n",
//aLine->mFloaters.NotEmpty() ? "yes" : "no",
aState.mHaveRightFloaters ? "(have right floaters)" : "",
aState.mBand.GetFloaterCount());
}
#endif
@ -4488,42 +4451,12 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#endif
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
if (aState.mHaveRightFloaters &&
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
// We are reflowing in an unconstrained situation or shrink wrapping and
// have some right floaters. They were placed at the infinite right edge
// which will cause the combined area to be unusable.
//
// To solve this issue, we pretend that the right floaters ended up just
// past the end of the line. Note that the right floater combined area
// we computed as we were going will have as its X coordinate the left
// most edge of all the right floaters. Therefore, to accomplish our goal
// all we do is set that X value to the lines XMost value.
#ifdef NOISY_COMBINED_AREA
printf(" ==> rightFloaterCA=%d,%d,%d,%d lineXMost=%d\n",
aState.mRightFloaterCombinedArea.x,
aState.mRightFloaterCombinedArea.y,
aState.mRightFloaterCombinedArea.width,
aState.mRightFloaterCombinedArea.height,
aLine->mBounds.XMost());
#endif
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
// Mark the line dirty so we come back and re-place the floater once
// the shrink wrap width is determined
aLine->MarkDirty();
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
}
}
aLine->SetCombinedArea(lineCombinedArea);
#ifdef NOISY_COMBINED_AREA
printf(" ==> final lineCA=%d,%d,%d,%d\n",
lineCombinedArea.x, lineCombinedArea.y,
lineCombinedArea.width, lineCombinedArea.height);
#endif
aState.mHaveRightFloaters = PR_FALSE;
}
// Apply break-after clearing if necessary

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

@ -124,7 +124,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mContentArea.width = PR_MAX(0, aReflowState.availableWidth - lr);
}
}
mHaveRightFloaters = PR_FALSE;
// Compute content area height. Unlike the width, if we have a
// specified style height we ignore it since extra content is
@ -1007,7 +1006,6 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// coordinates are computed <b>relative to the translation in the
// spacemanager</b> which means that the impacted region will be
// <b>inside</b> the border/padding area.
PRBool okToAddRectRegion = PR_TRUE;
PRBool isLeftFloater;
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
isLeftFloater = PR_TRUE;
@ -1031,8 +1029,10 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
}
else {
okToAddRectRegion = PR_FALSE;
region.x = NS_UNCONSTRAINEDSIZE - region.width;
// For unconstrained reflows, pretend that a right floater is
// instead a left floater. This will make us end up with the
// correct unconstrained width, and we'll place it later.
region.x = mAvailSpaceRect.x;
}
}
*aIsLeftFloater = isLeftFloater;
@ -1048,18 +1048,16 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
// Place the floater in the space manager
if (okToAddRectRegion) {
// if the floater split, then take up all of the vertical height
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
region.height = PR_MAX(region.height, mContentArea.height);
}
#ifdef DEBUG
nsresult rv =
#endif
mSpaceManager->AddRectRegion(floater, region);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad floater placement");
// if the floater split, then take up all of the vertical height
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
region.height = PR_MAX(region.height, mContentArea.height);
}
#ifdef DEBUG
nsresult rv =
#endif
mSpaceManager->AddRectRegion(floater, region);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad floater placement");
// If the floater's dimensions have changed, note the damage in the
// space manager.
@ -1116,23 +1114,21 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
nsRect combinedArea = aFloaterCache->mCombinedArea;
combinedArea.x += x;
combinedArea.y += y;
if (!isLeftFloater &&
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
// When we are placing a right floater in an unconstrained situation or
// when shrink wrapping, we don't apply it to the floater combined area
// immediately. Otherwise we end up with an infinitely wide combined
// area. Instead, we save it away in mRightFloaterCombinedArea so that
// later on when we know the width of a line we can compute a better value.
if (!mHaveRightFloaters) {
mRightFloaterCombinedArea = combinedArea;
mHaveRightFloaters = PR_TRUE;
}
else {
nsBlockFrame::CombineRects(combinedArea, mRightFloaterCombinedArea);
}
}
else {
// When we are placing a right floater in an unconstrained situation or
// when shrink wrapping, we don't apply it to the floater combined area
// immediately, since there's no need to since we're guaranteed another
// reflow, and since there's no need to change the code that was
// necessary back when the floater was positioned relative to
// NS_UNCONSTRAINEDSIZE.
if (isLeftFloater ||
!GetFlag(BRS_UNCONSTRAINEDWIDTH) ||
!GetFlag(BRS_SHRINKWRAPWIDTH)) {
nsBlockFrame::CombineRects(combinedArea, mFloaterCombinedArea);
} else if (GetFlag(BRS_SHRINKWRAPWIDTH)) {
// Mark the line dirty so we come back and re-place the floater once
// the shrink wrap width is determined
mCurrentLine->MarkDirty();
SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
}
// Remember the y-coordinate of the floater we've just placed

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

@ -192,11 +192,6 @@ public:
// to enforce 9.5.1 rule [2]
nscoord mLastFloaterY;
// For unconstained-width reflow, we keep the right floaters
// combined area stored seperately.
PRBool mHaveRightFloaters;
nsRect mRightFloaterCombinedArea;
nsFloaterCacheFreeList mFloaterCacheFreeList;
// Previous child. This is used when pulling up a frame to update

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

@ -69,7 +69,6 @@ class nsIChannel;
#define NS_BLOCK_NO_AUTO_MARGINS 0x00200000
#define NS_BLOCK_MARGIN_ROOT 0x00400000
#define NS_BLOCK_SPACE_MGR 0x00800000
#define NS_BLOCK_WRAP_SIZE 0x01000000
#define NS_BLOCK_FLAGS_MASK 0xFFF00000
// Factory method for creating a content iterator for generated
@ -108,7 +107,7 @@ NS_NewAttributeContent(nsIContent ** aResult);
// By default, area frames will extend
// their height to cover any children that "stick out".
extern nsresult NS_NewSelectsAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
PRUint32 aFlags = NS_BLOCK_WRAP_SIZE);
PRUint32 aFlags);
// Create a basic area frame.
extern nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
@ -117,7 +116,7 @@ extern nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
// These AreaFrame's shrink wrap around their contents
inline nsresult NS_NewTableCellInnerFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) {
return NS_NewBlockFrame(aPresShell, aNewFrame,
NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE|NS_BLOCK_MARGIN_ROOT);
NS_BLOCK_SPACE_MGR|NS_BLOCK_MARGIN_ROOT);
}
// This type of AreaFrame is the document root, a margin root, and the

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

@ -65,7 +65,7 @@
nsTableCaptionFrame::nsTableCaptionFrame()
{
// shrink wrap
SetFlags(NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE);
SetFlags(NS_BLOCK_SPACE_MGR);
}
nsTableCaptionFrame::~nsTableCaptionFrame()

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

@ -65,7 +65,7 @@
nsTableCaptionFrame::nsTableCaptionFrame()
{
// shrink wrap
SetFlags(NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE);
SetFlags(NS_BLOCK_SPACE_MGR);
}
nsTableCaptionFrame::~nsTableCaptionFrame()