fixes layout of pages where a single line is impacted by 2 or more floaters
r=troy
This commit is contained in:
buster%netscape.com 2000-03-22 23:19:10 +00:00
Родитель 0a15601c9b
Коммит 1c6eca645a
26 изменённых файлов: 972 добавлений и 198 удалений

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

@ -117,6 +117,7 @@ LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView*
// Alphabetical list of event handler names

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

@ -72,6 +72,16 @@ typedef enum SelectionRegion{SELECTION_ANCHOR_REGION = 0,
SELECTION_FOCUS_REGION,
NUM_SELECTION_REGIONS} SelectionRegion;
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
#define VERIFY_REFLOW_NOISY 0x02
#define VERIFY_REFLOW_ALL 0x04
#define VERIFY_REFLOW_DUMP_COMMANDS 0x08
#define VERIFY_REFLOW_NOISY_RC 0x10
#define VERIFY_REFLOW_REALLY_NOISY_RC 0x20
#define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80
/**
* Presentation shell interface. Presentation shells are the
@ -416,6 +426,10 @@ public:
*/
static NS_LAYOUT void SetVerifyReflowEnable(PRBool aEnabled);
/**
* Get the flags associated with the VerifyReflow debug tool
*/
static NS_LAYOUT PRInt32 GetVerifyReflowFlags();
};
/**

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

@ -117,6 +117,7 @@ LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView*
// Alphabetical list of event handler names

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

@ -22,6 +22,7 @@
#define PL_ARENA_CONST_ALIGN_MASK 3
#include "nsIPresShell.h"
#include "nsISpaceManager.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsIDocument.h"
@ -48,6 +49,7 @@
#include "nsIDOMSelection.h"
#include "nsISelectionController.h"
#include "nsLayoutCID.h"
#include "nsLayoutAtoms.h"
#include "nsIDOMRange.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h"
@ -573,15 +575,7 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrameManager* aFrameManager)
* means that you cannot perform logging before then.
*/
static PRLogModuleInfo* gLogModule;
static PRUint32 gVerifyReflowFlags;
#define VERIFY_REFLOW_ON 0x01
#define VERIFY_REFLOW_NOISY 0x02
#define VERIFY_REFLOW_ALL 0x04
#define VERIFY_REFLOW_DUMP_COMMANDS 0x08
#define VERIFY_REFLOW_NOISY_RC 0x10
#define VERIFY_REFLOW_REALLY_NOISY_RC 0x20
#endif
static PRBool gVerifyReflowEnabled;
@ -627,6 +621,12 @@ nsIPresShell::SetVerifyReflowEnable(PRBool aEnabled)
gVerifyReflowEnabled = aEnabled;
}
NS_LAYOUT PRInt32
nsIPresShell::GetVerifyReflowFlags()
{
return gVerifyReflowFlags;
}
//----------------------------------------------------------------------
NS_LAYOUT nsresult
@ -1406,6 +1406,13 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
#endif
}
ExitReflowLock(PR_TRUE);
// if the proper flag is set, VerifyReflow now
if (GetVerifyReflowEnable() && (VERIFY_REFLOW_DURING_RESIZE_REFLOW & gVerifyReflowFlags))
{
mInVerifyReflow = PR_TRUE;
PRBool ok = VerifyIncrementalReflow();
mInVerifyReflow = PR_FALSE;
}
return NS_OK; //XXX this needs to be real. MMP
}
@ -3231,6 +3238,8 @@ static PRBool
CompareTrees(nsIPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
nsIPresContext* aSecondPresContext, nsIFrame* aSecondFrame)
{
if (!aFirstPresContext || !aFirstFrame || !aSecondPresContext || !aSecondFrame)
return PR_TRUE;
PRBool ok = PR_TRUE;
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
@ -3305,6 +3314,115 @@ CompareTrees(nsIPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
break;
}
// verify that neither frame has a space manager,
// or they both do and the space managers are equivalent
nsCOMPtr<nsIFrameManager>fm1;
nsCOMPtr<nsIPresShell> ps1;
nsISpaceManager *sm1; // note, no ref counting here
aFirstPresContext->GetShell(getter_AddRefs(ps1));
NS_ASSERTION(ps1, "no pres shell for primary tree!");
ps1->GetFrameManager(getter_AddRefs(fm1));
NS_ASSERTION(fm1, "no frame manager for primary tree!");
fm1->GetFrameProperty((nsIFrame*)k1, nsLayoutAtoms::spaceManagerProperty,
0, (void **)&sm1);
// look at the test frame
nsCOMPtr<nsIFrameManager>fm2;
nsCOMPtr<nsIPresShell> ps2;
nsISpaceManager *sm2; // note, no ref counting here
aSecondPresContext->GetShell(getter_AddRefs(ps2));
NS_ASSERTION(ps2, "no pres shell for test tree!");
ps2->GetFrameManager(getter_AddRefs(fm2));
NS_ASSERTION(fm2, "no frame manager for test tree!");
fm2->GetFrameProperty((nsIFrame*)k2, nsLayoutAtoms::spaceManagerProperty,
0, (void **)&sm2);
// now compare the space managers
if (((nsnull == sm1) && (nsnull != sm2)) ||
((nsnull != sm1) && (nsnull == sm2))) { // one is null, and the other is not
ok = PR_FALSE;
LogVerifyMessage(k1, k2, "space managers are not matched\n");
}
else if (sm1 && sm2) { // both are not null, compare them
// first, compare yMost
nscoord yMost1, yMost2;
nsresult smresult = sm1->YMost(yMost1);
if (NS_ERROR_ABORT != smresult)
{
NS_ASSERTION(NS_SUCCEEDED(smresult), "bad result");
smresult = sm2->YMost(yMost2);
NS_ASSERTION(NS_SUCCEEDED(smresult), "bad result");
if (yMost1 != yMost2) {
LogVerifyMessage(k1, k2, "yMost of space managers differs\n");
}
// now compare bands by sampling
PRInt32 yIncrement = yMost1/100;
if (0==yIncrement) {
yIncrement = 1; // guarantee we make progress in the loop below
}
nscoord yOffset = 0;
for ( ; ok && yOffset < yMost1; yOffset += yIncrement)
{
nscoord small=5, large=100;
nsBandData band1, band2;
nsBandTrapezoid trap1[20], trap2[20];
band1.mSize = band2.mSize = 20;
band1.mTrapezoids = trap1;
band2.mTrapezoids = trap2;
sm1->GetBandData(yOffset, nsSize(small,small), band1);
sm2->GetBandData(yOffset, nsSize(small,small), band2);
if (band1.mCount != band2.mCount)
{ // count mismatch, stop comparing
LogVerifyMessage(k1, k2, "band.mCount of space managers differs\n");
printf("count1= %d, count2=%d, yOffset = %d, size=%d\n",
band1.mCount, band2.mCount, yOffset, small);
ok = PR_FALSE;
}
else // band counts match, compare individual traps
{
PRInt32 trapIndex=0;
for ( ;trapIndex<band1.mCount; trapIndex++)
{
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
trap1[trapIndex].mState == trap2[trapIndex].mState;
if (!match)
{
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
printf ("index %d\n", trapIndex);
}
}
}
// test the larger maxSize
sm1->GetBandData(yOffset, nsSize(large,large), band1);
sm2->GetBandData(yOffset, nsSize(large,large), band2);
if (band1.mCount != band2.mCount)
{ // count mismatch, stop comparing
LogVerifyMessage(k1, k2, "band.mCount of space managers differs\n");
printf("count1= %d, count2=%d, yOffset = %d, size=%d\n",
band1.mCount, band2.mCount, yOffset, small);
ok = PR_FALSE;
}
else // band counts match, compare individual traps
{
PRInt32 trapIndex=0;
for ( ; trapIndex<band1.mCount; trapIndex++)
{
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
trap1[trapIndex].mState == trap2[trapIndex].mState;
if (!match)
{
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
printf ("index %d\n", trapIndex);
}
}
}
}
}
}
// Compare the sub-trees too
if (!CompareTrees(aFirstPresContext, k1, aSecondPresContext, k2)) {
ok = PR_FALSE;

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

@ -72,6 +72,16 @@ typedef enum SelectionRegion{SELECTION_ANCHOR_REGION = 0,
SELECTION_FOCUS_REGION,
NUM_SELECTION_REGIONS} SelectionRegion;
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
#define VERIFY_REFLOW_NOISY 0x02
#define VERIFY_REFLOW_ALL 0x04
#define VERIFY_REFLOW_DUMP_COMMANDS 0x08
#define VERIFY_REFLOW_NOISY_RC 0x10
#define VERIFY_REFLOW_REALLY_NOISY_RC 0x20
#define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80
/**
* Presentation shell interface. Presentation shells are the
@ -416,6 +426,10 @@ public:
*/
static NS_LAYOUT void SetVerifyReflowEnable(PRBool aEnabled);
/**
* Get the flags associated with the VerifyReflow debug tool
*/
static NS_LAYOUT PRInt32 GetVerifyReflowFlags();
};
/**

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

@ -65,6 +65,17 @@ struct nsBandTrapezoid {
// Set the trapezoid from a rectangle
void operator=(const nsRect& aRect);
/** does a binary compare of this object with aTrap */
PRBool Equals(const nsBandTrapezoid aTrap) const;
/** does a semantic compare only of geometric data in this object and aTrap */
PRBool EqualGeometry(const nsBandTrapezoid aTrap) const;
nsBandTrapezoid() {
mTopY = mBottomY = mTopLeftX = mBottomLeftX = mTopRightX = mBottomRightX = 0;
mFrame = nsnull;
}
};
/**
@ -214,4 +225,30 @@ inline void nsBandTrapezoid::operator=(const nsRect& aRect)
mBottomY = aRect.YMost();
}
inline PRBool nsBandTrapezoid::Equals(const nsBandTrapezoid aTrap) const
{
return (
mTopLeftX == aTrap.mTopLeftX &&
mBottomLeftX == aTrap.mBottomLeftX &&
mTopRightX == aTrap.mTopRightX &&
mBottomRightX == aTrap.mBottomRightX &&
mTopY == aTrap.mTopY &&
mBottomY == aTrap.mBottomY &&
mState == aTrap.mState &&
mFrame == aTrap.mFrame
);
}
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
);
}
#endif /* nsISpaceManager_h___ */

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

