2001-09-29 00:14:13 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2001-10-25 05:08:40 +04:00
|
|
|
// vim:cindent:ts=2:et:sw=2:
|
2001-09-29 00:14:13 +04:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
2004-04-18 18:30:37 +04:00
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
1998-09-15 04:19:49 +04:00
|
|
|
*
|
2004-04-18 18:30:37 +04:00
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
1998-09-15 04:19:49 +04:00
|
|
|
*
|
2001-09-29 00:14:13 +04:00
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
1998-09-15 04:19:49 +04:00
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code.
|
|
|
|
*
|
2004-04-18 18:30:37 +04:00
|
|
|
* The Initial Developer of the Original Code is
|
2001-09-29 00:14:13 +04:00
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 06:40:37 +03:00
|
|
|
*
|
2001-09-29 00:14:13 +04:00
|
|
|
* Contributor(s):
|
2000-04-17 18:40:46 +04:00
|
|
|
* Steve Clark <buster@netscape.com>
|
|
|
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
2003-01-02 02:53:20 +03:00
|
|
|
* L. David Baron <dbaron@dbaron.org>
|
2006-08-24 09:22:16 +04:00
|
|
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
2001-09-29 00:14:13 +04:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
2004-04-18 18:30:37 +04:00
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
2001-09-29 00:14:13 +04:00
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
2004-04-18 18:30:37 +04:00
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
2001-09-29 00:14:13 +04:00
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
2004-04-18 18:30:37 +04:00
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
2001-09-29 00:14:13 +04:00
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
1998-09-24 00:10:40 +04:00
|
|
|
|
2006-03-29 22:29:03 +04:00
|
|
|
/* state used in reflow of block frames */
|
|
|
|
|
2001-05-01 08:22:57 +04:00
|
|
|
#include "nsBlockReflowContext.h"
|
|
|
|
#include "nsBlockReflowState.h"
|
|
|
|
#include "nsBlockFrame.h"
|
|
|
|
#include "nsLineLayout.h"
|
2004-08-01 03:15:21 +04:00
|
|
|
#include "nsPresContext.h"
|
2007-01-30 03:06:41 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2001-05-01 08:22:57 +04:00
|
|
|
#include "nsIFrame.h"
|
2004-02-24 00:29:06 +03:00
|
|
|
#include "nsFrameManager.h"
|
2010-08-06 08:59:19 +04:00
|
|
|
#include "mozilla/AutoRestore.h"
|
2001-05-01 08:22:57 +04:00
|
|
|
|
2002-03-08 23:25:54 +03:00
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
|
|
|
|
|
2001-05-01 08:22:57 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
#include "nsBlockDebugFlags.h"
|
|
|
|
#endif
|
1998-09-15 04:19:49 +04:00
|
|
|
|
2010-08-06 08:59:19 +04:00
|
|
|
using namespace mozilla;
|
|
|
|
|
1999-03-05 07:21:32 +03:00
|
|
|
nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
2004-08-01 03:15:21 +04:00
|
|
|
nsPresContext* aPresContext,
|
1999-03-05 07:21:32 +03:00
|
|
|
nsBlockFrame* aFrame,
|
2000-01-03 07:32:13 +03:00
|
|
|
const nsHTMLReflowMetrics& aMetrics,
|
2004-11-25 17:51:00 +03:00
|
|
|
PRBool aTopMarginRoot,
|
2007-02-19 02:53:25 +03:00
|
|
|
PRBool aBottomMarginRoot,
|
2009-01-05 03:39:54 +03:00
|
|
|
PRBool aBlockNeedsFloatManager)
|
1999-04-03 22:59:01 +04:00
|
|
|
: mBlock(aFrame),
|
|
|
|
mPresContext(aPresContext),
|
1999-03-05 07:21:32 +03:00
|
|
|
mReflowState(aReflowState),
|
2009-09-14 04:26:01 +04:00
|
|
|
mOverflowTracker(nsnull),
|
2001-10-25 05:08:40 +04:00
|
|
|
mPrevBottomMargin(),
|
2000-04-17 18:40:46 +04:00
|
|
|
mLineNumber(0),
|
2002-07-17 05:48:56 +04:00
|
|
|
mFlags(0),
|
2008-02-19 10:36:50 +03:00
|
|
|
mFloatBreakType(NS_STYLE_CLEAR_NONE)
|
1998-11-15 00:01:26 +03:00
|
|
|
{
|
2005-04-26 06:26:12 +04:00
|
|
|
SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nsnull);
|
2007-07-26 08:03:29 +04:00
|
|
|
SetFlag(BRS_ISOVERFLOWCONTAINER,
|
2007-10-02 09:57:45 +04:00
|
|
|
IS_TRUE_OVERFLOW_CONTAINER(aFrame));
|
2005-04-26 06:26:12 +04:00
|
|
|
|
2000-01-18 18:36:36 +03:00
|
|
|
const nsMargin& borderPadding = BorderPadding();
|
|
|
|
|
2004-11-25 17:51:00 +03:00
|
|
|
if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) {
|
2000-04-17 18:40:46 +04:00
|
|
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
2000-01-13 05:05:31 +03:00
|
|
|
}
|
2004-11-25 17:51:00 +03:00
|
|
|
if (aBottomMarginRoot || 0 != aReflowState.mComputedBorderPadding.bottom) {
|
2000-04-17 18:40:46 +04:00
|
|
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
2000-01-13 05:05:31 +03:00
|
|
|
}
|
2000-04-17 18:40:46 +04:00
|
|
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
|
|
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
2000-01-03 07:32:13 +03:00
|
|
|
}
|
2009-01-05 03:39:54 +03:00
|
|
|
if (aBlockNeedsFloatManager) {
|
|
|
|
SetFlag(BRS_FLOAT_MGR, PR_TRUE);
|
2007-02-19 02:53:25 +03:00
|
|
|
}
|
2000-01-03 07:32:13 +03:00
|
|
|
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager = aReflowState.mFloatManager;
|
1998-09-24 00:10:40 +04:00
|
|
|
|
2009-01-05 03:39:54 +03:00
|
|
|
NS_ASSERTION(mFloatManager,
|
|
|
|
"FloatManager should be set in nsBlockReflowState" );
|
|
|
|
if (mFloatManager) {
|
2000-01-18 18:36:36 +03:00
|
|
|
// Translate into our content area and then save the
|
|
|
|
// coordinate system origin for later.
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->Translate(borderPadding.left, borderPadding.top);
|
|
|
|
mFloatManager->GetTranslation(mFloatManagerX, mFloatManagerY);
|
2009-04-09 00:52:36 +04:00
|
|
|
mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
|
2000-01-18 18:36:36 +03:00
|
|
|
}
|
1998-09-24 00:10:40 +04:00
|
|
|
|
1998-12-05 19:02:08 +03:00
|
|
|
mReflowStatus = NS_FRAME_COMPLETE;
|
1998-09-24 00:10:40 +04:00
|
|
|
|
1998-12-05 19:02:08 +03:00
|
|
|
mPresContext = aPresContext;
|
2007-07-08 11:08:04 +04:00
|
|
|
mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
|
1998-09-24 00:10:40 +04:00
|
|
|
|
2009-10-29 06:22:28 +03:00
|
|
|
NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedWidth(),
|
|
|
|
"have unconstrained width; this should only result from "
|
|
|
|
"very large sizes, not attempts at intrinsic width "
|
|
|
|
"calculation");
|
2007-01-26 03:05:12 +03:00
|
|
|
mContentArea.width = aReflowState.ComputedWidth();
|
1998-12-30 20:50:00 +03:00
|
|
|
|
1999-03-05 07:21:32 +03:00
|
|
|
// Compute content area height. Unlike the width, if we have a
|
|
|
|
// specified style height we ignore it since extra content is
|
|
|
|
// managed by the "overflow" property. When we don't have a
|
|
|
|
// specified style height then we may end up limiting our height if
|
|
|
|
// the availableHeight is constrained (this situation occurs when we
|
|
|
|
// are paginated).
|
1999-03-23 07:28:20 +03:00
|
|
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
1999-04-03 22:59:01 +04:00
|
|
|
// We are in a paginated situation. The bottom edge is just inside
|
|
|
|
// the bottom border and padding. The content area height doesn't
|
|
|
|
// include either border or padding edge.
|
|
|
|
mBottomEdge = aReflowState.availableHeight - borderPadding.bottom;
|
2009-09-16 19:01:36 +04:00
|
|
|
mContentArea.height = NS_MAX(0, mBottomEdge - borderPadding.top);
|
1999-03-23 07:28:20 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// When we are not in a paginated situation then we always use
|
|
|
|
// an constrained height.
|
2000-04-17 18:40:46 +04:00
|
|
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
1999-04-03 22:59:01 +04:00
|
|
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
1999-03-05 07:21:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mY = borderPadding.top;
|
1998-12-05 19:02:08 +03:00
|
|
|
|
|
|
|
mPrevChild = nsnull;
|
2001-10-25 05:08:40 +04:00
|
|
|
mCurrentLine = aFrame->end_lines();
|
1999-03-05 07:21:32 +03:00
|
|
|
|
2009-05-19 02:13:12 +04:00
|
|
|
mMinLineHeight = aReflowState.CalcLineHeight();
|
1998-09-24 00:10:40 +04:00
|
|
|
}
|
|
|
|
|
1998-12-05 19:02:08 +03:00
|
|
|
nsBlockReflowState::~nsBlockReflowState()
|
1998-09-24 00:10:40 +04:00
|
|
|
{
|
2009-08-31 22:25:36 +04:00
|
|
|
NS_ASSERTION(mFloatContinuations.IsEmpty(),
|
|
|
|
"Leaking float continuation frames");
|
2006-12-12 04:06:23 +03:00
|
|
|
|
2009-01-05 03:39:54 +03:00
|
|
|
// Restore the coordinate system, unless the float manager is null,
|
2001-11-03 08:18:39 +03:00
|
|
|
// which means it was just destroyed.
|
2009-01-05 03:39:54 +03:00
|
|
|
if (mFloatManager) {
|
2001-11-03 08:18:39 +03:00
|
|
|
const nsMargin& borderPadding = BorderPadding();
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->Translate(-borderPadding.left, -borderPadding.top);
|
2001-11-03 08:18:39 +03:00
|
|
|
}
|
2005-03-23 06:35:08 +03:00
|
|
|
|
2009-08-31 22:25:36 +04:00
|
|
|
if (GetFlag(BRS_PROPTABLE_FLOATCLIST)) {
|
2010-03-29 05:46:55 +04:00
|
|
|
mPresContext->PropertyTable()->
|
|
|
|
Delete(mBlock, nsBlockFrame::FloatContinuationProperty());
|
2005-03-23 06:35:08 +03:00
|
|
|
}
|
1999-10-20 03:04:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsLineBox*
|
|
|
|
nsBlockReflowState::NewLineBox(nsIFrame* aFrame,
|
|
|
|
PRInt32 aCount,
|
|
|
|
PRBool aIsBlock)
|
|
|
|
{
|
2003-12-21 08:36:36 +03:00
|
|
|
return NS_NewLineBox(mPresContext->PresShell(), aFrame, aCount, aIsBlock);
|
1999-10-20 03:04:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsBlockReflowState::FreeLineBox(nsLineBox* aLine)
|
|
|
|
{
|
|
|
|
if (aLine) {
|
2003-12-21 08:36:36 +03:00
|
|
|
aLine->Destroy(mPresContext->PresShell());
|
1999-10-20 03:04:19 +04:00
|
|
|
}
|
1998-09-24 00:10:40 +04:00
|
|
|
}
|
|
|
|
|
2008-04-15 05:05:17 +04:00
|
|
|
void
|
|
|
|
nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
|
2009-04-09 00:52:37 +04:00
|
|
|
const nsRect& aFloatAvailableSpace,
|
2008-04-15 05:05:17 +04:00
|
|
|
nscoord& aLeftResult,
|
|
|
|
nscoord& aRightResult,
|
|
|
|
nsBlockFrame::
|
|
|
|
ReplacedElementWidthToClear
|
|
|
|
*aReplacedWidth)
|
|
|
|
{
|
2009-01-05 03:39:54 +03:00
|
|
|
// The frame is clueless about the float manager and therefore we
|
2008-04-15 05:05:17 +04:00
|
|
|
// only give it free space. An example is a table frame - the
|
|
|
|
// tables do not flow around floats.
|
|
|
|
// However, we can let its margins intersect floats.
|
2009-04-09 00:52:37 +04:00
|
|
|
NS_ASSERTION(aFloatAvailableSpace.x >= 0, "bad avail space rect x");
|
|
|
|
NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
|
|
|
|
aFloatAvailableSpace.XMost() <= mContentArea.width,
|
2008-04-15 05:05:17 +04:00
|
|
|
"bad avail space rect width");
|
|
|
|
|
|
|
|
nscoord leftOffset, rightOffset;
|
2009-04-09 00:52:37 +04:00
|
|
|
if (aFloatAvailableSpace.width == mContentArea.width) {
|
2008-04-15 05:05:17 +04:00
|
|
|
// We don't need to compute margins when there are no floats around.
|
|
|
|
leftOffset = 0;
|
|
|
|
rightOffset = 0;
|
|
|
|
} else {
|
|
|
|
// We pass in aReplacedWidth to make handling outer table frames
|
|
|
|
// work correctly. For outer table frames, we need to subtract off
|
|
|
|
// the margin that's going to be at the edge of them, since we're
|
|
|
|
// dealing with margin that it's really the child's responsibility
|
|
|
|
// to place.
|
|
|
|
nsCSSOffsetState os(aFrame, mReflowState.rendContext, mContentArea.width);
|
|
|
|
NS_ASSERTION(!aReplacedWidth ||
|
|
|
|
aFrame->GetType() == nsGkAtoms::tableOuterFrame ||
|
|
|
|
(aReplacedWidth->marginLeft == os.mComputedMargin.left &&
|
|
|
|
aReplacedWidth->marginRight == os.mComputedMargin.right),
|
|
|
|
"unexpected aReplacedWidth");
|
|
|
|
|
2009-04-09 00:52:37 +04:00
|
|
|
nscoord leftFloatXOffset = aFloatAvailableSpace.x;
|
2009-09-16 19:01:36 +04:00
|
|
|
leftOffset = NS_MAX(leftFloatXOffset, os.mComputedMargin.left) -
|
2008-04-15 05:05:17 +04:00
|
|
|
(aReplacedWidth ? aReplacedWidth->marginLeft
|
|
|
|
: os.mComputedMargin.left);
|
2009-09-16 19:01:36 +04:00
|
|
|
leftOffset = NS_MAX(leftOffset, 0); // in case of negative margin
|
2009-04-09 00:52:37 +04:00
|
|
|
nscoord rightFloatXOffset =
|
|
|
|
mContentArea.width - aFloatAvailableSpace.XMost();
|
2009-09-16 19:01:36 +04:00
|
|
|
rightOffset = NS_MAX(rightFloatXOffset, os.mComputedMargin.right) -
|
2008-04-15 05:05:17 +04:00
|
|
|
(aReplacedWidth ? aReplacedWidth->marginRight
|
|
|
|
: os.mComputedMargin.right);
|
2009-09-16 19:01:36 +04:00
|
|
|
rightOffset = NS_MAX(rightOffset, 0); // in case of negative margin
|
2008-04-15 05:05:17 +04:00
|
|
|
}
|
|
|
|
aLeftResult = leftOffset;
|
|
|
|
aRightResult = rightOffset;
|
|
|
|
}
|
|
|
|
|
1999-04-03 22:59:01 +04:00
|
|
|
// Compute the amount of available space for reflowing a block frame
|
|
|
|
// at the current Y coordinate. This method assumes that
|
|
|
|
// GetAvailableSpace has already been called.
|
1998-12-05 19:02:08 +03:00
|
|
|
void
|
1999-08-28 01:45:37 +04:00
|
|
|
nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|
|
|
const nsStyleDisplay* aDisplay,
|
2009-04-09 00:52:37 +04:00
|
|
|
const nsFlowAreaRect& aFloatAvailableSpace,
|
2008-05-04 03:33:36 +04:00
|
|
|
PRBool aBlockAvoidsFloats,
|
1999-04-03 22:59:01 +04:00
|
|
|
nsRect& aResult)
|
1998-09-24 00:10:40 +04:00
|
|
|
{
|
2000-04-17 18:40:46 +04:00
|
|
|
#ifdef REALLY_NOISY_REFLOW
|
2009-04-09 00:52:37 +04:00
|
|
|
printf("CBAS frame=%p has floats %d\n",
|
|
|
|
aFrame, aFloatAvailableSpace.mHasFloats);
|
2000-04-17 18:40:46 +04:00
|
|
|
#endif
|
1999-09-16 23:56:36 +04:00
|
|
|
aResult.y = mY;
|
2000-04-17 18:40:46 +04:00
|
|
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
1999-04-03 22:59:01 +04:00
|
|
|
? NS_UNCONSTRAINEDSIZE
|
2009-09-16 19:01:36 +04:00
|
|
|
: NS_MAX(0, mReflowState.availableHeight - mY);
|
2007-12-12 04:21:34 +03:00
|
|
|
// mY might be greater than mBottomEdge if the block's top margin pushes
|
|
|
|
// it off the page/column. Negative available height can confuse other code
|
|
|
|
// and is nonsense in principle.
|
1998-09-24 00:10:40 +04:00
|
|
|
|
1999-04-03 22:59:01 +04:00
|
|
|
const nsMargin& borderPadding = BorderPadding();
|
1999-08-28 01:45:37 +04:00
|
|
|
|
2008-01-29 10:40:05 +03:00
|
|
|
// XXX Do we really want this condition to be this restrictive (i.e.,
|
|
|
|
// more restrictive than it used to be)? The |else| here is allowed
|
|
|
|
// by the CSS spec, but only out of desperation given implementations,
|
|
|
|
// and the behavior it leads to is quite undesirable (it can cause
|
|
|
|
// things to become extremely narrow when they'd fit quite well a
|
|
|
|
// little bit lower). Should the else be a quirk or something that
|
|
|
|
// applies to a specific set of frame classes and no new ones?
|
|
|
|
// If we did that, then for those frames where the condition below is
|
|
|
|
// true but nsBlockFrame::BlockCanIntersectFloats is false,
|
|
|
|
// nsBlockFrame::WidthToClearPastFloats would need to use the
|
|
|
|
// shrink-wrap formula, max(MIN_WIDTH, min(avail width, PREF_WIDTH))
|
|
|
|
// rather than just using MIN_WIDTH.
|
2008-05-04 03:33:36 +04:00
|
|
|
NS_ASSERTION(nsBlockFrame::BlockCanIntersectFloats(aFrame) ==
|
|
|
|
!aBlockAvoidsFloats,
|
2008-04-15 05:05:17 +04:00
|
|
|
"unexpected replaced width");
|
2008-05-04 03:33:36 +04:00
|
|
|
if (!aBlockAvoidsFloats) {
|
2009-04-09 00:52:37 +04:00
|
|
|
if (aFloatAvailableSpace.mHasFloats) {
|
1999-09-16 23:56:36 +04:00
|
|
|
// Use the float-edge property to determine how the child block
|
2003-10-14 01:51:02 +04:00
|
|
|
// will interact with the float.
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
|
2001-02-07 12:57:26 +03:00
|
|
|
switch (borderStyle->mFloatEdge) {
|
1999-09-16 23:56:36 +04:00
|
|
|
default:
|
2003-10-14 01:51:02 +04:00
|
|
|
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floats
|
|
|
|
// The child block will flow around the float. Therefore
|
1999-09-16 23:56:36 +04:00
|
|
|
// give it all of the available space.
|
|
|
|
aResult.x = borderPadding.left;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
aResult.width = mContentArea.width;
|
|
|
|
break;
|
1999-09-16 23:56:36 +04:00
|
|
|
case NS_STYLE_FLOAT_EDGE_MARGIN:
|
|
|
|
{
|
|
|
|
// The child block's margins should be placed adjacent to,
|
2003-10-14 01:51:02 +04:00
|
|
|
// but not overlap the float.
|
2009-04-09 00:52:37 +04:00
|
|
|
aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left;
|
|
|
|
aResult.width = aFloatAvailableSpace.mRect.width;
|
1999-09-16 23:56:36 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2003-10-14 01:51:02 +04:00
|
|
|
// Since there are no floats present the float-edge property
|
1999-09-16 23:56:36 +04:00
|
|
|
// doesn't matter therefore give the block element all of the
|
2003-10-14 01:51:02 +04:00
|
|
|
// available space since it will flow around the float itself.
|
1999-09-16 23:56:36 +04:00
|
|
|
aResult.x = borderPadding.left;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
aResult.width = mContentArea.width;
|
1999-09-16 23:56:36 +04:00
|
|
|
}
|
1999-04-03 22:59:01 +04:00
|
|
|
}
|
|
|
|
else {
|
2008-05-04 03:33:36 +04:00
|
|
|
nsBlockFrame::ReplacedElementWidthToClear replacedWidthStruct;
|
|
|
|
nsBlockFrame::ReplacedElementWidthToClear *replacedWidth = nsnull;
|
|
|
|
if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) {
|
|
|
|
replacedWidth = &replacedWidthStruct;
|
2009-04-09 00:52:37 +04:00
|
|
|
replacedWidthStruct =
|
2009-04-09 00:52:37 +04:00
|
|
|
nsBlockFrame::WidthToClearPastFloats(*this, aFloatAvailableSpace.mRect,
|
2009-04-09 00:52:37 +04:00
|
|
|
aFrame);
|
2008-05-04 03:33:36 +04:00
|
|
|
}
|
|
|
|
|
2008-04-15 05:05:17 +04:00
|
|
|
nscoord leftOffset, rightOffset;
|
2009-04-09 00:52:37 +04:00
|
|
|
ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
|
2009-04-09 00:52:37 +04:00
|
|
|
leftOffset, rightOffset,
|
2008-05-04 03:33:36 +04:00
|
|
|
replacedWidth);
|
2008-04-15 05:05:17 +04:00
|
|
|
aResult.x = borderPadding.left + leftOffset;
|
|
|
|
aResult.width = mContentArea.width - leftOffset - rightOffset;
|
1999-04-03 22:59:01 +04:00
|
|
|
}
|
2003-01-09 05:24:10 +03:00
|
|
|
|
2000-03-23 02:19:10 +03:00
|
|
|
#ifdef REALLY_NOISY_REFLOW
|
2000-10-29 02:17:53 +04:00
|
|
|
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
|
2000-03-23 02:19:10 +03:00
|
|
|
#endif
|
1999-04-03 22:59:01 +04:00
|
|
|
}
|
1998-09-24 00:10:40 +04:00
|
|
|
|
2009-04-09 00:52:37 +04:00
|
|
|
nsFlowAreaRect
|
2009-04-09 00:52:36 +04:00
|
|
|
nsBlockReflowState::GetFloatAvailableSpaceWithState(
|
2010-08-06 08:59:18 +04:00
|
|
|
nscoord aY,
|
2009-04-09 00:52:37 +04:00
|
|
|
nsFloatManager::SavedState *aState) const
|
2001-05-01 08:22:57 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Verify that the caller setup the coordinate system properly
|
|
|
|
nscoord wx, wy;
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->GetTranslation(wx, wy);
|
|
|
|
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
|
2001-05-01 08:22:57 +04:00
|
|
|
"bad coord system");
|
|
|
|
#endif
|
|
|
|
|
2009-04-09 00:52:37 +04:00
|
|
|
nsFlowAreaRect result =
|
2009-05-20 15:21:34 +04:00
|
|
|
mFloatManager->GetFlowArea(aY - BorderPadding().top,
|
|
|
|
nsFloatManager::BAND_FROM_POINT,
|
2010-08-06 08:59:18 +04:00
|
|
|
mContentArea.height, mContentArea.width,
|
|
|
|
aState);
|
2009-02-05 00:24:17 +03:00
|
|
|
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
2009-04-09 00:52:37 +04:00
|
|
|
if (result.mRect.width < 0)
|
|
|
|
result.mRect.width = 0;
|
2001-05-01 08:22:57 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (nsBlockFrame::gNoisyReflow) {
|
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
2009-01-05 03:39:54 +03:00
|
|
|
printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
|
2009-04-09 00:52:37 +04:00
|
|
|
result.mRect.x, result.mRect.y, result.mRect.width,
|
|
|
|
result.mRect.height, result.mHasFloats);
|
2001-05-01 08:22:57 +04:00
|
|
|
}
|
|
|
|
#endif
|
2009-04-09 00:52:37 +04:00
|
|
|
return result;
|
2001-05-01 08:22:57 +04:00
|
|
|
}
|
|
|
|
|
2009-05-20 15:21:34 +04:00
|
|
|
nsFlowAreaRect
|
|
|
|
nsBlockReflowState::GetFloatAvailableSpaceForHeight(
|
|
|
|
nscoord aY, nscoord aHeight,
|
|
|
|
nsFloatManager::SavedState *aState) const
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Verify that the caller setup the coordinate system properly
|
|
|
|
nscoord wx, wy;
|
|
|
|
mFloatManager->GetTranslation(wx, wy);
|
|
|
|
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
|
|
|
|
"bad coord system");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsFlowAreaRect result =
|
|
|
|
mFloatManager->GetFlowArea(aY - BorderPadding().top,
|
|
|
|
nsFloatManager::WIDTH_WITHIN_HEIGHT,
|
|
|
|
aHeight, mContentArea.width, aState);
|
|
|
|
// Keep the width >= 0 for compatibility with nsSpaceManager.
|
|
|
|
if (result.mRect.width < 0)
|
|
|
|
result.mRect.width = 0;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (nsBlockFrame::gNoisyReflow) {
|
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
|
|
|
printf("GetAvailableSpaceForHeight: space=%d,%d,%d,%d hasfloats=%d\n",
|
|
|
|
result.mRect.x, result.mRect.y, result.mRect.width,
|
|
|
|
result.mRect.height, result.mHasFloats);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2001-10-25 05:08:40 +04:00
|
|
|
/*
|
|
|
|
* Reconstruct the vertical margin before the line |aLine| in order to
|
|
|
|
* do an incremental reflow that begins with |aLine| without reflowing
|
|
|
|
* the line before it. |aLine| may point to the fencepost at the end of
|
|
|
|
* the line list, and it is used this way since we (for now, anyway)
|
|
|
|
* always need to recover margins at the end of a block.
|
|
|
|
*
|
|
|
|
* The reconstruction involves walking backward through the line list to
|
|
|
|
* find any collapsed margins preceding the line that would have been in
|
|
|
|
* the reflow state's |mPrevBottomMargin| when we reflowed that line in
|
|
|
|
* a full reflow (under the rule in CSS2 that all adjacent vertical
|
|
|
|
* margins of blocks collapse).
|
|
|
|
*/
|
1999-04-03 22:59:01 +04:00
|
|
|
void
|
2001-10-25 05:08:40 +04:00
|
|
|
nsBlockReflowState::ReconstructMarginAbove(nsLineList::iterator aLine)
|
1999-04-03 22:59:01 +04:00
|
|
|
{
|
2001-10-25 05:08:40 +04:00
|
|
|
mPrevBottomMargin.Zero();
|
|
|
|
nsBlockFrame *block = mBlock;
|
|
|
|
|
|
|
|
nsLineList::iterator firstLine = block->begin_lines();
|
|
|
|
for (;;) {
|
|
|
|
--aLine;
|
|
|
|
if (aLine->IsBlock()) {
|
|
|
|
mPrevBottomMargin = aLine->GetCarriedOutBottomMargin();
|
|
|
|
break;
|
|
|
|
}
|
2003-11-11 02:36:06 +03:00
|
|
|
if (!aLine->IsEmpty()) {
|
2001-10-25 05:08:40 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (aLine == firstLine) {
|
|
|
|
// If the top margin was carried out (and thus already applied),
|
|
|
|
// set it to zero. Either way, we're done.
|
2007-02-19 02:53:25 +03:00
|
|
|
if (!GetFlag(BRS_ISTOPMARGINROOT)) {
|
2001-10-25 05:08:40 +04:00
|
|
|
mPrevBottomMargin.Zero();
|
|
|
|
}
|
|
|
|
break;
|
1999-04-03 22:59:01 +04:00
|
|
|
}
|
1998-12-05 19:02:08 +03:00
|
|
|
}
|
1999-04-03 22:59:01 +04:00
|
|
|
}
|
|
|
|
|
2009-08-31 22:25:36 +04:00
|
|
|
void
|
|
|
|
nsBlockReflowState::SetupFloatContinuationList()
|
|
|
|
{
|
|
|
|
if (!GetFlag(BRS_PROPTABLE_FLOATCLIST)) {
|
2010-03-29 05:46:55 +04:00
|
|
|
mPresContext->PropertyTable()->
|
|
|
|
Set(mBlock, nsBlockFrame::FloatContinuationProperty(),
|
|
|
|
&mFloatContinuations);
|
2009-08-31 22:25:36 +04:00
|
|
|
SetFlag(BRS_PROPTABLE_FLOATCLIST, PR_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-01-06 21:14:00 +03:00
|
|
|
/**
|
2009-01-05 03:39:54 +03:00
|
|
|
* Restore information about floats into the float manager for an
|
2003-10-14 01:51:02 +04:00
|
|
|
* incremental reflow, and simultaneously push the floats by
|
2002-01-06 21:14:00 +03:00
|
|
|
* |aDeltaY|, which is the amount |aLine| was pushed relative to its
|
|
|
|
* parent. The recovery of state is one of the things that makes
|
|
|
|
* incremental reflow O(N^2) and this state should really be kept
|
|
|
|
* around, attached to the frame tree.
|
|
|
|
*/
|
2001-11-15 10:28:46 +03:00
|
|
|
void
|
2003-10-14 01:51:02 +04:00
|
|
|
nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
|
|
|
nscoord aDeltaY)
|
2001-11-15 10:28:46 +03:00
|
|
|
{
|
2003-10-14 01:51:02 +04:00
|
|
|
if (aLine->HasFloats()) {
|
|
|
|
// Place the floats into the space-manager again. Also slide
|
2001-11-15 10:28:46 +03:00
|
|
|
// them, just like the regular frames on the line.
|
2003-10-14 01:51:02 +04:00
|
|
|
nsFloatCache* fc = aLine->GetFirstFloat();
|
2001-11-15 10:28:46 +03:00
|
|
|
while (fc) {
|
2009-08-31 22:25:35 +04:00
|
|
|
nsIFrame* floatFrame = fc->mFloat;
|
2002-01-06 21:14:00 +03:00
|
|
|
if (aDeltaY != 0) {
|
2003-10-14 01:51:02 +04:00
|
|
|
nsPoint p = floatFrame->GetPosition();
|
|
|
|
floatFrame->SetPosition(nsPoint(p.x, p.y + aDeltaY));
|
2007-07-02 09:19:57 +04:00
|
|
|
nsContainerFrame::PositionFrameView(floatFrame);
|
|
|
|
nsContainerFrame::PositionChildViews(floatFrame);
|
2002-01-06 21:14:00 +03:00
|
|
|
}
|
2001-11-15 10:28:46 +03:00
|
|
|
#ifdef DEBUG
|
2009-01-05 03:39:54 +03:00
|
|
|
if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
|
2001-11-15 10:28:46 +03:00
|
|
|
nscoord tx, ty;
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->GetTranslation(tx, ty);
|
2001-11-15 10:28:46 +03:00
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
2003-10-14 01:51:02 +04:00
|
|
|
printf("RecoverFloats: txy=%d,%d (%d,%d) ",
|
2009-01-05 03:39:54 +03:00
|
|
|
tx, ty, mFloatManagerX, mFloatManagerY);
|
2003-10-14 01:51:02 +04:00
|
|
|
nsFrame::ListTag(stdout, floatFrame);
|
2009-07-15 09:19:31 +04:00
|
|
|
nsRect region = nsFloatManager::GetRegionFor(floatFrame);
|
2002-01-06 21:14:00 +03:00
|
|
|
printf(" aDeltaY=%d region={%d,%d,%d,%d}\n",
|
2009-07-15 09:19:31 +04:00
|
|
|
aDeltaY, region.x, region.y, region.width, region.height);
|
2001-11-15 10:28:46 +03:00
|
|
|
}
|
|
|
|
#endif
|
2009-07-15 09:19:31 +04:00
|
|
|
mFloatManager->AddFloat(floatFrame,
|
|
|
|
nsFloatManager::GetRegionFor(floatFrame));
|
2001-11-15 10:28:46 +03:00
|
|
|
fc = fc->Next();
|
|
|
|
}
|
|
|
|
} else if (aLine->IsBlock()) {
|
2009-08-31 22:25:36 +04:00
|
|
|
nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager);
|
2001-11-15 10:28:46 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-03 08:18:39 +03:00
|
|
|
/**
|
|
|
|
* Everything done in this function is done O(N) times for each pass of
|
|
|
|
* reflow so it is O(N*M) where M is the number of incremental reflow
|
|
|
|
* passes. That's bad. Don't do stuff here.
|
|
|
|
*
|
|
|
|
* When this function is called, |aLine| has just been slid by |aDeltaY|
|
|
|
|
* and the purpose of RecoverStateFrom is to ensure that the
|
|
|
|
* nsBlockReflowState is in the same state that it would have been in
|
|
|
|
* had the line just been reflowed.
|
|
|
|
*
|
2003-10-14 01:51:02 +04:00
|
|
|
* Most of the state recovery that we have to do involves floats.
|
2001-11-03 08:18:39 +03:00
|
|
|
*/
|
1999-04-03 22:59:01 +04:00
|
|
|
void
|
2001-10-25 05:08:40 +04:00
|
|
|
nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
|
|
|
|
nscoord aDeltaY)
|
1999-04-03 22:59:01 +04:00
|
|
|
{
|
|
|
|
// Make the line being recovered the current line
|
|
|
|
mCurrentLine = aLine;
|
|
|
|
|
2009-01-05 03:39:54 +03:00
|
|
|
// Place floats for this line into the float manager
|
2003-10-14 01:51:02 +04:00
|
|
|
if (aLine->HasFloats() || aLine->IsBlock()) {
|
|
|
|
// Undo border/padding translation since the nsFloatCache's
|
1999-09-16 23:56:36 +04:00
|
|
|
// coordinates are relative to the frame not relative to the
|
|
|
|
// border/padding.
|
|
|
|
const nsMargin& bp = BorderPadding();
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->Translate(-bp.left, -bp.top);
|
1999-09-16 23:56:36 +04:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
RecoverFloats(aLine, aDeltaY);
|
2001-11-15 10:28:46 +03:00
|
|
|
|
2000-03-23 02:19:10 +03:00
|
|
|
#ifdef DEBUG
|
2009-01-05 03:39:54 +03:00
|
|
|
if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
|
|
|
|
mFloatManager->List(stdout);
|
2000-03-23 02:19:10 +03:00
|
|
|
}
|
|
|
|
#endif
|
1999-09-16 23:56:36 +04:00
|
|
|
// And then put the translation back again
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->Translate(bp.left, bp.top);
|
1999-04-03 22:59:01 +04:00
|
|
|
}
|
1998-12-05 19:02:08 +03:00
|
|
|
}
|
1998-09-24 00:10:40 +04:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// This is called by the line layout's AddFloat method when a
|
|
|
|
// place-holder frame is reflowed in a line. If the float is a
|
1998-12-05 19:02:08 +03:00
|
|
|
// left-most child (it's x coordinate is at the line's left margin)
|
2003-10-14 01:51:02 +04:00
|
|
|
// then the float is place immediately, otherwise the float
|
1998-12-05 19:02:08 +03:00
|
|
|
// placement is deferred until the line has been reflowed.
|
2001-07-04 06:00:05 +04:00
|
|
|
|
|
|
|
// XXXldb This behavior doesn't quite fit with CSS1 and CSS2 --
|
|
|
|
// technically we're supposed let the current line flow around the
|
|
|
|
// float as well unless it won't fit next to what we already have.
|
|
|
|
// But nobody else implements it that way...
|
2005-03-23 06:35:08 +03:00
|
|
|
PRBool
|
2009-08-31 22:25:36 +04:00
|
|
|
nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
|
2009-08-31 22:25:35 +04:00
|
|
|
nsIFrame* aFloat,
|
2008-06-11 03:53:22 +04:00
|
|
|
nscoord aAvailableWidth,
|
2003-10-14 01:51:02 +04:00
|
|
|
nsReflowStatus& aReflowStatus)
|
1998-12-05 19:02:08 +03:00
|
|
|
{
|
2009-08-31 22:25:36 +04:00
|
|
|
NS_PRECONDITION(!aLineLayout || mBlock->end_lines() != mCurrentLine, "null ptr");
|
2009-08-31 22:25:35 +04:00
|
|
|
NS_PRECONDITION(aFloat->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
|
|
|
|
"aFloat must be an out-of-flow frame");
|
1999-03-23 07:28:20 +03:00
|
|
|
|
2009-05-20 15:21:34 +04:00
|
|
|
// Set the geometric parent of the float
|
2009-08-31 22:25:35 +04:00
|
|
|
aFloat->SetParent(mBlock);
|
2009-05-20 15:21:34 +04:00
|
|
|
|
2002-05-29 02:50:43 +04:00
|
|
|
aReflowStatus = NS_FRAME_COMPLETE;
|
1998-09-23 06:25:26 +04:00
|
|
|
|
2009-04-09 00:52:36 +04:00
|
|
|
// Because we are in the middle of reflowing a placeholder frame
|
|
|
|
// within a line (and possibly nested in an inline frame or two
|
|
|
|
// that's a child of our block) we need to restore the space
|
|
|
|
// manager's translation to the space that the block resides in
|
|
|
|
// before placing the float.
|
|
|
|
nscoord ox, oy;
|
|
|
|
mFloatManager->GetTranslation(ox, oy);
|
|
|
|
nscoord dx = ox - mFloatManagerX;
|
|
|
|
nscoord dy = oy - mFloatManagerY;
|
|
|
|
mFloatManager->Translate(-dx, -dy);
|
|
|
|
|
2005-03-23 06:35:08 +03:00
|
|
|
PRBool placed;
|
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// Now place the float immediately if possible. Otherwise stash it
|
|
|
|
// away in mPendingFloats and place it later.
|
2008-06-11 03:53:22 +04:00
|
|
|
// If one or more floats has already been pushed to the next line,
|
|
|
|
// don't let this one go on the current line, since that would violate
|
|
|
|
// float ordering.
|
2009-04-09 00:52:37 +04:00
|
|
|
nsRect floatAvailableSpace = GetFloatAvailableSpace().mRect;
|
2009-08-31 22:25:36 +04:00
|
|
|
if (!aLineLayout ||
|
|
|
|
(mBelowCurrentLineFloats.IsEmpty() &&
|
|
|
|
(aLineLayout->LineIsEmpty() ||
|
|
|
|
mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aFloat)
|
|
|
|
<= aAvailableWidth))) {
|
2010-08-06 08:59:18 +04:00
|
|
|
nsFloatManager::SavedState floatManagerState;
|
|
|
|
mFloatManager->PushState(&floatManagerState);
|
|
|
|
|
1999-09-15 04:28:10 +04:00
|
|
|
// And then place it
|
2010-08-06 08:59:18 +04:00
|
|
|
placed = FlowAndPlaceFloat(aFloat, aReflowStatus);
|
|
|
|
if (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus)) {
|
2005-03-23 06:35:08 +03:00
|
|
|
// Pass on updated available space to the current inline reflow engine
|
2010-08-06 08:59:18 +04:00
|
|
|
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
|
2009-04-09 00:52:37 +04:00
|
|
|
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
|
|
|
|
mY),
|
|
|
|
floatAvailSpace.mRect.Size());
|
2009-08-31 22:25:36 +04:00
|
|
|
if (aLineLayout) {
|
|
|
|
aLineLayout->UpdateBand(availSpace, aFloat);
|
|
|
|
// Record this float in the current-line list
|
|
|
|
mCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
|
|
|
|
}
|
2005-03-23 06:35:08 +03:00
|
|
|
}
|
2005-10-22 02:23:28 +04:00
|
|
|
else {
|
2010-08-06 08:59:18 +04:00
|
|
|
if (placed) {
|
|
|
|
mFloatManager->PopState(&floatManagerState);
|
|
|
|
} else {
|
|
|
|
mFloatManager->AssertStateMatches(&floatManagerState);
|
|
|
|
}
|
2007-06-27 20:35:31 +04:00
|
|
|
if (IsAdjacentWithTop()) {
|
|
|
|
// Pushing the line to the next page won't give us any more space;
|
|
|
|
// therefore, we break.
|
2009-08-31 22:25:36 +04:00
|
|
|
NS_ASSERTION(aLineLayout->LineIsBreakable(),
|
2007-06-27 20:35:31 +04:00
|
|
|
"We can't get here unless forceFit is false");
|
|
|
|
aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
|
|
|
} else {
|
|
|
|
// Make sure we propagate the truncated status; this signals the
|
|
|
|
// block to push the line to the next page.
|
|
|
|
aReflowStatus |= NS_FRAME_TRUNCATED;
|
|
|
|
}
|
2005-10-22 02:23:28 +04:00
|
|
|
}
|
1998-09-15 04:19:49 +04:00
|
|
|
}
|
1998-12-05 19:02:08 +03:00
|
|
|
else {
|
2007-06-27 20:35:31 +04:00
|
|
|
// Always claim to be placed; we don't know whether we fit yet, so we
|
|
|
|
// deal with this in PlaceBelowCurrentLineFloats
|
|
|
|
placed = PR_TRUE;
|
2003-10-14 01:51:02 +04:00
|
|
|
// This float will be placed after the line is done (it is a
|
|
|
|
// below-current-line float).
|
2009-08-31 22:25:36 +04:00
|
|
|
mBelowCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
|
1998-09-15 04:19:49 +04:00
|
|
|
}
|
2009-04-09 00:52:36 +04:00
|
|
|
|
|
|
|
// Restore coordinate system
|
|
|
|
mFloatManager->Translate(dx, dy);
|
|
|
|
|
2005-03-23 06:35:08 +03:00
|
|
|
return placed;
|
1998-12-05 19:02:08 +03:00
|
|
|
}
|
1998-09-15 04:19:49 +04:00
|
|
|
|
1999-03-31 08:10:27 +04:00
|
|
|
PRBool
|
2010-08-06 08:59:18 +04:00
|
|
|
nsBlockReflowState::CanPlaceFloat(nscoord aFloatWidth,
|
2010-08-06 08:59:18 +04:00
|
|
|
const nsFlowAreaRect& aFloatAvailableSpace)
|
1999-03-31 08:10:27 +04:00
|
|
|
{
|
2010-08-06 08:59:18 +04:00
|
|
|
// A float fits at a given vertical position if there are no floats at
|
|
|
|
// its horizontal position (no matter what its width) or if its width
|
|
|
|
// fits in the space remaining after prior floats have been placed.
|
|
|
|
// FIXME: We should allow overflow by up to half a pixel here (bug 21193).
|
|
|
|
return !aFloatAvailableSpace.mHasFloats ||
|
|
|
|
aFloatAvailableSpace.mRect.width >= aFloatWidth;
|
1999-03-31 08:10:27 +04:00
|
|
|
}
|
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
static nscoord
|
|
|
|
FloatMarginWidth(const nsHTMLReflowState& aCBReflowState,
|
|
|
|
nscoord aFloatAvailableWidth,
|
|
|
|
nsIFrame *aFloat,
|
|
|
|
const nsCSSOffsetState& aFloatOffsetState)
|
|
|
|
{
|
|
|
|
return aFloat->ComputeSize(
|
|
|
|
aCBReflowState.rendContext,
|
|
|
|
nsSize(aCBReflowState.ComputedWidth(),
|
|
|
|
aCBReflowState.ComputedHeight()),
|
|
|
|
aFloatAvailableWidth,
|
|
|
|
nsSize(aFloatOffsetState.mComputedMargin.LeftRight(),
|
|
|
|
aFloatOffsetState.mComputedMargin.TopBottom()),
|
|
|
|
nsSize(aFloatOffsetState.mComputedBorderPadding.LeftRight() -
|
|
|
|
aFloatOffsetState.mComputedPadding.LeftRight(),
|
|
|
|
aFloatOffsetState.mComputedBorderPadding.TopBottom() -
|
|
|
|
aFloatOffsetState.mComputedPadding.TopBottom()),
|
|
|
|
nsSize(aFloatOffsetState.mComputedPadding.LeftRight(),
|
|
|
|
aFloatOffsetState.mComputedPadding.TopBottom()),
|
|
|
|
PR_TRUE).width +
|
|
|
|
aFloatOffsetState.mComputedMargin.LeftRight() +
|
|
|
|
aFloatOffsetState.mComputedBorderPadding.LeftRight();
|
|
|
|
}
|
|
|
|
|
2005-03-23 06:35:08 +03:00
|
|
|
PRBool
|
2009-08-31 22:25:35 +04:00
|
|
|
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
2010-08-06 08:59:18 +04:00
|
|
|
nsReflowStatus& aReflowStatus)
|
1998-09-15 04:19:49 +04:00
|
|
|
{
|
2002-05-29 02:50:43 +04:00
|
|
|
aReflowStatus = NS_FRAME_COMPLETE;
|
2003-10-14 01:51:02 +04:00
|
|
|
// Save away the Y coordinate before placing the float. We will
|
|
|
|
// restore mY at the end after placing the float. This is
|
|
|
|
// necessary because any adjustments to mY during the float
|
|
|
|
// placement are for the float only, not for any non-floating
|
1998-12-12 22:19:11 +03:00
|
|
|
// content.
|
2010-08-06 08:59:19 +04:00
|
|
|
AutoRestore<nscoord> restoreY(mY);
|
|
|
|
// FIXME: Should give AutoRestore a getter for the value to avoid this.
|
|
|
|
const nscoord saveY = mY;
|
2001-05-22 03:03:46 +04:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// Grab the float's display information
|
2009-08-31 22:25:35 +04:00
|
|
|
const nsStyleDisplay* floatDisplay = aFloat->GetStyleDisplay();
|
1998-12-05 19:02:08 +03:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// The float's old region, so we can propagate damage.
|
2009-08-31 22:25:35 +04:00
|
|
|
nsRect oldRegion = nsFloatManager::GetRegionFor(aFloat);
|
2002-04-26 23:19:39 +04:00
|
|
|
|
2003-03-12 02:56:49 +03:00
|
|
|
// Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
|
2001-05-22 03:03:46 +04:00
|
|
|
// ``above'' another float that preceded it in the flow.
|
2009-01-05 03:39:54 +03:00
|
|
|
mY = NS_MAX(mFloatManager->GetLowestFloatTop() + BorderPadding().top, mY);
|
2001-05-22 03:03:46 +04:00
|
|
|
|
2005-11-21 01:05:24 +03:00
|
|
|
// See if the float should clear any preceding floats...
|
2007-06-17 00:27:46 +04:00
|
|
|
// XXX We need to mark this float somehow so that it gets reflowed
|
|
|
|
// when floats are inserted before it.
|
2003-10-14 01:51:02 +04:00
|
|
|
if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
|
2001-07-19 06:33:43 +04:00
|
|
|
// XXXldb Does this handle vertical margins correctly?
|
2004-11-25 17:51:00 +03:00
|
|
|
mY = ClearFloats(mY, floatDisplay->mBreakType);
|
2001-07-19 06:33:43 +04:00
|
|
|
}
|
|
|
|
// Get the band of available space
|
2010-08-06 08:59:18 +04:00
|
|
|
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
|
2010-08-06 08:59:18 +04:00
|
|
|
nsRect adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
|
|
|
floatAvailableSpace.mRect, aFloat);
|
2001-05-22 03:03:46 +04:00
|
|
|
|
2009-08-31 22:25:35 +04:00
|
|
|
NS_ASSERTION(aFloat->GetParent() == mBlock,
|
2004-09-13 17:35:46 +04:00
|
|
|
"Float frame has wrong parent");
|
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
nsCSSOffsetState offsets(aFloat, mReflowState.rendContext,
|
|
|
|
mReflowState.ComputedWidth());
|
2001-05-22 03:03:46 +04:00
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
nscoord floatMarginWidth = FloatMarginWidth(mReflowState,
|
|
|
|
adjustedAvailableSpace.width,
|
|
|
|
aFloat, offsets);
|
2001-07-19 06:33:43 +04:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// Find a place to place the float. The CSS2 spec doesn't want
|
|
|
|
// floats overlapping each other or sticking out of the containing
|
2001-07-19 06:33:43 +04:00
|
|
|
// block if possible (CSS2 spec section 9.5.1, see the rule list).
|
2003-10-14 01:51:02 +04:00
|
|
|
NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) ||
|
|
|
|
(NS_STYLE_FLOAT_RIGHT == floatDisplay->mFloats),
|
2001-07-19 06:33:43 +04:00
|
|
|
"invalid float type");
|
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// Can the float fit here?
|
|
|
|
PRBool keepFloatOnSameLine = PR_FALSE;
|
2002-03-08 23:25:54 +03:00
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
for (;;) {
|
2009-04-09 00:52:37 +04:00
|
|
|
if (floatAvailableSpace.mRect.height <= 0) {
|
2005-03-23 06:35:08 +03:00
|
|
|
// No space, nowhere to put anything.
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
if (CanPlaceFloat(floatMarginWidth, floatAvailableSpace)) {
|
2010-08-06 08:59:18 +04:00
|
|
|
// We found an appropriate place.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-03-08 23:25:54 +03:00
|
|
|
// Nope. try to advance to the next band.
|
2003-10-14 01:51:02 +04:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
|
2003-12-25 00:51:50 +03:00
|
|
|
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
2002-03-08 23:25:54 +03:00
|
|
|
|
2009-04-09 00:52:37 +04:00
|
|
|
mY += floatAvailableSpace.mRect.height;
|
2010-08-06 08:59:18 +04:00
|
|
|
if (adjustedAvailableSpace.height != NS_UNCONSTRAINEDSIZE) {
|
|
|
|
adjustedAvailableSpace.height -= floatAvailableSpace.mRect.height;
|
|
|
|
}
|
2010-08-06 08:59:18 +04:00
|
|
|
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
2002-03-08 23:25:54 +03:00
|
|
|
} else {
|
2010-08-06 08:59:18 +04:00
|
|
|
// This quirk matches the one in nsBlockFrame::AdjustFloatAvailableSpace
|
2003-10-14 01:51:02 +04:00
|
|
|
// IE handles float tables in a very special way
|
2002-03-08 23:25:54 +03:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// see if the previous float is also a table and has "align"
|
|
|
|
nsFloatCache* fc = mCurrentLineFloats.Head();
|
2002-03-08 23:25:54 +03:00
|
|
|
nsIFrame* prevFrame = nsnull;
|
|
|
|
while (fc) {
|
2009-08-31 22:25:35 +04:00
|
|
|
if (fc->mFloat == aFloat) {
|
2002-03-08 23:25:54 +03:00
|
|
|
break;
|
|
|
|
}
|
2009-08-31 22:25:35 +04:00
|
|
|
prevFrame = fc->mFloat;
|
2002-03-08 23:25:54 +03:00
|
|
|
fc = fc->Next();
|
|
|
|
}
|
|
|
|
|
2002-03-09 00:23:55 +03:00
|
|
|
if(prevFrame) {
|
|
|
|
//get the frame type
|
2006-12-26 20:47:52 +03:00
|
|
|
if (nsGkAtoms::tableOuterFrame == prevFrame->GetType()) {
|
2002-03-09 00:23:55 +03:00
|
|
|
//see if it has "align="
|
|
|
|
// IE makes a difference between align and he float property
|
2003-06-27 22:13:48 +04:00
|
|
|
nsIContent* content = prevFrame->GetContent();
|
2002-03-09 00:23:55 +03:00
|
|
|
if (content) {
|
2005-10-28 15:25:24 +04:00
|
|
|
// we're interested only if previous frame is align=left
|
|
|
|
// IE messes things up when "right" (overlapping frames)
|
2006-12-26 20:47:52 +03:00
|
|
|
if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::align,
|
2005-10-28 15:25:24 +04:00
|
|
|
NS_LITERAL_STRING("left"), eIgnoreCase)) {
|
|
|
|
keepFloatOnSameLine = PR_TRUE;
|
|
|
|
// don't advance to next line (IE quirkie behaviour)
|
|
|
|
// it breaks rule CSS2/9.5.1/1, but what the hell
|
|
|
|
// since we cannot evangelize the world
|
|
|
|
break;
|
2002-03-08 23:25:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-11-15 00:01:26 +03:00
|
|
|
|
2002-03-08 23:25:54 +03:00
|
|
|
// the table does not fit anymore in this line so advance to next band
|
2009-04-09 00:52:37 +04:00
|
|
|
mY += floatAvailableSpace.mRect.height;
|
2010-08-06 08:59:18 +04:00
|
|
|
// To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
|
|
|
|
// get a new width for the new band.
|
2010-08-06 08:59:18 +04:00
|
|
|
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
2010-08-06 08:59:18 +04:00
|
|
|
adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
|
|
|
floatAvailableSpace.mRect, aFloat);
|
|
|
|
floatMarginWidth = FloatMarginWidth(mReflowState,
|
|
|
|
adjustedAvailableSpace.width,
|
|
|
|
aFloat, offsets);
|
2002-03-08 23:25:54 +03:00
|
|
|
}
|
|
|
|
}
|
2010-08-06 08:59:18 +04:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// If the float is continued, it will get the same absolute x value as its prev-in-flow
|
2005-03-23 06:35:08 +03:00
|
|
|
|
|
|
|
// We don't worry about the geometry of the prev in flow, let the continuation
|
|
|
|
// place and size itself as required.
|
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// Assign an x and y coordinate to the float. Note that the x,y
|
1998-12-05 19:02:08 +03:00
|
|
|
// 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.
|
2005-03-07 05:30:14 +03:00
|
|
|
nscoord floatX, floatY;
|
2003-10-14 01:51:02 +04:00
|
|
|
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
|
2009-04-09 00:52:37 +04:00
|
|
|
floatX = floatAvailableSpace.mRect.x;
|
1998-09-15 04:19:49 +04:00
|
|
|
}
|
|
|
|
else {
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
if (!keepFloatOnSameLine) {
|
2010-08-06 08:59:18 +04:00
|
|
|
floatX = floatAvailableSpace.mRect.XMost() - floatMarginWidth;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2000-04-17 18:40:46 +04:00
|
|
|
else {
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// this is the IE quirk (see few lines above)
|
|
|
|
// the table is kept in the same line: don't let it overlap the
|
|
|
|
// previous float
|
2009-04-09 00:52:37 +04:00
|
|
|
floatX = floatAvailableSpace.mRect.x;
|
2000-04-17 18:40:46 +04:00
|
|
|
}
|
1998-09-15 04:19:49 +04:00
|
|
|
}
|
1999-03-05 07:21:32 +03:00
|
|
|
const nsMargin& borderPadding = BorderPadding();
|
2005-03-07 05:30:14 +03:00
|
|
|
floatY = mY - borderPadding.top;
|
|
|
|
if (floatY < 0) {
|
2001-07-04 06:00:05 +04:00
|
|
|
// CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
|
|
|
|
// be higher than the top of its containing block." (Since the
|
|
|
|
// containing block is the content edge of the block box, this
|
2003-10-14 01:51:02 +04:00
|
|
|
// means the margin edge of the float can't be higher than the
|
2001-07-04 06:00:05 +04:00
|
|
|
// content edge of the block that contains it.)
|
2005-03-07 05:30:14 +03:00
|
|
|
floatY = 0;
|
1998-09-15 04:19:49 +04:00
|
|
|
}
|
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
// Reflow the float after computing its vertical position so it knows
|
|
|
|
// where to break.
|
|
|
|
nsMargin floatMargin; // computed margin
|
2010-08-06 08:59:19 +04:00
|
|
|
PRBool pushedDown = mY != saveY;
|
2010-08-06 08:59:18 +04:00
|
|
|
mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat,
|
2010-08-06 08:59:19 +04:00
|
|
|
floatMargin, pushedDown, aReflowStatus);
|
2010-08-06 08:59:18 +04:00
|
|
|
if (aFloat->GetPrevInFlow())
|
|
|
|
floatMargin.top = 0;
|
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
|
|
|
|
floatMargin.bottom = 0;
|
|
|
|
|
2010-08-06 08:59:19 +04:00
|
|
|
// In the case that we're in columns and not splitting floats, we need
|
|
|
|
// to check here that the float's height fit, and if it didn't, bail.
|
|
|
|
// (This code is only for DISABLE_FLOAT_BREAKING_IN_COLUMNS .)
|
|
|
|
if (mContentArea.height != NS_UNCONSTRAINEDSIZE &&
|
|
|
|
adjustedAvailableSpace.height == NS_UNCONSTRAINEDSIZE &&
|
|
|
|
(!mReflowState.mFlags.mIsTopOfPage || !IsAdjacentWithTop() ||
|
|
|
|
pushedDown) &&
|
|
|
|
aFloat->GetSize().height + floatMargin.TopBottom() >
|
|
|
|
mContentArea.height - floatY) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-07-15 09:19:31 +04:00
|
|
|
// Calculate the actual origin of the float frame's border rect
|
|
|
|
// relative to the parent block; floatX/Y must be converted from space-manager
|
|
|
|
// coordinates to parent coordinates, and the margin must be added in
|
|
|
|
// to get the border rect
|
|
|
|
nsPoint origin(borderPadding.left + floatMargin.left + floatX,
|
|
|
|
borderPadding.top + floatMargin.top + floatY);
|
|
|
|
|
|
|
|
// If float is relatively positioned, factor that in as well
|
2009-08-31 22:25:35 +04:00
|
|
|
origin += aFloat->GetRelativeOffset(floatDisplay);
|
2009-07-15 09:19:31 +04:00
|
|
|
|
|
|
|
// Position the float and make sure and views are properly
|
|
|
|
// positioned. We need to explicitly position its child views as
|
|
|
|
// well, since we're moving the float after flowing it.
|
2009-08-31 22:25:35 +04:00
|
|
|
aFloat->SetPosition(origin);
|
|
|
|
nsContainerFrame::PositionFrameView(aFloat);
|
|
|
|
nsContainerFrame::PositionChildViews(aFloat);
|
2009-07-15 09:19:31 +04:00
|
|
|
|
|
|
|
// Update the float combined area state
|
2009-08-31 22:25:35 +04:00
|
|
|
nsRect combinedArea = aFloat->GetOverflowRect() + origin;
|
2009-07-15 09:19:31 +04:00
|
|
|
|
|
|
|
// XXX Floats should really just get invalidated here if necessary
|
|
|
|
mFloatCombinedArea.UnionRect(combinedArea, mFloatCombinedArea);
|
|
|
|
|
2009-01-05 03:39:54 +03:00
|
|
|
// Place the float in the float manager
|
2009-07-15 09:19:31 +04:00
|
|
|
// calculate region
|
2009-08-31 22:25:35 +04:00
|
|
|
nsRect region = nsFloatManager::CalculateRegionFor(aFloat, floatMargin);
|
2009-07-15 09:19:31 +04:00
|
|
|
// if the float split, then take up all of the vertical height
|
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
|
2002-12-19 03:12:08 +03:00
|
|
|
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
|
2009-09-16 19:01:36 +04:00
|
|
|
region.height = NS_MAX(region.height, mContentArea.height - floatY);
|
2005-11-01 04:16:45 +03:00
|
|
|
}
|
2002-12-19 03:12:08 +03:00
|
|
|
nsresult rv =
|
2009-07-15 09:19:31 +04:00
|
|
|
// spacemanager translation is inset by the border+padding.
|
2009-08-31 22:25:35 +04:00
|
|
|
mFloatManager->AddFloat(aFloat,
|
2009-07-15 09:19:31 +04:00
|
|
|
region - nsPoint(borderPadding.left, borderPadding.top));
|
2003-10-14 01:51:02 +04:00
|
|
|
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
|
2009-07-15 09:19:31 +04:00
|
|
|
// store region
|
2009-08-31 22:25:35 +04:00
|
|
|
rv = nsFloatManager::StoreRegionFor(aFloat, region);
|
2009-07-15 09:19:31 +04:00
|
|
|
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "float region storage failed");
|
2007-06-17 00:27:46 +04:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
// If the float's dimensions have changed, note the damage in the
|
2009-01-05 03:39:54 +03:00
|
|
|
// float manager.
|
2009-07-15 09:19:31 +04:00
|
|
|
if (region != oldRegion) {
|
2002-04-26 23:19:39 +04:00
|
|
|
// XXXwaterson conservative: we could probably get away with noting
|
|
|
|
// less damage; e.g., if only height has changed, then only note the
|
|
|
|
// area into which the float has grown or from which the float has
|
|
|
|
// shrunk.
|
2009-07-15 09:19:31 +04:00
|
|
|
nscoord top = NS_MIN(region.y, oldRegion.y) - borderPadding.top;
|
2010-04-05 01:46:15 +04:00
|
|
|
nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost()) - borderPadding.top;
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->IncludeInDamage(top, bottom);
|
2002-04-26 23:19:39 +04:00
|
|
|
}
|
|
|
|
|
2009-01-05 03:39:54 +03:00
|
|
|
#ifdef NOISY_FLOATMANAGER
|
1999-09-15 04:28:10 +04:00
|
|
|
nscoord tx, ty;
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->GetTranslation(tx, ty);
|
1999-09-15 04:28:10 +04:00
|
|
|
nsFrame::ListTag(stdout, mBlock);
|
2009-01-05 03:39:54 +03:00
|
|
|
printf(": FlowAndPlaceFloat: AddFloat: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
|
2009-01-05 03:39:54 +03:00
|
|
|
tx, ty, mFloatManagerX, mFloatManagerY,
|
2009-07-15 09:19:31 +04:00
|
|
|
region.x, region.y, region.width, region.height);
|
1999-09-15 04:28:10 +04:00
|
|
|
#endif
|
|
|
|
|
1999-10-16 03:35:10 +04:00
|
|
|
#ifdef DEBUG
|
2001-05-01 08:22:57 +04:00
|
|
|
if (nsBlockFrame::gNoisyReflow) {
|
2009-08-31 22:25:35 +04:00
|
|
|
nsRect r = aFloat->GetRect();
|
2001-05-01 08:22:57 +04:00
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
2003-10-14 01:51:02 +04:00
|
|
|
printf("placed float: ");
|
2009-08-31 22:25:35 +04:00
|
|
|
nsFrame::ListTag(stdout, aFloat);
|
2000-10-29 02:17:53 +04:00
|
|
|
printf(" %d,%d,%d,%d\n", r.x, r.y, r.width, r.height);
|
1998-12-05 19:02:08 +03:00
|
|
|
}
|
1998-11-05 22:33:01 +03:00
|
|
|
#endif
|
2005-03-23 06:35:08 +03:00
|
|
|
|
|
|
|
return PR_TRUE;
|
1998-12-05 19:02:08 +03:00
|
|
|
}
|
1998-11-05 22:33:01 +03:00
|
|
|
|
1998-12-05 19:02:08 +03:00
|
|
|
/**
|
2003-10-14 01:51:02 +04:00
|
|
|
* Place below-current-line floats.
|
1998-12-05 19:02:08 +03:00
|
|
|
*/
|
2002-05-29 02:50:43 +04:00
|
|
|
PRBool
|
2010-08-06 08:59:18 +04:00
|
|
|
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList)
|
1998-12-05 19:02:08 +03:00
|
|
|
{
|
2003-10-14 01:51:02 +04:00
|
|
|
nsFloatCache* fc = aList.Head();
|
1999-09-15 04:28:10 +04:00
|
|
|
while (fc) {
|
2007-06-17 00:27:46 +04:00
|
|
|
{
|
1999-10-29 18:34:53 +04:00
|
|
|
#ifdef DEBUG
|
2001-05-01 08:22:57 +04:00
|
|
|
if (nsBlockFrame::gNoisyReflow) {
|
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
2003-10-14 01:51:02 +04:00
|
|
|
printf("placing bcl float: ");
|
2009-08-31 22:25:35 +04:00
|
|
|
nsFrame::ListTag(stdout, fc->mFloat);
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("\n");
|
1999-10-29 18:34:53 +04:00
|
|
|
}
|
|
|
|
#endif
|
2003-10-14 01:51:02 +04:00
|
|
|
// Place the float
|
2002-05-29 02:50:43 +04:00
|
|
|
nsReflowStatus reflowStatus;
|
2010-08-06 08:59:18 +04:00
|
|
|
PRBool placed = FlowAndPlaceFloat(fc->mFloat, reflowStatus);
|
2002-05-29 02:50:43 +04:00
|
|
|
|
2010-08-06 08:59:18 +04:00
|
|
|
if (!placed || NS_FRAME_IS_TRUNCATED(reflowStatus)) {
|
2003-10-14 01:51:02 +04:00
|
|
|
// return before processing all of the floats, since the line will be pushed.
|
2002-05-29 02:50:43 +04:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2009-08-31 22:25:36 +04:00
|
|
|
else if (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus)) {
|
|
|
|
// Create a continuation for the incomplete float
|
|
|
|
nsresult rv = mBlock->SplitFloat(*this, fc->mFloat, reflowStatus);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return PR_FALSE;
|
2005-03-23 06:35:08 +03:00
|
|
|
} else {
|
2007-07-05 03:38:39 +04:00
|
|
|
// XXX We could deal with truncated frames better by breaking before
|
|
|
|
// the associated placeholder
|
|
|
|
NS_WARN_IF_FALSE(!NS_FRAME_IS_TRUNCATED(reflowStatus),
|
|
|
|
"This situation currently leads to data not printing");
|
2009-08-31 22:25:35 +04:00
|
|
|
// Float is complete.
|
2002-05-29 02:50:43 +04:00
|
|
|
}
|
1999-02-09 20:31:33 +03:00
|
|
|
}
|
1999-09-15 04:28:10 +04:00
|
|
|
fc = fc->Next();
|
1999-02-09 20:31:33 +03:00
|
|
|
}
|
2002-05-29 02:50:43 +04:00
|
|
|
return PR_TRUE;
|
1999-02-09 20:31:33 +03:00
|
|
|
}
|
|
|
|
|
2004-11-25 17:51:00 +03:00
|
|
|
nscoord
|
2008-01-29 10:40:05 +03:00
|
|
|
nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
2008-05-04 03:33:36 +04:00
|
|
|
nsIFrame *aReplacedBlock)
|
1998-10-27 19:51:02 +03:00
|
|
|
{
|
1999-10-16 03:35:10 +04:00
|
|
|
#ifdef DEBUG
|
2001-05-01 08:22:57 +04:00
|
|
|
if (nsBlockFrame::gNoisyReflow) {
|
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
2004-11-25 17:51:00 +03:00
|
|
|
printf("clear floats: in: aY=%d(%d)\n",
|
|
|
|
aY, aY - BorderPadding().top);
|
1999-10-16 03:35:10 +04:00
|
|
|
}
|
1998-12-05 19:02:08 +03:00
|
|
|
#endif
|
1998-10-27 19:51:02 +03:00
|
|
|
|
2003-10-14 01:51:02 +04:00
|
|
|
#ifdef NOISY_FLOAT_CLEARING
|
|
|
|
printf("nsBlockReflowState::ClearFloats: aY=%d breakType=%d\n",
|
1999-09-16 23:56:36 +04:00
|
|
|
aY, aBreakType);
|
2009-01-05 03:39:54 +03:00
|
|
|
mFloatManager->List(stdout);
|
1999-09-16 23:56:36 +04:00
|
|
|
#endif
|
2004-06-08 23:18:30 +04:00
|
|
|
|
1999-03-05 07:21:32 +03:00
|
|
|
const nsMargin& bp = BorderPadding();
|
2008-01-29 10:40:05 +03:00
|
|
|
nscoord newY = aY;
|
|
|
|
|
|
|
|
if (aBreakType != NS_STYLE_CLEAR_NONE) {
|
2009-01-05 03:39:54 +03:00
|
|
|
newY = bp.top + mFloatManager->ClearFloats(newY - bp.top, aBreakType);
|
2008-01-29 10:40:05 +03:00
|
|
|
}
|
|
|
|
|
2008-05-04 03:33:36 +04:00
|
|
|
if (aReplacedBlock) {
|
2008-01-29 10:40:05 +03:00
|
|
|
for (;;) {
|
2010-08-06 08:59:18 +04:00
|
|
|
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newY);
|
2008-05-04 03:33:36 +04:00
|
|
|
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
|
2009-04-09 00:52:37 +04:00
|
|
|
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
|
2009-04-09 00:52:37 +04:00
|
|
|
aReplacedBlock);
|
2009-04-09 00:52:37 +04:00
|
|
|
if (!floatAvailableSpace.mHasFloats ||
|
2009-09-16 19:01:36 +04:00
|
|
|
NS_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) +
|
2008-05-04 03:33:36 +04:00
|
|
|
replacedWidth.borderBoxWidth +
|
2009-09-16 19:01:36 +04:00
|
|
|
NS_MAX(mContentArea.width -
|
|
|
|
NS_MIN(mContentArea.width,
|
2009-04-09 00:52:37 +04:00
|
|
|
floatAvailableSpace.mRect.XMost()),
|
2008-05-04 03:33:36 +04:00
|
|
|
replacedWidth.marginRight) <=
|
2008-04-15 05:05:17 +04:00
|
|
|
mContentArea.width) {
|
2008-01-29 10:40:05 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
|
2009-04-09 00:52:37 +04:00
|
|
|
if (floatAvailableSpace.mRect.height > 0) {
|
2008-01-29 10:40:05 +03:00
|
|
|
// See if there's room in the next band.
|
2009-04-09 00:52:37 +04:00
|
|
|
newY += floatAvailableSpace.mRect.height;
|
2008-01-29 10:40:05 +03:00
|
|
|
} else {
|
|
|
|
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
|
|
|
// Stop trying to clear here; we'll just get pushed to the
|
|
|
|
// next column or page and try again there.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
NS_NOTREACHED("avail space rect with zero height!");
|
|
|
|
newY += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-09-23 06:25:26 +04:00
|
|
|
|
1999-10-16 03:35:10 +04:00
|
|
|
#ifdef DEBUG
|
2001-05-01 08:22:57 +04:00
|
|
|
if (nsBlockFrame::gNoisyReflow) {
|
|
|
|
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
2004-11-25 17:51:00 +03:00
|
|
|
printf("clear floats: out: y=%d(%d)\n", newY, newY - bp.top);
|
1999-10-16 03:35:10 +04:00
|
|
|
}
|
1998-12-05 19:02:08 +03:00
|
|
|
#endif
|
2004-11-25 17:51:00 +03:00
|
|
|
|
|
|
|
return newY;
|
1998-12-05 19:02:08 +03:00
|
|
|
}
|
2001-05-01 08:22:57 +04:00
|
|
|
|