Replace space manager with a more limited float manager. (Bug 191448) r+sr=roc
--HG-- rename : layout/generic/nsSpaceManager.cpp => layout/generic/nsFloatManager.cpp rename : layout/generic/nsSpaceManager.h => layout/generic/nsFloatManager.h
This commit is contained in:
Родитель
7d25fc9316
Коммит
dbe76c825c
|
@ -67,7 +67,7 @@
|
|||
#include "nsNodeInfo.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsRepeatService.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsSprocketLayout.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsStyleSet.h"
|
||||
|
|
|
@ -113,7 +113,6 @@ endif
|
|||
CPPSRCS = \
|
||||
nsAbsoluteContainingBlock.cpp \
|
||||
nsBRFrame.cpp \
|
||||
nsBlockBandData.cpp \
|
||||
nsBlockFrame.cpp \
|
||||
nsBlockReflowContext.cpp \
|
||||
nsBlockReflowState.cpp \
|
||||
|
@ -121,6 +120,7 @@ CPPSRCS = \
|
|||
nsColumnSetFrame.cpp \
|
||||
nsContainerFrame.cpp \
|
||||
nsFirstLetterFrame.cpp \
|
||||
nsFloatManager.cpp \
|
||||
nsFrame.cpp \
|
||||
nsFrameFrame.cpp \
|
||||
nsFrameList.cpp \
|
||||
|
@ -144,7 +144,6 @@ CPPSRCS = \
|
|||
nsPlaceholderFrame.cpp \
|
||||
nsSelection.cpp \
|
||||
nsSimplePageSequence.cpp \
|
||||
nsSpaceManager.cpp \
|
||||
nsSpacerFrame.cpp \
|
||||
nsSplittableFrame.cpp \
|
||||
nsTextFrameThebes.cpp \
|
||||
|
|
|
@ -1,270 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* 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"),
|
||||
* 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
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* code for management of floats that implements float manager interfaces */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsBlockBandData.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsHTMLReflowState.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
||||
nsBlockBandData::nsBlockBandData()
|
||||
: mSpaceManager(nsnull),
|
||||
mSpaceManagerX(0),
|
||||
mSpaceManagerY(0),
|
||||
mSpace(0, 0)
|
||||
{
|
||||
mSize = NS_BLOCK_BAND_DATA_TRAPS;
|
||||
mTrapezoids = mData;
|
||||
}
|
||||
|
||||
nsBlockBandData::~nsBlockBandData()
|
||||
{
|
||||
if (mTrapezoids != mData) {
|
||||
delete [] mTrapezoids;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBlockBandData::Init(nsSpaceManager* aSpaceManager,
|
||||
const nsSize& aSpace)
|
||||
{
|
||||
NS_PRECONDITION(aSpaceManager, "null pointer");
|
||||
|
||||
mSpaceManager = aSpaceManager;
|
||||
aSpaceManager->GetTranslation(mSpaceManagerX, mSpaceManagerY);
|
||||
|
||||
mSpace = aSpace;
|
||||
mLeftFloats = 0;
|
||||
mRightFloats = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the available reflow space for the current y coordinate. The
|
||||
// available space is relative to our coordinate system (0,0) is our
|
||||
// upper left corner.
|
||||
nsresult
|
||||
nsBlockBandData::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint,
|
||||
nsRect& aResult)
|
||||
{
|
||||
// Get the raw band data for the given Y coordinate
|
||||
nsresult rv = GetBandData(aY, aRelaxHeightConstraint);
|
||||
if (NS_FAILED(rv)) { return rv; }
|
||||
|
||||
// Compute the bounding rect of the available space, i.e. space
|
||||
// between any left and right floats.
|
||||
ComputeAvailSpaceRect();
|
||||
aResult = mAvailSpace;
|
||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||
printf("nsBBD %p GetAvailableSpace(%d) returning (%d, %d, %d, %d)\n",
|
||||
this, aY, aResult.x, aResult.y, aResult.width, aResult.height);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// the code below should never loop more than a very few times.
|
||||
// this is a safety valve to see if we've gone off the deep end
|
||||
#define ERROR_TOO_MANY_ITERATIONS 1000
|
||||
|
||||
/* nsBlockBandData methods should never call mSpaceManager->GetBandData directly.
|
||||
* They should always call nsBlockBandData::GetBandData() instead.
|
||||
*/
|
||||
nsresult
|
||||
nsBlockBandData::GetBandData(nscoord aY, PRBool aRelaxHeightConstraint)
|
||||
{
|
||||
NS_ASSERTION(mSpaceManager, "bad state, no float manager");
|
||||
PRInt32 iterations =0;
|
||||
nsSize space = mSpace;
|
||||
if (aRelaxHeightConstraint) {
|
||||
space.height = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
nsresult rv = mSpaceManager->GetBandData(aY, space, *this);
|
||||
while (NS_FAILED(rv)) {
|
||||
iterations++;
|
||||
if (iterations>ERROR_TOO_MANY_ITERATIONS)
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "too many iterations in nsBlockBandData::GetBandData");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// We need more space for our bands
|
||||
NS_ASSERTION(mTrapezoids, "bad state, no mTrapezoids");
|
||||
if (mTrapezoids && (mTrapezoids != mData)) {
|
||||
delete [] mTrapezoids;
|
||||
}
|
||||
PRInt32 newSize = mSize * 2;
|
||||
if (newSize<mCount) {
|
||||
newSize = mCount;
|
||||
}
|
||||
mTrapezoids = new nsBandTrapezoid[newSize];
|
||||
NS_POSTCONDITION(mTrapezoids, "failure allocating mTrapezoids");
|
||||
if (!mTrapezoids) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mSize = newSize;
|
||||
rv = mSpaceManager->GetBandData(aY, space, *this);
|
||||
}
|
||||
NS_POSTCONDITION(mCount<=mSize, "bad state, count > size");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Computes the bounding rect of the available space, i.e. space
|
||||
* between any left and right floats. Uses the current trapezoid
|
||||
* data, see nsISpaceManager::GetBandData(). Also updates member
|
||||
* data "availSpace".
|
||||
*/
|
||||
void
|
||||
nsBlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||
printf("nsBlockBandData::ComputeAvailSpaceRect %p with count %d\n", this, mCount);
|
||||
#endif
|
||||
if (0 == mCount) {
|
||||
mAvailSpace.x = 0;
|
||||
mAvailSpace.y = 0;
|
||||
mAvailSpace.width = 0;
|
||||
mAvailSpace.height = 0;
|
||||
mLeftFloats = 0;
|
||||
mRightFloats = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
nsBandTrapezoid* trapezoid = mTrapezoids;
|
||||
// The trapezoid to the left of the first right-floated trapezoid.
|
||||
nsBandTrapezoid* rightTrapezoid = nsnull;
|
||||
|
||||
PRInt32 leftFloats = 0;
|
||||
PRInt32 rightFloats = 0;
|
||||
if (mCount > 1) {
|
||||
// If there's more than one trapezoid that means there are floats
|
||||
PRInt32 i;
|
||||
|
||||
// Examine each trapezoid in the band, counting up the number of
|
||||
// left and right floats. Use the right-most float to
|
||||
// determine where the right edge of the available space is.
|
||||
NS_PRECONDITION(mCount<=mSize, "bad state, count > size");
|
||||
for (i = 0; i < mCount; i++) {
|
||||
trapezoid = &mTrapezoids[i];
|
||||
if (trapezoid->mFrames) {
|
||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||
printf("band %p checking !Avail trap %p with frame %p\n", this, trapezoid, trapezoid->mFrames);
|
||||
#endif
|
||||
const nsSmallVoidArray* frames = trapezoid->mFrames;
|
||||
const PRInt32 numFrames = frames->Count();
|
||||
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
|
||||
for (PRInt32 j = 0; j < numFrames; j++) {
|
||||
nsIFrame* f = static_cast<nsIFrame*>(frames->ElementAt(j));
|
||||
const nsStyleDisplay* display = f->GetStyleDisplay();
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
leftFloats++;
|
||||
}
|
||||
else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
rightFloats++;
|
||||
if ((nsnull == rightTrapezoid) && (i > 0)) {
|
||||
rightTrapezoid = &mTrapezoids[i - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mTrapezoids[0].mFrames) {
|
||||
// We have a float using up all the available space
|
||||
leftFloats = 1;
|
||||
}
|
||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||
printf("band %p has floats %d, %d\n", this, leftFloats, rightFloats);
|
||||
#endif
|
||||
mLeftFloats = leftFloats;
|
||||
mRightFloats = rightFloats;
|
||||
|
||||
// We look for available space in the last trapezoid before the
|
||||
// first right float, or in the last trapezoid if there is no right
|
||||
// float or no trapezoid before the first right float.
|
||||
if (nsnull != rightTrapezoid) {
|
||||
trapezoid = rightTrapezoid;
|
||||
}
|
||||
trapezoid->GetRect(mAvailSpace);
|
||||
|
||||
// When there is no available space, we still need a proper X
|
||||
// coordinate to place objects that end up here anyway.
|
||||
const nsSmallVoidArray* frames = trapezoid->mFrames;
|
||||
if (frames) {
|
||||
// It's not clear what coordinate to use when there is no
|
||||
// available space and the space is multiply occupied...So: If
|
||||
// any of the floats that are a part of the trapezoid are left
|
||||
// floats then we move over to the right edge of the
|
||||
// unavaliable space.
|
||||
const PRInt32 numFrames = frames->Count();
|
||||
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
|
||||
for (PRInt32 j = 0; j < numFrames; j++) {
|
||||
nsIFrame* f = static_cast<nsIFrame*>(frames->ElementAt(j));
|
||||
const nsStyleDisplay* display = f->GetStyleDisplay();
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
mAvailSpace.x = mAvailSpace.XMost();
|
||||
break;
|
||||
}
|
||||
}
|
||||
mAvailSpace.width = 0;
|
||||
}
|
||||
|
||||
// Fixup width
|
||||
if (NS_UNCONSTRAINEDSIZE == mSpace.width) {
|
||||
mAvailSpace.width = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||
printf(" ComputeAvailSpaceRect settting state mAvailSpace (%d,%d,%d,%d)\n",
|
||||
mAvailSpace.x, mAvailSpace.y, mAvailSpace.width, mAvailSpace.height);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void nsBlockBandData::List()
|
||||
{
|
||||
printf("nsBlockBandData %p sm=%p, sm coord = (%d,%d), mSpace = (%d,%d)\n",
|
||||
this, mSpaceManager, mSpaceManagerX, mSpaceManagerY,
|
||||
mSpace.width, mSpace.height);
|
||||
printf(" availSpace=(%d, %d, %d, %d), floats l=%d r=%d\n",
|
||||
mAvailSpace.x, mAvailSpace.y, mAvailSpace.width, mAvailSpace.height,
|
||||
mLeftFloats, mRightFloats);
|
||||
}
|
||||
#endif
|
|
@ -1,126 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* 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"),
|
||||
* 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
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* code for management of floats that implements float manager interfaces */
|
||||
|
||||
#ifndef nsBlockBandData_h___
|
||||
#define nsBlockBandData_h___
|
||||
|
||||
#include "nsSpaceManager.h"
|
||||
|
||||
class nsPresContext;
|
||||
|
||||
// Number of builtin nsBandTrapezoid's
|
||||
#define NS_BLOCK_BAND_DATA_TRAPS 6
|
||||
|
||||
/**
|
||||
* Class used to manage processing of the space-manager band data.
|
||||
* Provides HTML/CSS specific behavior to the raw data.
|
||||
*/
|
||||
class nsBlockBandData : public nsBandData {
|
||||
public:
|
||||
nsBlockBandData();
|
||||
~nsBlockBandData();
|
||||
|
||||
// Initialize. This must be called before any of the other methods.
|
||||
nsresult Init(nsSpaceManager* aSpaceManager, const nsSize& aSpace);
|
||||
|
||||
// Get some available space. Note that aY is relative to the current
|
||||
// float manager translation.
|
||||
nsresult GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint,
|
||||
nsRect& aResult);
|
||||
|
||||
// Get the raw trapezoid count for this band.
|
||||
PRInt32 GetTrapezoidCount() const {
|
||||
return mCount;
|
||||
}
|
||||
|
||||
const nsBandTrapezoid* GetTrapezoid(PRInt32 aIndex) const {
|
||||
return &mTrapezoids[aIndex];
|
||||
}
|
||||
|
||||
// Get the number of floats that are impacting the current
|
||||
// band. Note that this value is relative to the current translation
|
||||
// in the float manager which means that some floats may be hidden
|
||||
// by the translation and therefore won't be in the count.
|
||||
PRInt32 GetFloatCount() const {
|
||||
return mLeftFloats + mRightFloats;
|
||||
}
|
||||
PRInt32 GetLeftFloatCount() const {
|
||||
return mLeftFloats;
|
||||
}
|
||||
PRInt32 GetRightFloatCount() const {
|
||||
return mRightFloats;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void List();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
/** utility method to calculate the band data at aY.
|
||||
* nsBlockBandData methods should never call
|
||||
* mSpaceManager->GetBandData directly.
|
||||
* They should always call this method instead so data members
|
||||
* mTrapezoid, mCount, and mSize all get managed properly.
|
||||
*/
|
||||
nsresult GetBandData(nscoord aY, PRBool aRelaxHeightConstraint);
|
||||
|
||||
// The spacemanager we are getting space from
|
||||
nsSpaceManager* mSpaceManager;
|
||||
nscoord mSpaceManagerX, mSpaceManagerY;
|
||||
|
||||
// Limit to the available space (set by Init)
|
||||
nsSize mSpace;
|
||||
|
||||
// Trapezoids used during band processing
|
||||
nsBandTrapezoid mData[NS_BLOCK_BAND_DATA_TRAPS];
|
||||
|
||||
// Bounding rect of available space between any left and right floats
|
||||
nsRect mAvailSpace;
|
||||
|
||||
// Number of left/right floats in the current band. Note that this
|
||||
// number may be less than the total number of floats present in
|
||||
// the band, if our translation in the float manager "hides" some
|
||||
// floats.
|
||||
PRInt32 mLeftFloats, mRightFloats;
|
||||
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
#endif /* nsBlockBandData_h___ */
|
|
@ -51,7 +51,7 @@
|
|||
#undef NOISY_VERTICAL_MARGINS
|
||||
#undef NOISY_REFLOW_REASON // gives a little info about why each reflow was requested
|
||||
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
|
||||
#undef NOISY_FLOATMANAGER // enables debug output for float manager use, useful for analysing reflow of floats and positioned elements
|
||||
#undef NOISY_FLOATMANAGER // enables debug output for float manager use, useful for analysing reflow of floats
|
||||
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
|
||||
#undef REALLY_NOISY_REFLOW // some extra debug info
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "nsBlockFrame.h"
|
||||
#include "nsBlockReflowContext.h"
|
||||
#include "nsBlockReflowState.h"
|
||||
#include "nsBlockBandData.h"
|
||||
#include "nsBulletFrame.h"
|
||||
#include "nsLineBox.h"
|
||||
#include "nsInlineFrame.h"
|
||||
|
@ -70,7 +69,7 @@
|
|||
#include "prprf.h"
|
||||
#include "nsStyleChangeList.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsIntervalSet.h"
|
||||
#include "prenv.h"
|
||||
#include "plstr.h"
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "nsBlockReflowContext.h"
|
||||
#include "nsLineLayout.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsFrameManager.h"
|
||||
|
|
|
@ -134,7 +134,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
|||
}
|
||||
|
||||
mY = borderPadding.top;
|
||||
mBand.Init(mFloatManager, mContentArea);
|
||||
|
||||
mPrevChild = nsnull;
|
||||
mCurrentLine = aFrame->end_lines();
|
||||
|
@ -257,8 +256,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|||
nsRect& aResult)
|
||||
{
|
||||
#ifdef REALLY_NOISY_REFLOW
|
||||
printf("CBAS frame=%p has float count %d\n", aFrame, mBand.GetFloatCount());
|
||||
mBand.List();
|
||||
printf("CBAS frame=%p has floats %d\n", aFrame, mBandHasFloats);
|
||||
#endif
|
||||
aResult.y = mY;
|
||||
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||
|
@ -286,7 +284,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
|||
!aBlockAvoidsFloats,
|
||||
"unexpected replaced width");
|
||||
if (!aBlockAvoidsFloats) {
|
||||
if (mBand.GetFloatCount()) {
|
||||
if (mBandHasFloats) {
|
||||
// Use the float-edge property to determine how the child block
|
||||
// will interact with the float.
|
||||
const nsStyleBorder* borderStyle = aFrame->GetStyleBorder();
|
||||
|
@ -347,16 +345,22 @@ nsBlockReflowState::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint)
|
|||
"bad coord system");
|
||||
#endif
|
||||
|
||||
mBand.GetAvailableSpace(aY - BorderPadding().top, aRelaxHeightConstraint,
|
||||
mAvailSpaceRect);
|
||||
PRBool hasFloats;
|
||||
mAvailSpaceRect =
|
||||
mFloatManager->GetBand(aY - BorderPadding().top,
|
||||
aRelaxHeightConstraint ? nscoord_MAX
|
||||
: mContentArea.height,
|
||||
mContentArea.width,
|
||||
&hasFloats);
|
||||
mBandHasFloats = hasFloats;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("GetAvailableSpace: band=%d,%d,%d,%d count=%d\n",
|
||||
printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
|
||||
mAvailSpaceRect.x, mAvailSpaceRect.y,
|
||||
mAvailSpaceRect.width, mAvailSpaceRect.height,
|
||||
mBand.GetTrapezoidCount());
|
||||
mBandHasFloats);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -439,7 +443,7 @@ nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
|
|||
fc->mRegion.width, fc->mRegion.height);
|
||||
}
|
||||
#endif
|
||||
mFloatManager->AddRectRegion(floatFrame, fc->mRegion);
|
||||
mFloatManager->AddFloat(floatFrame, fc->mRegion);
|
||||
fc = fc->Next();
|
||||
}
|
||||
} else if (aLine->IsBlock()) {
|
||||
|
@ -522,9 +526,9 @@ nsBlockReflowState::IsImpactedByFloat() const
|
|||
{
|
||||
#ifdef REALLY_NOISY_REFLOW
|
||||
printf("nsBlockReflowState::IsImpactedByFloat %p returned %d\n",
|
||||
this, mBand.GetFloatCount());
|
||||
this, mBandHasFloats);
|
||||
#endif
|
||||
return mBand.GetFloatCount() > 0;
|
||||
return mBandHasFloats;
|
||||
}
|
||||
|
||||
|
||||
|
@ -659,7 +663,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
|||
// If the current Y coordinate is not impacted by any floats
|
||||
// then by definition the float fits.
|
||||
PRBool result = PR_TRUE;
|
||||
if (0 != mBand.GetFloatCount()) {
|
||||
if (mBandHasFloats) {
|
||||
// XXX We should allow overflow by up to half a pixel here (bug 21193).
|
||||
if (mAvailSpaceRect.width < aFloatSize.width) {
|
||||
// The available width is too narrow (and its been impacted by a
|
||||
|
@ -725,7 +729,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
|||
mY += mAvailSpaceRect.height;
|
||||
GetAvailableSpace(mY, aForceFit);
|
||||
|
||||
if (0 != mBand.GetFloatCount()) {
|
||||
if (mBandHasFloats) {
|
||||
if ((xa < mAvailSpaceRect.x) || (xb > mAvailSpaceRect.XMost())) {
|
||||
// The float can't go here.
|
||||
result = PR_FALSE;
|
||||
|
@ -775,7 +779,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||
|
||||
// Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
|
||||
// ``above'' another float that preceded it in the flow.
|
||||
mY = NS_MAX(mFloatManager->GetLowestRegionTop() + BorderPadding().top, mY);
|
||||
mY = NS_MAX(mFloatManager->GetLowestFloatTop() + BorderPadding().top, mY);
|
||||
|
||||
// See if the float should clear any preceding floats...
|
||||
// XXX We need to mark this float somehow so that it gets reflowed
|
||||
|
@ -944,7 +948,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
mFloatManager->AddRectRegion(floatFrame, region);
|
||||
mFloatManager->AddFloat(floatFrame, region);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
|
||||
|
||||
// Save away the floats region in the spacemanager, after making
|
||||
|
@ -973,7 +977,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
|||
nscoord tx, ty;
|
||||
mFloatManager->GetTranslation(tx, ty);
|
||||
nsFrame::ListTag(stdout, mBlock);
|
||||
printf(": FlowAndPlaceFloat: AddRectRegion: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
|
||||
printf(": FlowAndPlaceFloat: AddFloat: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
|
||||
tx, ty, mFloatManagerX, mFloatManagerY,
|
||||
aFloatCache->mRegion.x, aFloatCache->mRegion.y,
|
||||
aFloatCache->mRegion.width, aFloatCache->mRegion.height);
|
||||
|
@ -1101,7 +1105,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
|||
GetAvailableSpace(newY, PR_FALSE);
|
||||
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
|
||||
nsBlockFrame::WidthToClearPastFloats(*this, aReplacedBlock);
|
||||
if (mBand.GetFloatCount() == 0 ||
|
||||
if (!mBandHasFloats ||
|
||||
PR_MAX(mAvailSpaceRect.x, replacedWidth.marginLeft) +
|
||||
replacedWidth.borderBoxWidth +
|
||||
PR_MAX(mContentArea.width -
|
||||
|
@ -1124,8 +1128,8 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
|
|||
newY += 1;
|
||||
}
|
||||
}
|
||||
// Restore mBand and mAvailSpaceRect to the way they were. This may
|
||||
// well not be needed, and we should probably come up with
|
||||
// Restore mBandHasFloats and mAvailSpaceRect to the way they were.
|
||||
// This may well not be needed, and we should probably come up with
|
||||
// well-defined rules about when these members are valid so that
|
||||
// it's clearly not needed.
|
||||
GetAvailableSpace();
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#ifndef nsBlockReflowState_h__
|
||||
#define nsBlockReflowState_h__
|
||||
|
||||
#include "nsBlockBandData.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsLineBox.h"
|
||||
#include "nsFrameList.h"
|
||||
#include "nsBlockFrame.h"
|
||||
|
@ -194,7 +194,7 @@ public:
|
|||
|
||||
nsFloatManager* mFloatManager;
|
||||
|
||||
// The coordinates within the spacemanager where the block is being
|
||||
// The coordinates within the float manager where the block is being
|
||||
// placed <b>after</b> taking into account the blocks border and
|
||||
// padding. This, therefore, represents the inner "content area" (in
|
||||
// spacemanager coordinates) where child frames will be placed,
|
||||
|
@ -272,9 +272,6 @@ public:
|
|||
// this to the next next-in-flow.
|
||||
nsBlockFrame* mNextInFlow;
|
||||
|
||||
// The current band data for the current Y coordinate
|
||||
nsBlockBandData mBand;
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
// Temporary line-reflow state. This state is used during the reflow
|
||||
|
@ -299,6 +296,11 @@ public:
|
|||
|
||||
PRUint8 mFloatBreakType;
|
||||
|
||||
// The number of floats on the sides of mAvailSpaceRect, including
|
||||
// floats that do not reduce mAvailSpaceRect because they are in the
|
||||
// margins.
|
||||
PRPackedBool mBandHasFloats;
|
||||
|
||||
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||
{
|
||||
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||
|
|
|
@ -0,0 +1,465 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* 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"),
|
||||
* 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
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* class that manages rules for positioning floats */
|
||||
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsHTMLReflowState.h"
|
||||
#include "nsHashSets.h"
|
||||
#include "nsBlockDebugFlags.h"
|
||||
|
||||
PRInt32 nsFloatManager::sCachedFloatManagerCount = 0;
|
||||
void* nsFloatManager::sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PresShell Arena allocate callback (for nsIntervalSet use below)
|
||||
static void*
|
||||
PSArenaAllocCB(size_t aSize, void* aClosure)
|
||||
{
|
||||
return static_cast<nsIPresShell*>(aClosure)->AllocateFrame(aSize);
|
||||
}
|
||||
|
||||
// PresShell Arena free callback (for nsIntervalSet use below)
|
||||
static void
|
||||
PSArenaFreeCB(size_t aSize, void* aPtr, void* aClosure)
|
||||
{
|
||||
static_cast<nsIPresShell*>(aClosure)->FreeFrame(aSize, aPtr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsFloatManager
|
||||
|
||||
nsFloatManager::nsFloatManager(nsIPresShell* aPresShell)
|
||||
: mX(0), mY(0),
|
||||
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsFloatManager);
|
||||
}
|
||||
|
||||
nsFloatManager::~nsFloatManager()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsFloatManager);
|
||||
}
|
||||
|
||||
// static
|
||||
void* nsFloatManager::operator new(size_t aSize) CPP_THROW_NEW
|
||||
{
|
||||
if (sCachedFloatManagerCount > 0) {
|
||||
// We have cached unused instances of this class, return a cached
|
||||
// instance in stead of always creating a new one.
|
||||
return sCachedFloatManagers[--sCachedFloatManagerCount];
|
||||
}
|
||||
|
||||
// The cache is empty, this means we haveto create a new instance using
|
||||
// the global |operator new|.
|
||||
return nsMemory::Alloc(aSize);
|
||||
}
|
||||
|
||||
void
|
||||
nsFloatManager::operator delete(void* aPtr, size_t aSize)
|
||||
{
|
||||
if (!aPtr)
|
||||
return;
|
||||
// This float manager is no longer used, if there's still room in
|
||||
// the cache we'll cache this float manager, unless the layout
|
||||
// module was already shut down.
|
||||
|
||||
if (sCachedFloatManagerCount < NS_FLOAT_MANAGER_CACHE_SIZE &&
|
||||
sCachedFloatManagerCount >= 0) {
|
||||
// There's still space in the cache for more instances, put this
|
||||
// instance in the cache in stead of deleting it.
|
||||
|
||||
sCachedFloatManagers[sCachedFloatManagerCount++] = aPtr;
|
||||
return;
|
||||
}
|
||||
|
||||
// The cache is full, or the layout module has been shut down,
|
||||
// delete this float manager.
|
||||
nsMemory::Free(aPtr);
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
void nsFloatManager::Shutdown()
|
||||
{
|
||||
// The layout module is being shut down, clean up the cache and
|
||||
// disable further caching.
|
||||
|
||||
PRInt32 i;
|
||||
|
||||
for (i = 0; i < sCachedFloatManagerCount; i++) {
|
||||
void* floatManager = sCachedFloatManagers[i];
|
||||
if (floatManager)
|
||||
nsMemory::Free(floatManager);
|
||||
}
|
||||
|
||||
// Disable further caching.
|
||||
sCachedFloatManagerCount = -1;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsFloatManager::GetBand(nscoord aYOffset,
|
||||
nscoord aMaxHeight,
|
||||
nscoord aContentAreaWidth,
|
||||
PRBool* aHasFloats) const
|
||||
{
|
||||
NS_ASSERTION(aMaxHeight >= 0, "unexpected max height");
|
||||
NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width");
|
||||
|
||||
nscoord top = aYOffset + mY;
|
||||
if (top < nscoord_MIN) {
|
||||
NS_NOTREACHED("bad value");
|
||||
top = nscoord_MIN;
|
||||
}
|
||||
|
||||
// If there are no floats at all, or we're below the last one, return
|
||||
// quickly.
|
||||
PRUint32 floatCount = mFloats.Length();
|
||||
if (floatCount == 0 ||
|
||||
(mFloats[floatCount-1].mLeftYMost <= top &&
|
||||
mFloats[floatCount-1].mRightYMost <= top)) {
|
||||
*aHasFloats = PR_FALSE;
|
||||
return nsRect(0, aYOffset, aContentAreaWidth, aMaxHeight);
|
||||
}
|
||||
|
||||
nscoord bottom;
|
||||
if (aMaxHeight == nscoord_MAX) {
|
||||
bottom = nscoord_MAX;
|
||||
} else {
|
||||
bottom = top + aMaxHeight;
|
||||
if (bottom < top || bottom > nscoord_MAX) {
|
||||
NS_NOTREACHED("bad value");
|
||||
bottom = nscoord_MAX;
|
||||
}
|
||||
}
|
||||
nscoord left = mX;
|
||||
nscoord right = aContentAreaWidth + mX;
|
||||
if (right < left) {
|
||||
NS_NOTREACHED("bad value");
|
||||
right = left;
|
||||
}
|
||||
|
||||
// Walk backwards through the floats until we either hit the front of
|
||||
// the list or we're above |top|.
|
||||
PRBool haveFloats = PR_FALSE;
|
||||
for (PRUint32 i = mFloats.Length(); i > 0; --i) {
|
||||
const FloatInfo &fi = mFloats[i-1];
|
||||
if (fi.mLeftYMost <= top && fi.mRightYMost <= top) {
|
||||
// There aren't any more floats that could intersect this band.
|
||||
break;
|
||||
}
|
||||
if (fi.mRect.IsEmpty()) {
|
||||
// For compatibility, ignore floats with empty rects, even though it
|
||||
// disagrees with the spec. (We might want to fix this in the
|
||||
// future, though.)
|
||||
continue;
|
||||
}
|
||||
nscoord floatTop = fi.mRect.y, floatBottom = fi.mRect.YMost();
|
||||
if (floatTop > top) {
|
||||
// This float is below our band. Shrink our band's height if needed.
|
||||
if (floatTop < bottom) {
|
||||
bottom = floatTop;
|
||||
}
|
||||
} else if (floatBottom > top) {
|
||||
// This float is in our band.
|
||||
haveFloats = PR_TRUE;
|
||||
|
||||
// Shrink our band's height if needed.
|
||||
if (floatBottom < bottom) {
|
||||
bottom = floatBottom;
|
||||
}
|
||||
|
||||
// Shrink our band's width if needed.
|
||||
if (fi.mFrame->GetStyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) {
|
||||
// A left float.
|
||||
nscoord rightEdge = fi.mRect.XMost();
|
||||
if (rightEdge > left) {
|
||||
left = rightEdge;
|
||||
}
|
||||
} else {
|
||||
// A right float.
|
||||
nscoord leftEdge = fi.mRect.x;
|
||||
if (leftEdge < right) {
|
||||
right = leftEdge;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aHasFloats = haveFloats;
|
||||
nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top);
|
||||
return nsRect(left - mX, top - mY, right - left, height);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect)
|
||||
{
|
||||
NS_ASSERTION(aMarginRect.width >= 0, "negative width!");
|
||||
NS_ASSERTION(aMarginRect.height >= 0, "negative height!");
|
||||
|
||||
FloatInfo info(aFloatFrame, aMarginRect + nsPoint(mX, mY));
|
||||
|
||||
// Set mLeftYMost and mRightYMost.
|
||||
if (HasAnyFloats()) {
|
||||
FloatInfo &tail = mFloats[mFloats.Length() - 1];
|
||||
info.mLeftYMost = tail.mLeftYMost;
|
||||
info.mRightYMost = tail.mRightYMost;
|
||||
} else {
|
||||
info.mLeftYMost = nscoord_MIN;
|
||||
info.mRightYMost = nscoord_MIN;
|
||||
}
|
||||
PRUint8 floatStyle = aFloatFrame->GetStyleDisplay()->mFloats;
|
||||
NS_ASSERTION(floatStyle == NS_STYLE_FLOAT_LEFT ||
|
||||
floatStyle == NS_STYLE_FLOAT_RIGHT, "unexpected float");
|
||||
nscoord& sideYMost = (floatStyle == NS_STYLE_FLOAT_LEFT) ? info.mLeftYMost
|
||||
: info.mRightYMost;
|
||||
nscoord thisYMost = info.mRect.YMost();
|
||||
if (thisYMost > sideYMost)
|
||||
sideYMost = thisYMost;
|
||||
|
||||
if (!mFloats.AppendElement(info))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFloatManager::RemoveTrailingRegions(nsIFrame* aFrameList)
|
||||
{
|
||||
if (!aFrameList) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This could be a good bit simpler if we could guarantee that the
|
||||
// floats given were at the end of our list, so we could just search
|
||||
// for the head of aFrameList. (But we can't;
|
||||
// layout/reftests/bugs/421710-1.html crashes.)
|
||||
nsVoidHashSet frameSet;
|
||||
|
||||
frameSet.Init(1);
|
||||
for (nsIFrame* f = aFrameList; f; f = f->GetNextSibling()) {
|
||||
frameSet.Put(f);
|
||||
}
|
||||
|
||||
PRUint32 newLength = mFloats.Length();
|
||||
while (newLength > 0) {
|
||||
if (!frameSet.Contains(mFloats[newLength - 1].mFrame)) {
|
||||
break;
|
||||
}
|
||||
--newLength;
|
||||
}
|
||||
mFloats.RemoveElementsAt(newLength, mFloats.Length() - newLength);
|
||||
|
||||
#ifdef DEBUG
|
||||
for (PRUint32 i = 0; i < mFloats.Length(); ++i) {
|
||||
NS_ASSERTION(!frameSet.Contains(mFloats[i].mFrame),
|
||||
"Frame region deletion was requested but we couldn't delete it");
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloatManager::PushState(SavedState* aState)
|
||||
{
|
||||
NS_PRECONDITION(aState, "Need a place to save state");
|
||||
|
||||
// This is a cheap push implementation, which
|
||||
// only saves the (x,y) and last frame in the mFrameInfoMap
|
||||
// which is enough info to get us back to where we should be
|
||||
// when pop is called.
|
||||
//
|
||||
// This push/pop mechanism is used to undo any
|
||||
// floats that were added during the unconstrained reflow
|
||||
// in nsBlockReflowContext::DoReflowBlock(). (See bug 96736)
|
||||
//
|
||||
// It should also be noted that the state for mFloatDamage is
|
||||
// intentionally not saved or restored in PushState() and PopState(),
|
||||
// since that could lead to bugs where damage is missed/dropped when
|
||||
// we move from position A to B (during the intermediate incremental
|
||||
// reflow mentioned above) and then from B to C during the subsequent
|
||||
// reflow. In the typical case A and C will be the same, but not always.
|
||||
// Allowing mFloatDamage to accumulate the damage incurred during both
|
||||
// reflows ensures that nothing gets missed.
|
||||
aState->mX = mX;
|
||||
aState->mY = mY;
|
||||
aState->mFloatInfoCount = mFloats.Length();
|
||||
}
|
||||
|
||||
void
|
||||
nsFloatManager::PopState(SavedState* aState)
|
||||
{
|
||||
NS_PRECONDITION(aState, "No state to restore?");
|
||||
|
||||
mX = aState->mX;
|
||||
mY = aState->mY;
|
||||
|
||||
NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(),
|
||||
"somebody misused PushState/PopState");
|
||||
mFloats.RemoveElementsAt(aState->mFloatInfoCount,
|
||||
mFloats.Length() - aState->mFloatInfoCount);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFloatManager::GetLowestFloatTop() const
|
||||
{
|
||||
if (!HasAnyFloats()) {
|
||||
return nscoord_MIN;
|
||||
}
|
||||
return mFloats[mFloats.Length() - 1].mRect.y - mY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
DebugListFloatManager(const nsFloatManager *aFloatManager)
|
||||
{
|
||||
aFloatManager->List(stdout);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFloatManager::List(FILE* out) const
|
||||
{
|
||||
if (!HasAnyFloats())
|
||||
return NS_OK;
|
||||
|
||||
for (PRUint32 i = 0; i < mFloats.Length(); ++i) {
|
||||
const FloatInfo &fi = mFloats[i];
|
||||
printf("Float %u: frame=%p rect={%d,%d,%d,%d} ymost={l:%d, r:%d}\n",
|
||||
i, static_cast<void*>(fi.mFrame),
|
||||
fi.mRect.x, fi.mRect.y, fi.mRect.width, fi.mRect.height,
|
||||
fi.mLeftYMost, fi.mRightYMost);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nscoord
|
||||
nsFloatManager::ClearFloats(nscoord aY, PRUint8 aBreakType) const
|
||||
{
|
||||
if (!HasAnyFloats()) {
|
||||
return aY;
|
||||
}
|
||||
|
||||
nscoord bottom = aY + mY;
|
||||
|
||||
const FloatInfo &tail = mFloats[mFloats.Length() - 1];
|
||||
switch (aBreakType) {
|
||||
case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
|
||||
bottom = PR_MAX(bottom, tail.mLeftYMost);
|
||||
bottom = PR_MAX(bottom, tail.mRightYMost);
|
||||
break;
|
||||
case NS_STYLE_CLEAR_LEFT:
|
||||
bottom = PR_MAX(bottom, tail.mLeftYMost);
|
||||
break;
|
||||
case NS_STYLE_CLEAR_RIGHT:
|
||||
bottom = PR_MAX(bottom, tail.mRightYMost);
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
bottom -= mY;
|
||||
|
||||
return bottom;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FloatInfo
|
||||
|
||||
nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, const nsRect& aRect)
|
||||
: mFrame(aFrame), mRect(aRect)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsFloatManager::FloatInfo::~FloatInfo()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsFloatManager::FloatInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsAutoFloatManager::~nsAutoFloatManager()
|
||||
{
|
||||
// Restore the old float manager in the reflow state if necessary.
|
||||
if (mNew) {
|
||||
#ifdef NOISY_FLOATMANAGER
|
||||
printf("restoring old float manager %p\n", mOld);
|
||||
#endif
|
||||
|
||||
mReflowState.mFloatManager = mOld;
|
||||
|
||||
#ifdef NOISY_FLOATMANAGER
|
||||
if (mOld) {
|
||||
static_cast<nsFrame *>(mReflowState.frame)->ListTag(stdout);
|
||||
printf(": space-manager %p after reflow\n", mOld);
|
||||
mOld->List(stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
delete mNew;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoFloatManager::CreateFloatManager(nsPresContext *aPresContext)
|
||||
{
|
||||
// Create a new float manager and install it in the reflow
|
||||
// state. `Remember' the old float manager so we can restore it
|
||||
// later.
|
||||
mNew = new nsFloatManager(aPresContext->PresShell());
|
||||
if (! mNew)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
#ifdef NOISY_FLOATMANAGER
|
||||
printf("constructed new float manager %p (replacing %p)\n",
|
||||
mNew, mReflowState.mFloatManager);
|
||||
#endif
|
||||
|
||||
// Set the float manager in the existing reflow state
|
||||
mOld = mReflowState.mFloatManager;
|
||||
mReflowState.mFloatManager = mNew;
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:cindent:ts=2:et:sw=2:
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* 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"),
|
||||
* 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
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* class that manages rules for positioning floats */
|
||||
|
||||
#ifndef nsFloatManager_h_
|
||||
#define nsFloatManager_h_
|
||||
|
||||
#include "nsIntervalSet.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIPresShell;
|
||||
class nsIFrame;
|
||||
struct nsHTMLReflowState;
|
||||
class nsPresContext;
|
||||
|
||||
#define NS_FLOAT_MANAGER_CACHE_SIZE 4
|
||||
|
||||
class nsFloatManager {
|
||||
public:
|
||||
nsFloatManager(nsIPresShell* aPresShell);
|
||||
~nsFloatManager();
|
||||
|
||||
void* operator new(size_t aSize) CPP_THROW_NEW;
|
||||
void operator delete(void* aPtr, size_t aSize);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* Translate the current origin by the specified (dx, dy). This
|
||||
* creates a new local coordinate space relative to the current
|
||||
* coordinate space.
|
||||
*/
|
||||
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
|
||||
|
||||
/**
|
||||
* Returns the current translation from local coordinate space to
|
||||
* world coordinate space. This represents the accumulated calls to
|
||||
* Translate().
|
||||
*/
|
||||
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
|
||||
|
||||
/**
|
||||
* Get information about the band containing vertical coordinate |aY|,
|
||||
* but up to at most |aMaxHeight| (which may be nscoord_MAX). This
|
||||
* will return the tallest rectangle whose top is |aY| and in which
|
||||
* there are no changes in what floats are on the sides of that
|
||||
* rectangle, but will limit the height of the rectangle to
|
||||
* |aMaxHeight|. The left and right edges of the rectangle give the
|
||||
* area available for line boxes in that space.
|
||||
*
|
||||
* @param aY [in] vertical coordinate for top of available space
|
||||
* desired
|
||||
* @param aMaxHeight [in] maximum height of available space desired
|
||||
* @param aContentAreaWidth [in] the width of the content area (whose left
|
||||
* edge must be zero in the current translation)
|
||||
* @param aHasFloats [out] whether there are floats at the sides of
|
||||
* the return value including those that do not
|
||||
* reduce the line box width at all (because they
|
||||
* are entirely in the margins)
|
||||
* @return the resulting rectangle for line boxes. It will not go
|
||||
* left of 0, nor right of aContentAreaWidth, but will be
|
||||
* narrower when floats are present.
|
||||
*
|
||||
* aY and aAvailSpace are positioned relative to the current translation
|
||||
*/
|
||||
nsRect GetBand(nscoord aY, nscoord aMaxHeight, nscoord aContentAreaWidth,
|
||||
PRBool* aHasFloats) const;
|
||||
|
||||
/**
|
||||
* Add a float that comes after all floats previously added. Its top
|
||||
* must be even with or below the top of all previous floats.
|
||||
*
|
||||
* aMarginRect is relative to the current translation. The caller
|
||||
* must ensure aMarginRect.height >= 0 and aMarginRect.width >= 0.
|
||||
*/
|
||||
nsresult AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect);
|
||||
|
||||
/**
|
||||
* Remove the regions associated with this floating frame and its
|
||||
* next-sibling list. Some of the frames may never have been added;
|
||||
* we just skip those. This is not fully general; it only works as
|
||||
* long as the N frames to be removed are the last N frames to have
|
||||
* been added; if there's a frame in the middle of them that should
|
||||
* not be removed, YOU LOSE.
|
||||
*/
|
||||
nsresult RemoveTrailingRegions(nsIFrame* aFrameList);
|
||||
|
||||
private:
|
||||
struct FloatInfo;
|
||||
public:
|
||||
|
||||
// Structure that stores the current state of a frame manager for
|
||||
// Save/Restore purposes.
|
||||
struct SavedState;
|
||||
friend struct SavedState;
|
||||
struct SavedState {
|
||||
private:
|
||||
PRUint32 mFloatInfoCount;
|
||||
nscoord mX, mY;
|
||||
|
||||
friend class nsFloatManager;
|
||||
};
|
||||
|
||||
PRBool HasAnyFloats() const { return !mFloats.IsEmpty(); }
|
||||
|
||||
/**
|
||||
* Methods for dealing with the propagation of float damage during
|
||||
* reflow.
|
||||
*/
|
||||
PRBool HasFloatDamage() const
|
||||
{
|
||||
return !mFloatDamage.IsEmpty();
|
||||
}
|
||||
|
||||
void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
|
||||
{
|
||||
mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
|
||||
}
|
||||
|
||||
PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd) const
|
||||
{
|
||||
return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current state of the float manager into aState.
|
||||
*/
|
||||
void PushState(SavedState* aState);
|
||||
|
||||
/**
|
||||
* Restores the float manager to the saved state.
|
||||
*
|
||||
* These states must be managed using stack discipline. PopState can only
|
||||
* be used after PushState has been used to save the state, and it can only
|
||||
* be used once --- although it can be omitted; saved states can be ignored.
|
||||
* States must be popped in the reverse order they were pushed.
|
||||
*/
|
||||
void PopState(SavedState* aState);
|
||||
|
||||
/**
|
||||
* Get the top of the last float placed into the float manager, to
|
||||
* enforce the rule that a float can't be above an earlier float.
|
||||
* Returns the minimum nscoord value if there are no floats.
|
||||
*
|
||||
* The result is relative to the current translation.
|
||||
*/
|
||||
nscoord GetLowestFloatTop() const;
|
||||
|
||||
/**
|
||||
* Return the coordinate of the lowest float matching aBreakType in this
|
||||
* float manager. Returns aY if there are no matching floats.
|
||||
*
|
||||
* Both aY and the result are relative to the current translation.
|
||||
*/
|
||||
nscoord ClearFloats(nscoord aY, PRUint8 aBreakType) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Dump the state of the float manager out to a file.
|
||||
*/
|
||||
nsresult List(FILE* out) const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
struct FloatInfo {
|
||||
nsIFrame *const mFrame;
|
||||
nsRect mRect;
|
||||
// The lowest bottoms of left/right floats up to and including this one.
|
||||
nscoord mLeftYMost, mRightYMost;
|
||||
|
||||
FloatInfo(nsIFrame* aFrame, const nsRect& aRect);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
~FloatInfo();
|
||||
#endif
|
||||
};
|
||||
|
||||
nscoord mX, mY; // translation from local to global coordinate space
|
||||
nsTArray<FloatInfo> mFloats;
|
||||
nsIntervalSet mFloatDamage;
|
||||
|
||||
static PRInt32 sCachedFloatManagerCount;
|
||||
static void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];
|
||||
|
||||
nsFloatManager(const nsFloatManager&); // no implementation
|
||||
void operator=(const nsFloatManager&); // no implementation
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper class to manage maintenance of the float manager during
|
||||
* nsBlockFrame::Reflow. It automatically restores the old float
|
||||
* manager in the reflow state when the object goes out of scope.
|
||||
*/
|
||||
class nsAutoFloatManager {
|
||||
public:
|
||||
nsAutoFloatManager(nsHTMLReflowState& aReflowState)
|
||||
: mReflowState(aReflowState),
|
||||
mNew(nsnull),
|
||||
mOld(nsnull) {}
|
||||
|
||||
~nsAutoFloatManager();
|
||||
|
||||
/**
|
||||
* Create a new float manager for the specified frame. This will
|
||||
* `remember' the old float manager, and install the new float
|
||||
* manager in the reflow state.
|
||||
*/
|
||||
nsresult
|
||||
CreateFloatManager(nsPresContext *aPresContext);
|
||||
|
||||
protected:
|
||||
nsHTMLReflowState &mReflowState;
|
||||
nsFloatManager *mNew;
|
||||
nsFloatManager *mOld;
|
||||
};
|
||||
|
||||
#endif /* !defined(nsFloatManager_h_) */
|
|
@ -41,7 +41,6 @@
|
|||
/* representation of one line within a block frame, a CSS line box */
|
||||
|
||||
#include "nsLineBox.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsLineLayout.h"
|
||||
#include "prprf.h"
|
||||
#include "nsBlockFrame.h"
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsILineIterator.h"
|
||||
|
||||
class nsFloatManager;
|
||||
class nsLineBox;
|
||||
class nsFloatCache;
|
||||
class nsFloatCacheList;
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
#include "nsInlineFrame.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIFontMetrics.h"
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,491 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:cindent:ts=2:et:sw=2:
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* 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"),
|
||||
* 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
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* class that manages regions of 2-D space, originally designed
|
||||
* generally but actually specific to space occupied by floats
|
||||
*/
|
||||
|
||||
#ifndef nsSpaceManager_h___
|
||||
#define nsSpaceManager_h___
|
||||
|
||||
#include "prclist.h"
|
||||
#include "nsIntervalSet.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsIPresShell;
|
||||
class nsIFrame;
|
||||
struct nsSize;
|
||||
struct nsHTMLReflowState;
|
||||
class nsPresContext;
|
||||
|
||||
#define NS_SPACE_MANAGER_CACHE_SIZE 4
|
||||
|
||||
/**
|
||||
* Information about a particular trapezoid within a band. The space described
|
||||
* by the trapezoid is in one of three states:
|
||||
* <ul>
|
||||
* <li>available
|
||||
* <li>occupied by one frame
|
||||
* <li>occupied by more than one frame
|
||||
* </ul>
|
||||
*/
|
||||
struct nsBandTrapezoid {
|
||||
nscoord mTopY, mBottomY; // top and bottom y-coordinates
|
||||
nscoord mTopLeftX, mBottomLeftX; // left edge x-coordinates
|
||||
nscoord mTopRightX, mBottomRightX; // right edge x-coordinates
|
||||
const nsSmallVoidArray* mFrames; // list of frames occupying the space
|
||||
|
||||
// Get the height of the trapezoid
|
||||
nscoord GetHeight() const {return mBottomY - mTopY;}
|
||||
|
||||
// Get the bounding rect of the trapezoid
|
||||
inline void GetRect(nsRect& aRect) const;
|
||||
|
||||
// Set the trapezoid from a rectangle
|
||||
inline void operator=(const nsRect& aRect);
|
||||
|
||||
// Do these trapezoids have the same geometry?
|
||||
inline PRBool EqualGeometry(const nsBandTrapezoid& aTrap) const;
|
||||
|
||||
nsBandTrapezoid()
|
||||
: mTopY(0),
|
||||
mBottomY(0),
|
||||
mTopLeftX(0),
|
||||
mBottomLeftX(0),
|
||||
mTopRightX(0),
|
||||
mBottomRightX(0),
|
||||
mFrames(nsnull)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline void nsBandTrapezoid::GetRect(nsRect& aRect) const
|
||||
{
|
||||
aRect.x = PR_MIN(mTopLeftX, mBottomLeftX);
|
||||
aRect.y = mTopY;
|
||||
aRect.width = PR_MAX(mTopRightX, mBottomRightX);
|
||||
if (NS_MAXSIZE != aRect.width) {
|
||||
aRect.width -= aRect.x;
|
||||
}
|
||||
aRect.height = (NS_MAXSIZE == mBottomY) ? NS_MAXSIZE : mBottomY - mTopY;
|
||||
}
|
||||
|
||||
inline void nsBandTrapezoid::operator=(const nsRect& aRect)
|
||||
{
|
||||
mTopLeftX = mBottomLeftX = aRect.x;
|
||||
mTopRightX = mBottomRightX = aRect.XMost();
|
||||
mTopY = aRect.y;
|
||||
mBottomY = aRect.YMost();
|
||||
}
|
||||
|
||||
inline PRBool nsBandTrapezoid::EqualGeometry(const nsBandTrapezoid& aTrap) const
|
||||
{
|
||||
return (
|
||||
mTopLeftX == aTrap.mTopLeftX &&
|
||||
mBottomLeftX == aTrap.mBottomLeftX &&
|
||||
mTopRightX == aTrap.mTopRightX &&
|
||||
mBottomRightX == aTrap.mBottomRightX &&
|
||||
mTopY == aTrap.mTopY &&
|
||||
mBottomY == aTrap.mBottomY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure used for describing the space within a band.
|
||||
* @see #GetBandData()
|
||||
*/
|
||||
struct nsBandData {
|
||||
PRInt32 mCount; // [out] actual number of trapezoids in the band data
|
||||
PRInt32 mSize; // [in] the size of the array (number of trapezoids)
|
||||
nsBandTrapezoid* mTrapezoids; // [out] array of length 'size'
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for dealing with bands of available space. The float manager
|
||||
* defines a coordinate space (relative to the frame that created the
|
||||
* float manager) with an origin at (0, 0) that grows down and to the
|
||||
* right.
|
||||
*/
|
||||
class nsFloatManager {
|
||||
public:
|
||||
nsFloatManager(nsIPresShell* aPresShell);
|
||||
~nsFloatManager();
|
||||
|
||||
void* operator new(size_t aSize) CPP_THROW_NEW;
|
||||
void operator delete(void* aPtr, size_t aSize);
|
||||
|
||||
static void Shutdown();
|
||||
/**
|
||||
* Translate the current origin by the specified (dx, dy). This
|
||||
* creates a new local coordinate space relative to the current
|
||||
* coordinate space.
|
||||
*/
|
||||
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
|
||||
|
||||
/**
|
||||
* Returns the current translation from local coordinate space to
|
||||
* world coordinate space. This represents the accumulated calls to
|
||||
* Translate().
|
||||
*/
|
||||
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
|
||||
/**
|
||||
* Returns the y-most of the bottommost band or 0 if there are no bands.
|
||||
*
|
||||
* @return PR_TRUE if there are bands and PR_FALSE if there are no bands
|
||||
*/
|
||||
PRBool YMost(nscoord& aYMost) const;
|
||||
|
||||
/**
|
||||
* Returns a band starting at the specified y-offset. The band data
|
||||
* indicates which parts of the band are available, and which parts
|
||||
* are unavailable
|
||||
*
|
||||
* The band data that is returned is in the coordinate space of the
|
||||
* local coordinate system.
|
||||
*
|
||||
* The local coordinate space origin, the y-offset, and the max size
|
||||
* describe a rectangle that's used to clip the underlying band of
|
||||
* available space, i.e.
|
||||
* {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
|
||||
* coordinate space
|
||||
*
|
||||
* @param aYOffset the y-offset of where the band begins. The coordinate is
|
||||
* relative to the upper-left corner of the local coordinate space
|
||||
* @param aMaxSize the size to use to constrain the band data
|
||||
* @param aBandData [in,out] used to return the list of trapezoids that
|
||||
* describe the available space and the unavailable space
|
||||
* @return NS_OK if successful and NS_ERROR_FAILURE if the band data is not
|
||||
* not large enough. The 'count' member of the band data struct
|
||||
* indicates how large the array of trapezoids needs to be
|
||||
*/
|
||||
nsresult GetBandData(nscoord aYOffset,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aBandData) const;
|
||||
|
||||
/**
|
||||
* Add a rectangular region of unavailable space. The space is
|
||||
* relative to the local coordinate system.
|
||||
*
|
||||
* The region is tagged with a frame
|
||||
*
|
||||
* @param aFrame the frame used to identify the region. Must not be NULL
|
||||
* @param aUnavailableSpace the bounding rect of the unavailable space
|
||||
* @return NS_OK if successful
|
||||
* NS_ERROR_FAILURE if there is already a region tagged with aFrame
|
||||
*/
|
||||
nsresult AddRectRegion(nsIFrame* aFrame,
|
||||
const nsRect& aUnavailableSpace);
|
||||
|
||||
/**
|
||||
* Remove the regions associated with this floating frame and its
|
||||
* next-sibling list. Some of the frames may never have been added;
|
||||
* we just skip those. This is not fully general; it only works as
|
||||
* long as the N frames to be removed are the last N frames to have
|
||||
* been added; if there's a frame in the middle of them that should
|
||||
* not be removed, YOU LOSE.
|
||||
*
|
||||
* This can only be done at the end of the life of this float manager. The only
|
||||
* methods it is safe to call after this are XMost() and YMost().
|
||||
*/
|
||||
nsresult RemoveTrailingRegions(nsIFrame* aFrameList);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Remove the region associated with aFrane.
|
||||
*
|
||||
* doesn't work in the general case!
|
||||
*
|
||||
* Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
|
||||
* tagged with aFrame
|
||||
*/
|
||||
nsresult RemoveRegion(nsIFrame* aFrame);
|
||||
|
||||
public:
|
||||
// Structure that stores the current state of a frame manager for
|
||||
// Save/Restore purposes.
|
||||
struct SavedState {
|
||||
private:
|
||||
nsIFrame *mLastFrame;
|
||||
nscoord mX, mY;
|
||||
nscoord mLowestTop;
|
||||
nscoord mMaximalLeftYMost;
|
||||
nscoord mMaximalRightYMost;
|
||||
PRPackedBool mHaveCachedLeftYMost;
|
||||
PRPackedBool mHaveCachedRightYMost;
|
||||
|
||||
friend class nsFloatManager;
|
||||
};
|
||||
|
||||
PRBool HasAnyFloats() { return mFrameInfoMap != nsnull; }
|
||||
|
||||
/**
|
||||
* Methods for dealing with the propagation of float damage during
|
||||
* reflow.
|
||||
*/
|
||||
PRBool HasFloatDamage()
|
||||
{
|
||||
return !mFloatDamage.IsEmpty();
|
||||
}
|
||||
|
||||
void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
|
||||
{
|
||||
mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
|
||||
}
|
||||
|
||||
PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
|
||||
{
|
||||
return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current state of the float manager into aState.
|
||||
*/
|
||||
void PushState(SavedState* aState);
|
||||
|
||||
/**
|
||||
* Restores the float manager to the saved state.
|
||||
*
|
||||
* These states must be managed using stack discipline. PopState can only
|
||||
* be used after PushState has been used to save the state, and it can only
|
||||
* be used once --- although it can be omitted; saved states can be ignored.
|
||||
* States must be popped in the reverse order they were pushed.
|
||||
*/
|
||||
void PopState(SavedState* aState);
|
||||
|
||||
/**
|
||||
* Get the top of the last region placed into the float manager, to
|
||||
* enforce the rule that a float can't be above an earlier float.
|
||||
* Returns the minimum nscoord value if there are no regions.
|
||||
*/
|
||||
nscoord GetLowestRegionTop();
|
||||
|
||||
/**
|
||||
* Return the coordinate of the lowest float matching aBreakType in this
|
||||
* float manager. Returns aY if there are no matching floats.
|
||||
*/
|
||||
nscoord ClearFloats(nscoord aY, PRUint8 aBreakType);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Dump the state of the spacemanager out to a file
|
||||
*/
|
||||
nsresult List(FILE* out);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Structure that maintains information about the region associated
|
||||
// with a particular frame
|
||||
struct FrameInfo {
|
||||
nsIFrame* const mFrame;
|
||||
nsRect mRect; // rectangular region
|
||||
FrameInfo* mNext;
|
||||
|
||||
FrameInfo(nsIFrame* aFrame, const nsRect& aRect);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
~FrameInfo();
|
||||
#endif
|
||||
};
|
||||
|
||||
public:
|
||||
// Doubly linked list of band rects
|
||||
struct BandRect : PRCListStr {
|
||||
nscoord mLeft, mTop;
|
||||
nscoord mRight, mBottom;
|
||||
nsSmallVoidArray mFrames; // list of frames occupying the space
|
||||
|
||||
BandRect(nscoord aLeft, nscoord aTop,
|
||||
nscoord aRight, nscoord aBottom,
|
||||
nsIFrame* aFrame);
|
||||
BandRect(nscoord aLeft, nscoord aTop,
|
||||
nscoord aRight, nscoord aBottom,
|
||||
nsSmallVoidArray& frames);
|
||||
~BandRect();
|
||||
|
||||
// List operations
|
||||
BandRect* Next() const {return (BandRect*)PR_NEXT_LINK(this);}
|
||||
BandRect* Prev() const {return (BandRect*)PR_PREV_LINK(this);}
|
||||
void InsertBefore(BandRect* aBandRect) {PR_INSERT_BEFORE(aBandRect, this);}
|
||||
void InsertAfter(BandRect* aBandRect) {PR_INSERT_AFTER(aBandRect, this);}
|
||||
void Remove() {PR_REMOVE_LINK(this);}
|
||||
|
||||
// Split the band rect into two vertically, with this band rect becoming
|
||||
// the top part, and a new band rect being allocated and returned for the
|
||||
// bottom part
|
||||
//
|
||||
// Does not insert the new band rect into the linked list
|
||||
BandRect* SplitVertically(nscoord aBottom);
|
||||
|
||||
// Split the band rect into two horizontally, with this band rect becoming
|
||||
// the left part, and a new band rect being allocated and returned for the
|
||||
// right part
|
||||
//
|
||||
// Does not insert the new band rect into the linked list
|
||||
BandRect* SplitHorizontally(nscoord aRight);
|
||||
|
||||
// Accessor functions
|
||||
PRBool IsOccupiedBy(const nsIFrame* aFrame) const {
|
||||
return (mFrames.IndexOf((void*)aFrame) != -1);
|
||||
}
|
||||
void AddFrame(const nsIFrame* aFrame) {
|
||||
mFrames.AppendElement((void*)aFrame);
|
||||
}
|
||||
void RemoveFrame(const nsIFrame* aFrame) {
|
||||
mFrames.RemoveElement((void*)aFrame);
|
||||
}
|
||||
nsIFrame * FrameAt(PRInt32 index) {
|
||||
return static_cast<nsIFrame*>(mFrames.FastElementAt(index));
|
||||
}
|
||||
PRBool HasSameFrameList(const BandRect* aBandRect) const;
|
||||
PRInt32 Length() const;
|
||||
};
|
||||
|
||||
// Circular linked list of band rects
|
||||
struct BandList : BandRect {
|
||||
BandList();
|
||||
|
||||
// Accessors
|
||||
PRBool IsEmpty() const {return PR_CLIST_IS_EMPTY((PRCListStr*)this);}
|
||||
BandRect* Head() const {return (BandRect*)PR_LIST_HEAD(this);}
|
||||
BandRect* Tail() const {return (BandRect*)PR_LIST_TAIL(this);}
|
||||
|
||||
// Operations
|
||||
void Append(BandRect* aBandRect) {PR_APPEND_LINK(aBandRect, this);}
|
||||
|
||||
// Remove and delete all the band rects in the list
|
||||
void Clear();
|
||||
};
|
||||
|
||||
protected:
|
||||
nscoord mX, mY; // translation from local to global coordinate space
|
||||
BandList mBandList; // header/sentinel for circular linked list of band rects
|
||||
nscoord mLowestTop; // the lowest *top*
|
||||
FrameInfo* mFrameInfoMap;
|
||||
nsIntervalSet mFloatDamage;
|
||||
PRPackedBool mHaveCachedLeftYMost; // If true, mMaximalLeftYMost is set
|
||||
PRPackedBool mHaveCachedRightYMost; // If true, mMaximalRightYMost is set
|
||||
nscoord mMaximalLeftYMost; // The maximal YMost of our FrameInfo
|
||||
// rects for left floats. Only makes
|
||||
// sense when mHaveCachedLeftYMost is
|
||||
// true.
|
||||
nscoord mMaximalRightYMost; // The maximal YMost of our FrameInfo
|
||||
// rects for right floats. Only makes
|
||||
// sense when mHaveCachedLeftYMost is
|
||||
// true.
|
||||
// We keep track of the last BandRect* we worked with so that we can
|
||||
// make use of locality of reference in situations where people want
|
||||
// to do a bunch of operations in a row.
|
||||
BandRect* mCachedBandPosition;
|
||||
|
||||
protected:
|
||||
FrameInfo* GetFrameInfoFor(nsIFrame* aFrame);
|
||||
FrameInfo* CreateFrameInfo(nsIFrame* aFrame, const nsRect& aRect);
|
||||
void DestroyFrameInfo(FrameInfo*);
|
||||
|
||||
void ClearFrameInfo();
|
||||
|
||||
BandRect* GetNextBand(const BandRect* aBandRect) const;
|
||||
BandRect* GetPrevBand(const BandRect* aBandRect) const;
|
||||
void DivideBand(BandRect* aBand, nscoord aBottom);
|
||||
PRBool CanJoinBands(BandRect* aBand, BandRect* aPrevBand);
|
||||
PRBool JoinBands(BandRect* aBand, BandRect* aPrevBand);
|
||||
void AddRectToBand(BandRect* aBand, BandRect* aBandRect);
|
||||
void InsertBandRect(BandRect* aBandRect);
|
||||
|
||||
nsresult GetBandAvailableSpace(const BandRect* aBand,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
|
||||
// Return a band guaranteed to have its top at or above aYOffset or the first
|
||||
// band if there is no band with its top above aYOffset. This method will
|
||||
// use mCachedBandPosition to maybe get such a band that's not too far up.
|
||||
// This function should not be called if there are no bands.
|
||||
// This function never returns null.
|
||||
BandRect* GuessBandWithTopAbove(nscoord aYOffset) const;
|
||||
|
||||
void SetCachedBandPosition(BandRect* aBandRect) {
|
||||
NS_ASSERTION(!aBandRect ||
|
||||
aBandRect == mBandList.Head() ||
|
||||
aBandRect->Prev()->mBottom != aBandRect->mBottom,
|
||||
"aBandRect should be first rect within its band");
|
||||
mCachedBandPosition = aBandRect;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static PRInt32 sCachedFloatManagerCount;
|
||||
static void* sCachedFloatManagers[NS_SPACE_MANAGER_CACHE_SIZE];
|
||||
|
||||
nsFloatManager(const nsFloatManager&); // no implementation
|
||||
void operator=(const nsFloatManager&); // no implementation
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper class to manage maintenance of the float manager during
|
||||
* nsBlockFrame::Reflow. It automatically restores the old space
|
||||
* manager in the reflow state when the object goes out of scope.
|
||||
*/
|
||||
class nsAutoFloatManager {
|
||||
public:
|
||||
nsAutoFloatManager(nsHTMLReflowState& aReflowState)
|
||||
: mReflowState(aReflowState),
|
||||
mNew(nsnull),
|
||||
mOld(nsnull) {}
|
||||
|
||||
~nsAutoFloatManager();
|
||||
|
||||
/**
|
||||
* Create a new float manager for the specified frame. This will
|
||||
* `remember' the old float manager, and install the new space
|
||||
* manager in the reflow state.
|
||||
*/
|
||||
nsresult
|
||||
CreateFloatManager(nsPresContext *aPresContext);
|
||||
|
||||
protected:
|
||||
nsHTMLReflowState &mReflowState;
|
||||
nsFloatManager *mNew;
|
||||
nsFloatManager *mOld;
|
||||
};
|
||||
|
||||
#endif /* nsSpaceManager_h___ */
|
||||
|
|
@ -41,7 +41,6 @@
|
|||
#include "nsIDOMSVGForeignObjectElem.h"
|
||||
#include "nsIDOMSVGMatrix.h"
|
||||
#include "nsIDOMSVGSVGElement.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsSVGOuterSVGFrame.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
#include "nsINameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIView.h"
|
||||
|
|
Загрузка…
Ссылка в новой задаче