@ -117,6 +117,7 @@ LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView*
// Alphabetical list of event handler names

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

@ -133,6 +133,9 @@ nsBlockBandData::GetBandData(nscoord aY)
void
nsBlockBandData::ComputeAvailSpaceRect()
{
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("nsBlockBandData::ComputeAvailSpaceRect %p \n", this);
#endif
if (0 == mCount) {
mAvailSpace.x = 0;
mAvailSpace.y = 0;
@ -157,6 +160,9 @@ nsBlockBandData::ComputeAvailSpaceRect()
for (i = 0; i < mCount; i++) {
trapezoid = &mTrapezoids[i];
if (trapezoid->mState != nsBandTrapezoid::Available) {
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("band %p checking !Avail trap %p with frame %p\n", this, trapezoid, trapezoid->mFrame);
#endif
const nsStyleDisplay* display;
if (nsBandTrapezoid::OccupiedMultiple == trapezoid->mState) {
PRInt32 j, numFrames = trapezoid->mFrames->Count();
@ -195,6 +201,9 @@ nsBlockBandData::ComputeAvailSpaceRect()
// We have a floater using up all the available space
leftFloaters = 1;
}
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("band %p has floaters %d, %d\n", this, leftFloaters, rightFloaters);
#endif
mLeftFloaters = leftFloaters;
mRightFloaters = rightFloaters;

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

@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);

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

@ -140,8 +140,15 @@ public:
virtual void DeleteChildsNextInFlow(nsIPresContext* aPresContext,
nsIFrame* aNextInFlow);
/** return the topmost block child based on y-index.
* almost always the first or second line, if there is one.
* accounts for lines that hold only compressed white space, etc.
*/
nsIFrame* GetTopBlockChild();
/** Place the floaters in the spacemanager for all lines in this block.
* recursively adds floaters in child blocks of this frame.
*/
nsresult UpdateSpaceManager(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager);
@ -160,9 +167,16 @@ protected:
return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
}
/** move the frames contained by aLine by aDY
* if aLine is a block, it's child floaters are added to the state manager
*/
void SlideLine(nsBlockReflowState& aState,
nsLineBox* aLine, nscoord aDY);
/** grab overflow lines from this block's prevInFlow, and make them
* part of this block's mLines list.
* @return PR_TRUE if any lines were drained.
*/
PRBool DrainOverflowLines(nsIPresContext* aPresContext);
virtual PRIntn GetSkipSides() const;
@ -171,26 +185,51 @@ protected:
nsBlockReflowState& aState,
nsHTMLReflowMetrics& aMetrics);
/** add the frames in aFrameList to this block after aPrevSibling
* this block thinks in terms of lines, but the frame construction code
* knows nothing about lines at all. So we need to find the line that
* contains aPrevSibling and add aFrameList after aPrevSibling on that line.
* new lines are created as necessary to handle block data in aFrameList.
*/
nsresult AddFrames(nsIPresContext* aPresContext,
nsIFrame* aFrameList,
nsIFrame* aPrevSibling);
/** move the frame list rooted at aFrame into this as a child
* assumes prev/next sibling pointers will be or have been set elsewhere
* changes aFrame's parent to be this, and reparents aFrame's view and stylecontext.
*/
void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame);
/** does all the real work for removing aDeletedFrame from this
* finds the line containing aFrame.
* handled continued frames
* marks lines dirty as needed
*/
nsresult DoRemoveFrame(nsIPresContext* aPresContext,
nsIFrame* aDeletedFrame);
/** set up the conditions necessary for an initial reflow */
nsresult PrepareInitialReflow(nsBlockReflowState& aState);
/** set up the conditions necessary for an styleChanged reflow */
nsresult PrepareStyleChangedReflow(nsBlockReflowState& aState);
/** set up the conditions necessary for an incremental reflow.
* the primary task is to mark the minimumly sufficient lines dirty.
*/
nsresult PrepareChildIncrementalReflow(nsBlockReflowState& aState);
/** set up the conditions necessary for an resize reflow
* the primary task is to mark the minimumly sufficient lines dirty.
*/
nsresult PrepareResizeReflow(nsBlockReflowState& aState);
/** reflow all lines that have been marked dirty */
nsresult ReflowDirtyLines(nsBlockReflowState& aState);
/** set aState to what it would be if we had done a full reflow to this point. */
void RecoverStateFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord aDeltaY,
@ -198,8 +237,15 @@ protected:
//----------------------------------------
// Methods for line reflow
// XXX nuke em
/**
* Reflow a line.
* @param aState the current reflow state
* @param aLine the line to reflow. can contain a single block frame
* or contain 1 or more inline frames.
* @param aKeepReflowGoing [OUT] indicates whether the caller should continue to reflow more lines
* @param aDamageDirtyArea if PR_TRUE, do extra work to mark the changed areas as damaged for painting
* this indicates that frames may have changed size, for example
*/
nsresult ReflowLine(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepReflowGoing,

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

@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);

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

@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);

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

@ -32,10 +32,16 @@
#include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h"
#undef NOISY_FINAL_SIZE
#ifdef DEBUG
#undef NOISY_PUSHING
#endif
nsIID nsInlineFrame::kInlineFrameCID = NS_INLINE_FRAME_CID;
//////////////////////////////////////////////////////////////////////
// Basic nsInlineFrame methods
@ -426,6 +432,9 @@ nsInlineFrame::ReflowFrames(nsIPresContext* aPresContext,
PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
PRBool isComplete;
frame = PullOneFrame(aPresContext, irs, &isComplete);
#ifdef NOISY_PUSHING
printf("%p pulled up %p\n", this, frame);
#endif
if (nsnull == frame) {
if (!isComplete) {
aStatus = NS_FRAME_NOT_COMPLETE;
@ -668,6 +677,10 @@ nsInlineFrame::PushFrames(nsIPresContext* aPresContext,
NS_PRECONDITION(prevNextSibling == aFromChild, "bad prev sibling");
#endif
#ifdef NOISY_PUSHING
printf("%p pushing aFromChild %p, disconnecting from prev sib %p\n",
this, aFromChild, aPrevSibling);
#endif
// Disconnect aFromChild from its previous sibling
aPrevSibling->SetNextSibling(nsnull);

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

@ -153,8 +153,8 @@ nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const
{
PR_snprintf(aBuf, aBufSize, "%s,%s,%s,%s[0x%x]",
IsBlock() ? "block" : "inline",
IsDirty() ? "dirty" : "",
IsImpactedByFloater() ? "impacted" : "",
IsDirty() ? "dirty" : "clean",
IsImpactedByFloater() ? "IMPACTED" : "NOT Impacted",
IsTrimmed() ? "trimmed" : "",
mAllFlags);
return aBuf;
@ -353,16 +353,15 @@ nsLineBox::FreeFloaters(nsFloaterCacheFreeList& aFreeList)
void
nsLineBox::RemoveFloatersFromSpaceManager(nsISpaceManager* aSpaceManager)
{
{
if (IsInline()) {
if (mInlineData) {
nsFloaterCache* floaterCache = mInlineData->mFloaters.Head();
while (floaterCache) {
nsIFrame* floater = floaterCache->mPlaceholder->GetOutOfFlowFrame();
aSpaceManager->RemoveRegion(floater);
floaterCache = floaterCache->Next();
floaterCache = floaterCache->Next();
}
}
}
@ -370,7 +369,7 @@ nsLineBox::RemoveFloatersFromSpaceManager(nsISpaceManager* aSpaceManager)
void
nsLineBox::AppendFloaters(nsFloaterCacheFreeList& aFreeList)
{
{
NS_ABORT_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline()) {
if (aFreeList.NotEmpty()) {
@ -404,7 +403,7 @@ nsLineBox::RemoveFloater(nsIFrame* aFrame)
void
nsLineBox::SetCombinedArea(const nsRect& aCombinedArea)
{
{
NS_ASSERTION(aCombinedArea.width >= 0, "illegal width for combined area");
NS_ASSERTION(aCombinedArea.height >= 0, "illegal height for combined area");
if (aCombinedArea != mBounds) {
@ -428,13 +427,22 @@ nsLineBox::SetCombinedArea(const nsRect& aCombinedArea)
}
MaybeFreeData();
}
#ifdef VERY_NOISY_REFLOW
printf("nsLB::SetCombinedArea(1) %p (%d, %d, %d, %d)\n",
this, aCombinedArea.x, aCombinedArea.y, aCombinedArea.width, aCombinedArea.height);
#endif
}
void
nsLineBox::GetCombinedArea(nsRect* aResult)
{
NS_ASSERTION(aResult, "null arg");
if (aResult) {
*aResult = mData ? mData->mCombinedArea : mBounds;
#ifdef VERY_NOISY_REFLOW
printf("nsLB::SetCombinedArea(1) %p (%d, %d, %d, %d)\n",
this, aResult->x, aResult->y, aResult->width, aResult->height);
#endif
}
}

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

@ -189,6 +189,7 @@ public:
// mImpactedByFloater bit
void SetLineIsImpactedByFloater(PRBool aValue) {
NS_ASSERTION((PR_FALSE==aValue || PR_TRUE==aValue), "somebody is playing fast and loose with bools and bits!");
mFlags.mImpactedByFloater = aValue;
}
PRBool IsImpactedByFloater() const {
@ -197,6 +198,7 @@ public:
// mTrimmed bit
void SetTrimmed(PRBool aOn) {
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
mFlags.mTrimmed = aOn;
}
PRBool IsTrimmed() const {
@ -205,6 +207,7 @@ public:
// mHasPercentageChild bit
void SetHasPercentageChild(PRBool aOn) {
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
mFlags.mHasPercentageChild = aOn;
}
PRBool HasPercentageChild() const {
@ -213,6 +216,7 @@ public:
// mLineWrapped bit
void SetLineWrapped(PRBool aOn) {
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
mFlags.mLineWrapped = aOn;
}
PRBool IsLineWrapped() const {

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

@ -235,6 +235,10 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
PRBool aImpactedByFloaters,
PRBool aIsTopOfPage)
{
#ifdef REALLY_NOISY_REFLOW
printf("nsLL::BeginLineReflow %d, %d, %d, %d, impacted=%s\n",
aX, aY, aWidth, aHeight, aImpactedByFloaters?"true":"false");
#endif
NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
#ifdef DEBUG
if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) {
@ -350,6 +354,10 @@ nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
PRBool aPlacedLeftFloater,
nsIFrame* aFloaterFrame)
{
#ifdef REALLY_NOISY_REFLOW
printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p placedLeft=%s\n will set mImpacted to PR_TRUE",
aX, aY, aWidth, aHeight, aFloaterFrame, aPlacedLeftFloater?"true":"false");
#endif
PerSpanData* psd = mRootSpan;
NS_PRECONDITION(psd->mX == psd->mLeftEdge, "update-band called late");
#ifdef DEBUG

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

@ -133,6 +133,9 @@ nsBlockBandData::GetBandData(nscoord aY)
void
nsBlockBandData::ComputeAvailSpaceRect()
{
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("nsBlockBandData::ComputeAvailSpaceRect %p \n", this);
#endif
if (0 == mCount) {
mAvailSpace.x = 0;
mAvailSpace.y = 0;
@ -157,6 +160,9 @@ nsBlockBandData::ComputeAvailSpaceRect()
for (i = 0; i < mCount; i++) {
trapezoid = &mTrapezoids[i];
if (trapezoid->mState != nsBandTrapezoid::Available) {
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("band %p checking !Avail trap %p with frame %p\n", this, trapezoid, trapezoid->mFrame);
#endif
const nsStyleDisplay* display;
if (nsBandTrapezoid::OccupiedMultiple == trapezoid->mState) {
PRInt32 j, numFrames = trapezoid->mFrames->Count();
@ -195,6 +201,9 @@ nsBlockBandData::ComputeAvailSpaceRect()
// We have a floater using up all the available space
leftFloaters = 1;
}
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("band %p has floaters %d, %d\n", this, leftFloaters, rightFloaters);
#endif
mLeftFloaters = leftFloaters;
mRightFloaters = rightFloaters;

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

@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);

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

@ -140,8 +140,15 @@ public:
virtual void DeleteChildsNextInFlow(nsIPresContext* aPresContext,
nsIFrame* aNextInFlow);
/** return the topmost block child based on y-index.
* almost always the first or second line, if there is one.
* accounts for lines that hold only compressed white space, etc.
*/
nsIFrame* GetTopBlockChild();
/** Place the floaters in the spacemanager for all lines in this block.
* recursively adds floaters in child blocks of this frame.
*/
nsresult UpdateSpaceManager(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager);
@ -160,9 +167,16 @@ protected:
return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
}
/** move the frames contained by aLine by aDY
* if aLine is a block, it's child floaters are added to the state manager
*/
void SlideLine(nsBlockReflowState& aState,
nsLineBox* aLine, nscoord aDY);
/** grab overflow lines from this block's prevInFlow, and make them
* part of this block's mLines list.
* @return PR_TRUE if any lines were drained.
*/
PRBool DrainOverflowLines(nsIPresContext* aPresContext);
virtual PRIntn GetSkipSides() const;
@ -171,26 +185,51 @@ protected:
nsBlockReflowState& aState,
nsHTMLReflowMetrics& aMetrics);
/** add the frames in aFrameList to this block after aPrevSibling
* this block thinks in terms of lines, but the frame construction code
* knows nothing about lines at all. So we need to find the line that
* contains aPrevSibling and add aFrameList after aPrevSibling on that line.
* new lines are created as necessary to handle block data in aFrameList.
*/
nsresult AddFrames(nsIPresContext* aPresContext,
nsIFrame* aFrameList,
nsIFrame* aPrevSibling);
/** move the frame list rooted at aFrame into this as a child
* assumes prev/next sibling pointers will be or have been set elsewhere
* changes aFrame's parent to be this, and reparents aFrame's view and stylecontext.
*/
void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame);
/** does all the real work for removing aDeletedFrame from this
* finds the line containing aFrame.
* handled continued frames
* marks lines dirty as needed
*/
nsresult DoRemoveFrame(nsIPresContext* aPresContext,
nsIFrame* aDeletedFrame);
/** set up the conditions necessary for an initial reflow */
nsresult PrepareInitialReflow(nsBlockReflowState& aState);
/** set up the conditions necessary for an styleChanged reflow */
nsresult PrepareStyleChangedReflow(nsBlockReflowState& aState);
/** set up the conditions necessary for an incremental reflow.
* the primary task is to mark the minimumly sufficient lines dirty.
*/
nsresult PrepareChildIncrementalReflow(nsBlockReflowState& aState);
/** set up the conditions necessary for an resize reflow
* the primary task is to mark the minimumly sufficient lines dirty.
*/
nsresult PrepareResizeReflow(nsBlockReflowState& aState);
/** reflow all lines that have been marked dirty */
nsresult ReflowDirtyLines(nsBlockReflowState& aState);
/** set aState to what it would be if we had done a full reflow to this point. */
void RecoverStateFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord aDeltaY,
@ -198,8 +237,15 @@ protected:
//----------------------------------------
// Methods for line reflow
// XXX nuke em
/**
* Reflow a line.
* @param aState the current reflow state
* @param aLine the line to reflow. can contain a single block frame
* or contain 1 or more inline frames.
* @param aKeepReflowGoing [OUT] indicates whether the caller should continue to reflow more lines
* @param aDamageDirtyArea if PR_TRUE, do extra work to mark the changed areas as damaged for painting
* this indicates that frames may have changed size, for example
*/
nsresult ReflowLine(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepReflowGoing,

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

@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);

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

@ -146,7 +146,7 @@ InitDebugFlags()
}
#undef NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
#undef NOISY_FLOATER_CLEARING
@ -410,6 +410,10 @@ public:
}
PRBool IsImpactedByFloater() {
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockReflowState::IsImpactedByFloater %p returned %d\n",
this, mBand.GetFloaterCount());
#endif
return mBand.GetFloaterCount();
}
@ -741,16 +745,15 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
(const nsStyleStruct*&) spacing);
switch (spacing->mFloatEdge) {
default:
case NS_STYLE_FLOAT_EDGE_CONTENT:
case NS_STYLE_FLOAT_EDGE_CONTENT: // content and only content does runaround of floaters
// The child block will flow around the floater. Therefore
// give it all of the available space.
aResult.x = borderPadding.left;
aResult.width = mUnconstrainedWidth
? NS_UNCONSTRAINEDSIZE
: mContentArea.width;
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
break;
case NS_STYLE_FLOAT_EDGE_BORDER:
case NS_STYLE_FLOAT_EDGE_PADDING:
{
// The child block's border should be placed adjacent to,
@ -819,6 +822,9 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
aResult.x = mAvailSpaceRect.x + borderPadding.left;
aResult.width = mAvailSpaceRect.width;
}
#ifdef REALLY_NOISY_REFLOW
printf(" CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
#endif
}
PRBool
@ -1069,7 +1075,11 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
mSpaceManager->AddRectRegion(floater, fc->mRegion);
fc = fc->Next();
}
#ifdef DEBUG
if (gNoisyReflow || gNoisySpaceManager) {
mSpaceManager->List(stdout);
}
#endif
// And then put the translation back again
mSpaceManager->Translate(bp.left, bp.top);
}
@ -1394,8 +1404,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
if (gNoisyReflow) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n",
aReflowState.availableWidth, aReflowState.availableHeight,
printf(": begin reflow type %d availSize=%d,%d computedSize=%d,%d\n",
aReflowState.reason, aReflowState.availableWidth, aReflowState.availableHeight,
aReflowState.mComputedWidth, aReflowState.mComputedHeight);
}
if (gNoisy) {
@ -1437,6 +1447,9 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
// Set the space manager in the existing reflow state
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
reflowState.mSpaceManager = spaceManager.get();
#ifdef NOISY_SPACEMANAGER
printf("constructed new space manager %p\n", reflowState.mSpaceManager);
#endif
}
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
@ -1621,23 +1634,45 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
}
}
// see if verifyReflow is enabled, and if so store off the space manager pointer
#ifdef DEBUG
PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();
if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)
{
// this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
nsISpaceManager *spaceManager = reflowState.mSpaceManager;
NS_ADDREF(spaceManager);
rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::spaceManagerProperty,
reflowState.mSpaceManager, nsnull /* should be nsSpaceManagerDestroyer*/);
}
}
}
#endif
// If we set the space manager, then restore the old space manager now that we're
// going out of scope
if (NS_BLOCK_SPACE_MGR & mState) {
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
#ifdef NOISY_SPACEMANAGER
printf("restoring old space manager %p\n", oldSpaceManager);
#endif
reflowState.mSpaceManager = oldSpaceManager;
}
#if 0
#ifdef NOISY_SPACEMANAGER
if (eReflowReason_Incremental == aReflowState.reason) {
if (mSpaceManager) {
ListTag(stdout);
printf(": space-manager after reflow\n");
mSpaceManager->List(stdout);
}
nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState;
if (reflowState.mSpaceManager) {
ListTag(stdout);
printf(": space-manager %p after reflow\n", reflowState.mSpaceManager);
reflowState.mSpaceManager->List(stdout);
}
#endif
#endif
// If this is an incremental reflow and we changed size, then make sure our
@ -2364,6 +2399,12 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
else {
// We can avoid reflowing *some* inline lines in some cases.
#ifdef REALLY_NOISY_REFLOW
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
line, line->IsImpactedByFloater() ? "" : "not ");
#endif
if (notWrapping) {
// When no-wrap is set then the only line-breaking that
// occurs for inline lines is triggered by BR elements or by
@ -2525,7 +2566,11 @@ nsBlockFrame::PropogateReflowDamage(nsBlockReflowState& aState,
//then we don't need to mark the line dirty.
aState.GetAvailableSpace(next->mBounds.y + aDeltaY);
PRBool wasImpactedByFloater = next->IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater();
PRBool isImpactedByFloater = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropogateReflowDamage %p was = %d, is=%d\n",
this, wasImpactedByFloater, isImpactedByFloater);
#endif
if (wasImpactedByFloater != isImpactedByFloater) {
next->MarkDirty();
}
@ -2659,10 +2704,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (NS_FAILED(rv)) {
return rv;
}
if (!(NS_FRAME_IS_COMPLETE(aState.mReflowStatus)))
{
printf("line %p is not complete\n", line);
}
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line);
@ -2826,7 +2867,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
/**
* Reflow a line. The line will either contain a single block frame
* or contain 1 or more inline frames. aLineReflowStatus indicates
* or contain 1 or more inline frames. aKeepReflowGoing indicates
* whether or not the caller should continue to reflow more lines.
*/
nsresult
@ -3512,7 +3553,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Compute the available space for the block
aState.GetAvailableSpace();
aLine->SetLineIsImpactedByFloater(aState.IsImpactedByFloater());
#ifdef REALLY_NOISY_REFLOW
printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");
#endif
PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(isImpacted);
nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;
frame->IsSplittable(splitType);
nsRect availSpace;
@ -3855,8 +3900,12 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// into. Apply a previous block frame's bottom margin first.
aState.mY += aState.mPrevBottomMargin;
aState.GetAvailableSpace();
PRBool impactedByFloaters = aState.IsImpactedByFloater();
PRBool impactedByFloaters = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;
aLine->SetLineIsImpactedByFloater(impactedByFloaters);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, impactedByFloaters);
#endif
const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
@ -4697,10 +4746,10 @@ nsBlockFrame::DrainOverflowLines(nsIPresContext* aPresContext)
// we are told to reflow again before a next-in-flow is created
// and reflows.
nsLineBox* lastLine = nsLineBox::LastLine(mLines);
if (nsnull == lastLine) {
mLines = overflowLines;
if (nsnull == lastLine) { // if we had no lines before the drain operation
mLines = overflowLines; // set our mLines to the overflow
}
else {
else { // otherwise, append the overflow to the mLines list
lastLine->mNext = overflowLines;
nsIFrame* lastFrame = lastLine->LastChild();
lastFrame->SetNextSibling(overflowLines->mFirstChild);

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

@ -32,10 +32,16 @@
#include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h"
#undef NOISY_FINAL_SIZE
#ifdef DEBUG
#undef NOISY_PUSHING
#endif
nsIID nsInlineFrame::kInlineFrameCID = NS_INLINE_FRAME_CID;
//////////////////////////////////////////////////////////////////////
// Basic nsInlineFrame methods
@ -426,6 +432,9 @@ nsInlineFrame::ReflowFrames(nsIPresContext* aPresContext,
PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
PRBool isComplete;
frame = PullOneFrame(aPresContext, irs, &isComplete);
#ifdef NOISY_PUSHING
printf("%p pulled up %p\n", this, frame);
#endif
if (nsnull == frame) {
if (!isComplete) {
aStatus = NS_FRAME_NOT_COMPLETE;
@ -668,6 +677,10 @@ nsInlineFrame::PushFrames(nsIPresContext* aPresContext,
NS_PRECONDITION(prevNextSibling == aFromChild, "bad prev sibling");
#endif
#ifdef NOISY_PUSHING
printf("%p pushing aFromChild %p, disconnecting from prev sib %p\n",
this, aFromChild, aPrevSibling);
#endif
// Disconnect aFromChild from its previous sibling
aPrevSibling->SetNextSibling(nsnull);

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

@ -153,8 +153,8 @@ nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const
{
PR_snprintf(aBuf, aBufSize, "%s,%s,%s,%s[0x%x]",
IsBlock() ? "block" : "inline",
IsDirty() ? "dirty" : "",
IsImpactedByFloater() ? "impacted" : "",
IsDirty() ? "dirty" : "clean",
IsImpactedByFloater() ? "IMPACTED" : "NOT Impacted",
IsTrimmed() ? "trimmed" : "",
mAllFlags);
return aBuf;
@ -353,16 +353,15 @@ nsLineBox::FreeFloaters(nsFloaterCacheFreeList& aFreeList)
void
nsLineBox::RemoveFloatersFromSpaceManager(nsISpaceManager* aSpaceManager)
{
{
if (IsInline()) {
if (mInlineData) {
nsFloaterCache* floaterCache = mInlineData->mFloaters.Head();
while (floaterCache) {
nsIFrame* floater = floaterCache->mPlaceholder->GetOutOfFlowFrame();
aSpaceManager->RemoveRegion(floater);
floaterCache = floaterCache->Next();
floaterCache = floaterCache->Next();
}
}
}
@ -370,7 +369,7 @@ nsLineBox::RemoveFloatersFromSpaceManager(nsISpaceManager* aSpaceManager)
void
nsLineBox::AppendFloaters(nsFloaterCacheFreeList& aFreeList)
{
{
NS_ABORT_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline()) {
if (aFreeList.NotEmpty()) {
@ -404,7 +403,7 @@ nsLineBox::RemoveFloater(nsIFrame* aFrame)
void
nsLineBox::SetCombinedArea(const nsRect& aCombinedArea)
{
{
NS_ASSERTION(aCombinedArea.width >= 0, "illegal width for combined area");
NS_ASSERTION(aCombinedArea.height >= 0, "illegal height for combined area");
if (aCombinedArea != mBounds) {
@ -428,13 +427,22 @@ nsLineBox::SetCombinedArea(const nsRect& aCombinedArea)
}
MaybeFreeData();
}
#ifdef VERY_NOISY_REFLOW
printf("nsLB::SetCombinedArea(1) %p (%d, %d, %d, %d)\n",
this, aCombinedArea.x, aCombinedArea.y, aCombinedArea.width, aCombinedArea.height);
#endif
}
void
nsLineBox::GetCombinedArea(nsRect* aResult)
{
NS_ASSERTION(aResult, "null arg");
if (aResult) {
*aResult = mData ? mData->mCombinedArea : mBounds;
#ifdef VERY_NOISY_REFLOW
printf("nsLB::SetCombinedArea(1) %p (%d, %d, %d, %d)\n",
this, aResult->x, aResult->y, aResult->width, aResult->height);
#endif
}
}

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

@ -189,6 +189,7 @@ public:
// mImpactedByFloater bit
void SetLineIsImpactedByFloater(PRBool aValue) {
NS_ASSERTION((PR_FALSE==aValue || PR_TRUE==aValue), "somebody is playing fast and loose with bools and bits!");
mFlags.mImpactedByFloater = aValue;
}
PRBool IsImpactedByFloater() const {
@ -197,6 +198,7 @@ public:
// mTrimmed bit
void SetTrimmed(PRBool aOn) {
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
mFlags.mTrimmed = aOn;
}
PRBool IsTrimmed() const {
@ -205,6 +207,7 @@ public:
// mHasPercentageChild bit
void SetHasPercentageChild(PRBool aOn) {
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
mFlags.mHasPercentageChild = aOn;
}
PRBool HasPercentageChild() const {
@ -213,6 +216,7 @@ public:
// mLineWrapped bit
void SetLineWrapped(PRBool aOn) {
NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!");
mFlags.mLineWrapped = aOn;
}
PRBool IsLineWrapped() const {

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

@ -235,6 +235,10 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
PRBool aImpactedByFloaters,
PRBool aIsTopOfPage)
{
#ifdef REALLY_NOISY_REFLOW
printf("nsLL::BeginLineReflow %d, %d, %d, %d, impacted=%s\n",
aX, aY, aWidth, aHeight, aImpactedByFloaters?"true":"false");
#endif
NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
#ifdef DEBUG
if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) {
@ -350,6 +354,10 @@ nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
PRBool aPlacedLeftFloater,
nsIFrame* aFloaterFrame)
{
#ifdef REALLY_NOISY_REFLOW
printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p placedLeft=%s\n will set mImpacted to PR_TRUE",
aX, aY, aWidth, aHeight, aFloaterFrame, aPlacedLeftFloater?"true":"false");
#endif
PerSpanData* psd = mRootSpan;
NS_PRECONDITION(psd->mX == psd->mLeftEdge, "update-band called late");
#ifdef DEBUG

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

@ -22,6 +22,7 @@
#define PL_ARENA_CONST_ALIGN_MASK 3
#include "nsIPresShell.h"
#include "nsISpaceManager.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsIDocument.h"
@ -48,6 +49,7 @@
#include "nsIDOMSelection.h"
#include "nsISelectionController.h"
#include "nsLayoutCID.h"
#include "nsLayoutAtoms.h"
#include "nsIDOMRange.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h"
@ -573,15 +575,7 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrameManager* aFrameManager)
* means that you cannot perform logging before then.
*/
static PRLogModuleInfo* gLogModule;
static PRUint32 gVerifyReflowFlags;
#define VERIFY_REFLOW_ON 0x01
#define VERIFY_REFLOW_NOISY 0x02
#define VERIFY_REFLOW_ALL 0x04
#define VERIFY_REFLOW_DUMP_COMMANDS 0x08
#define VERIFY_REFLOW_NOISY_RC 0x10
#define VERIFY_REFLOW_REALLY_NOISY_RC 0x20
#endif
static PRBool gVerifyReflowEnabled;
@ -627,6 +621,12 @@ nsIPresShell::SetVerifyReflowEnable(PRBool aEnabled)
gVerifyReflowEnabled = aEnabled;
}
NS_LAYOUT PRInt32
nsIPresShell::GetVerifyReflowFlags()
{
return gVerifyReflowFlags;
}
//----------------------------------------------------------------------
NS_LAYOUT nsresult
@ -1406,6 +1406,13 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
#endif
}
ExitReflowLock(PR_TRUE);
// if the proper flag is set, VerifyReflow now
if (GetVerifyReflowEnable() && (VERIFY_REFLOW_DURING_RESIZE_REFLOW & gVerifyReflowFlags))
{
mInVerifyReflow = PR_TRUE;
PRBool ok = VerifyIncrementalReflow();
mInVerifyReflow = PR_FALSE;
}
return NS_OK; //XXX this needs to be real. MMP
}
@ -3231,6 +3238,8 @@ static PRBool
CompareTrees(nsIPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
nsIPresContext* aSecondPresContext, nsIFrame* aSecondFrame)
{
if (!aFirstPresContext || !aFirstFrame || !aSecondPresContext || !aSecondFrame)
return PR_TRUE;
PRBool ok = PR_TRUE;
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
@ -3305,6 +3314,115 @@ CompareTrees(nsIPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
break;
}
// verify that neither frame has a space manager,
// or they both do and the space managers are equivalent
nsCOMPtr<nsIFrameManager>fm1;
nsCOMPtr<nsIPresShell> ps1;
nsISpaceManager *sm1; // note, no ref counting here
aFirstPresContext->GetShell(getter_AddRefs(ps1));
NS_ASSERTION(ps1, "no pres shell for primary tree!");
ps1->GetFrameManager(getter_AddRefs(fm1));
NS_ASSERTION(fm1, "no frame manager for primary tree!");
fm1->GetFrameProperty((nsIFrame*)k1, nsLayoutAtoms::spaceManagerProperty,
0, (void **)&sm1);
// look at the test frame
nsCOMPtr<nsIFrameManager>fm2;
nsCOMPtr<nsIPresShell> ps2;
nsISpaceManager *sm2; // note, no ref counting here
aSecondPresContext->GetShell(getter_AddRefs(ps2));
NS_ASSERTION(ps2, "no pres shell for test tree!");
ps2->GetFrameManager(getter_AddRefs(fm2));
NS_ASSERTION(fm2, "no frame manager for test tree!");
fm2->GetFrameProperty((nsIFrame*)k2, nsLayoutAtoms::spaceManagerProperty,
0, (void **)&sm2);
// now compare the space managers
if (((nsnull == sm1) && (nsnull != sm2)) ||
((nsnull != sm1) && (nsnull == sm2))) { // one is null, and the other is not
ok = PR_FALSE;
LogVerifyMessage(k1, k2, "space managers are not matched\n");
}
else if (sm1 && sm2) { // both are not null, compare them
// first, compare yMost
nscoord yMost1, yMost2;
nsresult smresult = sm1->YMost(yMost1);
if (NS_ERROR_ABORT != smresult)
{
NS_ASSERTION(NS_SUCCEEDED(smresult), "bad result");
smresult = sm2->YMost(yMost2);
NS_ASSERTION(NS_SUCCEEDED(smresult), "bad result");
if (yMost1 != yMost2) {
LogVerifyMessage(k1, k2, "yMost of space managers differs\n");
}
// now compare bands by sampling
PRInt32 yIncrement = yMost1/100;
if (0==yIncrement) {
yIncrement = 1; // guarantee we make progress in the loop below
}
nscoord yOffset = 0;
for ( ; ok && yOffset < yMost1; yOffset += yIncrement)
{
nscoord small=5, large=100;
nsBandData band1, band2;
nsBandTrapezoid trap1[20], trap2[20];
band1.mSize = band2.mSize = 20;
band1.mTrapezoids = trap1;
band2.mTrapezoids = trap2;
sm1->GetBandData(yOffset, nsSize(small,small), band1);
sm2->GetBandData(yOffset, nsSize(small,small), band2);
if (band1.mCount != band2.mCount)
{ // count mismatch, stop comparing
LogVerifyMessage(k1, k2, "band.mCount of space managers differs\n");
printf("count1= %d, count2=%d, yOffset = %d, size=%d\n",
band1.mCount, band2.mCount, yOffset, small);
ok = PR_FALSE;
}
else // band counts match, compare individual traps
{
PRInt32 trapIndex=0;
for ( ;trapIndex<band1.mCount; trapIndex++)
{
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
trap1[trapIndex].mState == trap2[trapIndex].mState;
if (!match)
{
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
printf ("index %d\n", trapIndex);
}
}
}
// test the larger maxSize
sm1->GetBandData(yOffset, nsSize(large,large), band1);
sm2->GetBandData(yOffset, nsSize(large,large), band2);
if (band1.mCount != band2.mCount)
{ // count mismatch, stop comparing
LogVerifyMessage(k1, k2, "band.mCount of space managers differs\n");
printf("count1= %d, count2=%d, yOffset = %d, size=%d\n",
band1.mCount, band2.mCount, yOffset, small);
ok = PR_FALSE;
}
else // band counts match, compare individual traps
{
PRInt32 trapIndex=0;
for ( ; trapIndex<band1.mCount; trapIndex++)
{
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
trap1[trapIndex].mState == trap2[trapIndex].mState;
if (!match)
{
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
printf ("index %d\n", trapIndex);
}
}
}
}
}
}
// Compare the sub-trees too
if (!CompareTrees(aFirstPresContext, k1, aSecondPresContext, k2)) {
ok = PR_FALSE;