diff --git a/mozilla/content/html/style/src/nsCSSLayout.cpp b/mozilla/content/html/style/src/nsCSSLayout.cpp
index be0fcccdc1a..42755c0a074 100644
--- a/mozilla/content/html/style/src/nsCSSLayout.cpp
+++ b/mozilla/content/html/style/src/nsCSSLayout.cpp
@@ -24,7 +24,6 @@
#include "nsIPresContext.h"
#include "nsRect.h"
#include "nsIPtr.h"
-#include "nsBlockFrame.h"
#include "nsHTMLIIDs.h"
NS_DEF_PTR(nsIStyleContext);
@@ -309,6 +308,7 @@ GetStyleDimension(nsIPresContext* aPresContext,
rv = PR_TRUE;
break;
}
+ aResult = 0;
rs = rs->parentReflowState;
}
}
@@ -338,10 +338,12 @@ nsCSSLayout::GetStyleSize(nsIPresContext* aPresContext,
if (NS_OK == result) {
if (GetStyleDimension(aPresContext, aReflowState, pos, pos->mWidth,
aStyleSize.width)) {
+NS_ASSERTION(aStyleSize.width < 100000, "bad % result");
rv |= NS_SIZE_HAS_WIDTH;
}
if (GetStyleDimension(aPresContext, aReflowState, pos, pos->mHeight,
aStyleSize.height)) {
+NS_ASSERTION(aStyleSize.height < 100000, "bad % result");
rv |= NS_SIZE_HAS_HEIGHT;
}
}
diff --git a/mozilla/layout/Makefile b/mozilla/layout/Makefile
index f85dc453da3..77f2a7a3fa0 100644
--- a/mozilla/layout/Makefile
+++ b/mozilla/layout/Makefile
@@ -17,7 +17,7 @@
DEPTH = ..
-DIRS = base html events build
+DIRS = base css html events build
include $(DEPTH)/config/config.mk
diff --git a/mozilla/layout/base/src/nsContainerFrame.cpp b/mozilla/layout/base/src/nsContainerFrame.cpp
index c96d018c776..440297ed1d3 100644
--- a/mozilla/layout/base/src/nsContainerFrame.cpp
+++ b/mozilla/layout/base/src/nsContainerFrame.cpp
@@ -118,7 +118,8 @@ NS_METHOD
nsContainerFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
- NS_FRAME_TRACE_MSG(("enter nsContainerFrame::DidReflow: status=%d",
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("enter nsContainerFrame::DidReflow: status=%d",
aStatus));
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
nsFrameState state;
@@ -492,7 +493,6 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
// the right parent to do the removal (it's possible that the
// parent is not this because we are executing pullup code)
nsIFrame* parent;
-
aKidFrame->GetGeometricParent(parent);
((nsContainerFrame*)parent)->DeleteChildsNextInFlow(aKidFrame);
}
@@ -510,7 +510,8 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
* @param aChild child this child's next-in-flow
* @return PR_TRUE if successful and PR_FALSE otherwise
*/
-PRBool nsContainerFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
+PRBool
+nsContainerFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
{
NS_PRECONDITION(IsChild(aChild), "bad geometric parent");
@@ -527,7 +528,7 @@ PRBool nsContainerFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
nextInFlow->GetNextInFlow(nextNextInFlow);
if (nsnull != nextNextInFlow) {
- ((nsContainerFrame*)parent)->DeleteChildsNextInFlow(nextInFlow);
+ parent->DeleteChildsNextInFlow(nextInFlow);
}
#ifdef NS_DEBUG
@@ -594,17 +595,11 @@ PRBool nsContainerFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
WillDeleteNextInFlowFrame(nextInFlow);
nextInFlow->DeleteFrame();
parent->mChildCount--;
-#ifdef NS_DEBUG
-#if XXX_new_block_doesn_t_work_with_this_check
- if (0 != parent->mChildCount) {
- parent->CheckContentOffsets();
- }
-#endif
+#ifdef NS_DEBUG
aChild->GetNextInFlow(nextInFlow);
NS_POSTCONDITION(nsnull == nextInFlow, "non null next-in-flow");
#endif
-
return PR_TRUE;
}
@@ -766,74 +761,6 @@ void nsContainerFrame::PushChildren(nsIFrame* aFromChild,
}
}
-// Note: mLastContentIsComplete is not set correctly by this routine
-// (we don't always know the correct value at this time)
-nsIFrame* nsContainerFrame::PullUpOneChild(nsContainerFrame* aNextInFlow,
- nsIFrame* aLastChild)
-{
- NS_PRECONDITION(nsnull != aNextInFlow, "null ptr");
-#ifdef NS_DEBUG
- if (nsnull != aLastChild) {
- NS_PRECONDITION(IsLastChild(aLastChild), "bad last child");
- }
-#endif
-
- // Get first available frame from the next-in-flow
- NS_ASSERTION(nsnull == aNextInFlow->mOverflowList, "bad next in flow");
- nsIFrame* kidFrame = aNextInFlow->mFirstChild;
- if (nsnull == kidFrame) {
- return nsnull;
- }
-
-#ifdef NOISY
- ListTag(stdout);
- printf(": pulled ");
- kidFrame->ListTag(stdout);
- printf("\n");
-#endif
-
- // Take the frame away from the next-in-flow. Update it's first
- // content offset and propagate upward the offset if the
- // next-in-flow is a pseudo-frame.
- kidFrame->GetNextSibling(aNextInFlow->mFirstChild);
- aNextInFlow->mChildCount--;
- if (nsnull != aNextInFlow->mFirstChild) {
- aNextInFlow->SetFirstContentOffset(aNextInFlow->mFirstChild);
- if (aNextInFlow->IsPseudoFrame()) {
- aNextInFlow->PropagateContentOffsets();
- }
- } else {
-#ifdef NOISY
- ListTag(stdout);
- printf(": drained next-in-flow %p\n", aNextInFlow);
-#endif
- }
-
- // Now give the frame to this container
- kidFrame->SetGeometricParent(this);
-
- nsIFrame* contentParent;
-
- kidFrame->GetContentParent(contentParent);
- if (aNextInFlow == contentParent) {
- kidFrame->SetContentParent(this);
- }
- if (nsnull == aLastChild) {
- mFirstChild = kidFrame;
- SetFirstContentOffset(kidFrame);
- // If we are a pseudo-frame propagate our first offset upward
- if (IsPseudoFrame()) {
- PropagateContentOffsets();
- }
- } else {
- aLastChild->SetNextSibling(kidFrame);
- }
- kidFrame->SetNextSibling(nsnull);
- mChildCount++;
-
- return kidFrame;
-}
-
/**
* Moves any frames on the overflwo lists (the prev-in-flow's overflow list and
* the receiver's overflow list) to the child list.
@@ -1020,9 +947,6 @@ NS_METHOD nsContainerFrame::List(FILE* out, PRInt32 aIndent) const
// Output the children
if (mChildCount > 0) {
- if (!mLastContentIsComplete) {
- fputs(", !complete", out);
- }
if (0 != mState) {
fprintf(out, " [state=%08x]", mState);
}
diff --git a/mozilla/layout/base/src/nsContainerFrame.h b/mozilla/layout/base/src/nsContainerFrame.h
index 18eadcfae0e..0c13ee7937a 100644
--- a/mozilla/layout/base/src/nsContainerFrame.h
+++ b/mozilla/layout/base/src/nsContainerFrame.h
@@ -190,7 +190,7 @@ public:
*
* It's a precondition that this frame must be a pseudo-frame.
*/
- void PropagateContentOffsets();
+ virtual void PropagateContentOffsets();
protected:
// Constructor. Takes as arguments the content object, the index in parent,
@@ -237,22 +237,16 @@ protected:
*/
PRBool MoveOverflowToChildList();
- /**
- * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow
- * pointers
- *
- * Updates the child count and content offsets of all containers that are
- * affected
- *
- * @param aChild child this child's next-in-flow
- * @return PR_TRUE if successful and PR_FALSE otherwise
- */
- PRBool DeleteChildsNextInFlow(nsIFrame* aChild);
-
- static PRBool DeleteNextInFlowsFor(nsContainerFrame* aParent, nsIFrame* aKid)
- {
- return aParent->DeleteChildsNextInFlow(aKid);
- }
+ /**
+ * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow
+ * pointers.
+ *
+ * Updates the child count and content offsets of all containers that are
+ * affected.
+ *
+ * @param aChild child this child's next-in-flow
+ */
+ PRBool DeleteChildsNextInFlow(nsIFrame* aChild);
/**
* Push aFromChild and its next siblings to the next-in-flow. Change the
@@ -274,27 +268,6 @@ protected:
void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling,
PRBool aNextInFlowsLastChildIsComplete);
- /**
- * Attempt to pull one child from the next-in-flow, if any. This
- * does everything necessary for the receiving frame and the
- * next-in-flow frame to ensure that the content offsets and
- * mLastContentIsComplete flags are correct, and it makes sure that
- * the parent offsets if this frame or the next is a pseudo-frame
- * are correct. If there are no children to pull from the next
- * in flow, nsnull is returned.
- *
- * If the caller decides that it doesn't want the child from the
- * next in flow, it can call PushChildren to push it back.
- *
- * @param aNextInFlow the next-in-flow frame to attempt to pull a child
- * from
- * @param aLastChild the current last child for this frame. If a child
- * is pullable then the child will become aLastChild's next
- * sibling
- */
- nsIFrame* PullUpOneChild(nsContainerFrame* aNextInFlow,
- nsIFrame* aLastChild);
-
/**
* Called after pulling-up children from the next-in-flow. Adjusts the first
* content offset of all the empty next-in-flows
diff --git a/mozilla/layout/base/src/nsFrame.cpp b/mozilla/layout/base/src/nsFrame.cpp
index 547bfe39e0b..18a68afc6eb 100644
--- a/mozilla/layout/base/src/nsFrame.cpp
+++ b/mozilla/layout/base/src/nsFrame.cpp
@@ -1026,7 +1026,8 @@ nsFrame::SetFrameState(nsFrameState aNewState)
NS_METHOD
nsFrame::WillReflow(nsIPresContext& aPresContext)
{
- NS_FRAME_TRACE_MSG(("WillReflow: oldState=%x", mState));
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("WillReflow: oldState=%x", mState));
mState |= NS_FRAME_IN_REFLOW;
return NS_OK;
}
@@ -1035,7 +1036,8 @@ NS_METHOD
nsFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
- NS_FRAME_TRACE_MSG(("nsFrame::DidReflow: aStatus=%d", aStatus));
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("nsFrame::DidReflow: aStatus=%d", aStatus));
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW);
diff --git a/mozilla/layout/base/src/nsFrame.h b/mozilla/layout/base/src/nsFrame.h
index c0c4aacd875..bfbd34f63ba 100644
--- a/mozilla/layout/base/src/nsFrame.h
+++ b/mozilla/layout/base/src/nsFrame.h
@@ -34,6 +34,7 @@
#define NS_FRAME_TRACE_CALLS 0x1
#define NS_FRAME_TRACE_PUSH_PULL 0x2
#define NS_FRAME_TRACE_CHILD_REFLOW 0x4
+#define NS_FRAME_TRACE_NEW_FRAMES 0x8
#define NS_FRAME_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit))
@@ -48,17 +49,36 @@
#define NS_FRAME_LOG(_bit,_args)
#endif
+// XXX Need to rework this so that logging is free when it's off
#ifdef NS_DEBUG
#define NS_FRAME_TRACE_IN(_method) Trace(_method, PR_TRUE)
+
#define NS_FRAME_TRACE_OUT(_method) Trace(_method, PR_FALSE)
-#define NS_FRAME_TRACE_MSG(_args) TraceMsg _args
+
+// XXX remove me
+#define NS_FRAME_TRACE_MSG(_bit,_args) \
+ PR_BEGIN_MACRO \
+ if (NS_FRAME_LOG_TEST(nsIFrame::GetLogModuleInfo(),_bit)) { \
+ TraceMsg _args; \
+ } \
+ PR_END_MACRO
+
+#define NS_FRAME_TRACE(_bit,_args) \
+ PR_BEGIN_MACRO \
+ if (NS_FRAME_LOG_TEST(nsIFrame::GetLogModuleInfo(),_bit)) { \
+ TraceMsg _args; \
+ } \
+ PR_END_MACRO
+
#define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, PR_TRUE)
+
#define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
Trace(_method, PR_FALSE, _status)
+
#else
#define NS_FRAME_TRACE_IN(_method)
#define NS_FRAME_TRACE_OUT(_method)
-#define NS_FRAME_TRACE_MSG(_args)
+#define NS_FRAME_TRACE_MSG(_bits,_args)
#define NS_FRAME_TRACE_REFLOW_IN(_method)
#define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
#endif
diff --git a/mozilla/layout/base/src/nsSplittableFrame.cpp b/mozilla/layout/base/src/nsSplittableFrame.cpp
index eb6657c6f98..22e79414a06 100644
--- a/mozilla/layout/base/src/nsSplittableFrame.cpp
+++ b/mozilla/layout/base/src/nsSplittableFrame.cpp
@@ -87,6 +87,8 @@ nsSplittableFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
// Append the continuing frame to the flow
aContinuingFrame->AppendToFlow(this);
+ // XXX remove this!
+
// Resolve style for the continuing frame and set its style context.
nsIStyleContext* styleContext =
aPresContext->ResolveStyleContextFor(mContent, aParent);
diff --git a/mozilla/layout/build/makefile.win b/mozilla/layout/build/makefile.win
index 5db17e6f42d..653788fa3ef 100644
--- a/mozilla/layout/build/makefile.win
+++ b/mozilla/layout/build/makefile.win
@@ -35,6 +35,7 @@ DLL=.\$(OBJDIR)\$(DLLNAME).dll
MISCDEP = \
$(DIST)\lib\raptorlayout_s.lib \
$(DIST)\lib\raptorhtmlbase_s.lib \
+ $(DIST)\lib\nglcsslay_s.lib \
$(DIST)\lib\raptorhtmldoc_s.lib \
$(DIST)\lib\raptorhtmlforms_s.lib \
$(DIST)\lib\raptorhtmlstyle_s.lib \
@@ -59,6 +60,7 @@ LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I..\..\style\src
LLIBS= \
$(DIST)\lib\raptorlayout_s.lib \
$(DIST)\lib\raptorhtmlbase_s.lib \
+ $(DIST)\lib\nglcsslay_s.lib \
$(DIST)\lib\raptorhtmldoc_s.lib \
$(DIST)\lib\raptorhtmlforms_s.lib \
$(DIST)\lib\raptorhtmlstyle_s.lib \
diff --git a/mozilla/layout/css/layout/src/nsCSSBlockFrame.cpp b/mozilla/layout/css/layout/src/nsCSSBlockFrame.cpp
index 24534a533c3..aa1bf454934 100644
--- a/mozilla/layout/css/layout/src/nsCSSBlockFrame.cpp
+++ b/mozilla/layout/css/layout/src/nsCSSBlockFrame.cpp
@@ -93,7 +93,7 @@ struct LineData;
#define DTPF 1
// XXX temporary until PropagateContentOffsets can be written genericly
-#define nsCSSBlockFrameSuper nsContainerFrame
+#define nsCSSBlockFrameSuper nsCSSContainerFrame
class nsCSSBlockFrame : public nsCSSBlockFrameSuper,
public nsIRunaround,
@@ -113,7 +113,6 @@ public:
NS_IMETHOD NextChild(const nsIFrame* aChild, nsIFrame*& aNextChild) const;
NS_IMETHOD PrevChild(const nsIFrame* aChild, nsIFrame*& aPrevChild) const;
NS_IMETHOD LastChild(nsIFrame*& aLastChild) const;
- NS_IMETHOD DeleteChildsNextInFlow(nsIFrame* aNextInFlow);
NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext,
nsIFrame* aParent,
@@ -127,6 +126,13 @@ public:
nsIContent* aContainer);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
+ NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus);
+ NS_IMETHOD GetCursorAt(nsIPresContext& aPresContext,
+ const nsPoint& aPoint,
+ nsIFrame** aFrame,
+ PRInt32& aCursor);
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
NS_IMETHOD ListTag(FILE* out) const;
NS_IMETHOD VerifyTree() const;
@@ -156,6 +162,7 @@ protected:
PRBool GetLastContentIsComplete() const;
#endif
+ virtual PRBool DeleteNextInFlowsFor(nsIFrame* aNextInFlow);
nsresult DrainOverflowLines();
@@ -165,8 +172,6 @@ protected:
//XXX void PropagateContentOffsets();
- //XXX virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow);
-
PRIntn GetSkipSides() const;
PRBool IsPseudoFrame() const;
@@ -322,6 +327,16 @@ LineData::~LineData()
}
}
+static void
+ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
+{
+ PRInt32 i, n = aFloaters->Count();
+ for (i = 0; i < n; i++) {
+ nsIFrame* frame = (nsIFrame*) aFloaters->ElementAt(i);
+ frame->List(out, aIndent);
+ }
+}
+
void
LineData::List(FILE* out, PRInt32 aIndent) const
{
@@ -341,12 +356,8 @@ LineData::List(FILE* out, PRInt32 aIndent) const
for (i = aIndent; --i >= 0; ) fputs(" ", out);
if (nsnull != mFloaters) {
- PRInt32 j, n = mFloaters->Count();
- fprintf(out, "> #floaters=%d<\n", n);
- for (j = 0; j < n; j++) {
- nsIFrame* frame = (nsIFrame*) mFloaters->ElementAt(j);
- frame->List(out, aIndent + 1);
- }
+ fputs("> bcl-floaters=<\n", out);
+ ListFloaters(out, aIndent + 1, mFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out);
}
fputs(">\n", out);
@@ -445,10 +456,22 @@ VerifyChildCount(LineData* aLines, PRBool aEmptyOK = PR_FALSE)
static void
DeleteLineList(LineData* aLine)
{
- while (nsnull != aLine) {
- LineData* next = aLine->mNext;
- delete aLine;
- aLine = next;
+ if (nsnull != aLine) {
+ // Delete our child frames before doing anything else. In particular
+ // we do all of this before our base class releases it's hold on the
+ // view.
+ for (nsIFrame* child = aLine->mFirstChild; child; ) {
+ nsIFrame* nextChild;
+ child->GetNextSibling(nextChild);
+ child->DeleteFrame();
+ child = nextChild;
+ }
+
+ while (nsnull != aLine) {
+ LineData* next = aLine->mNext;
+ delete aLine;
+ aLine = next;
+ }
}
}
@@ -532,7 +555,7 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
nsCSSBlockFrame* aBlock,
nsIStyleContext* aBlockSC,
const nsReflowState& aReflowState,
- nsSize* aMaxElementSize)
+ PRBool aComputeMaxElementSize)
: nsReflowState(aBlock, *aReflowState.parentReflowState,
aReflowState.maxSize),
mLineLayout(aPresContext, aSpaceManager),
@@ -553,12 +576,10 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
mY = 0;
mUnconstrainedWidth = aReflowState.maxSize.width == NS_UNCONSTRAINEDSIZE;
mUnconstrainedHeight = aReflowState.maxSize.height == NS_UNCONSTRAINEDSIZE;
- mMaxElementSize = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- // XXX CAN'T pass our's to an inline child frame because it will
- // do the same thing...
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
+ mComputeMaxElementSize = aComputeMaxElementSize;
+ if (mComputeMaxElementSize) {
+ mMaxElementSize.width = 0;
+ mMaxElementSize.height = 0;
}
// Set mNoWrap flag
@@ -578,9 +599,18 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
aBlockSC->GetStyleData(eStyleStruct_Display);
mDirection = styleDisplay->mDirection;
+ if (NS_STYLE_DISPLAY_LIST_ITEM == styleDisplay->mDisplay) {
+ const nsStyleList* sl = (const nsStyleList*)
+ aBlockSC->GetStyleData(eStyleStruct_List);
+ if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == sl->mListStylePosition) {
+ mLineLayout.mListPositionOutside = PR_TRUE;
+ }
+ }
+
// Apply border and padding adjustments for regular frames only
nsRect blockRect;
mBlock->GetRect(blockRect);
+ mStyleSizeFlags = 0;
if (!mBlockIsPseudo) {
const nsStyleSpacing* blockSpacing = (const nsStyleSpacing*)
aBlockSC->GetStyleData(eStyleStruct_Spacing);
@@ -665,9 +695,17 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
nsCSSBlockReflowState::~nsCSSBlockReflowState()
{
- // XXX release free list
+ LineData* line = mFreeList;
+ while (nsnull != line) {
+ NS_ASSERTION((0 == line->mChildCount) && (nsnull == line->mFirstChild),
+ "bad free line");
+ LineData* next = line->mNext;
+ delete line;
+ line = next;
+ }
}
+// XXX I think the handling of mBorderPadding.left is weird here.
void
nsCSSBlockReflowState::GetAvailableSpace()
{
@@ -675,15 +713,18 @@ nsCSSBlockReflowState::GetAvailableSpace()
nsISpaceManager* sm = mSpaceManager;
- // Fill in band data for the specific Y coordinate
- sm->Translate(mBorderPadding.left, mY);
- sm->GetBandData(0, mInnerSize, mCurrentBand);
- sm->Translate(-mBorderPadding.left, -mY);
+ // Fill in band data for the specific Y coordinate. Note: We don't
+ // translate by Y so that the band will be absolute (at least in y);
+ // this makes the implementation of ClearFloaters simpler.
+ sm->Translate(mBorderPadding.left, 0);
+ sm->GetBandData(mY, mInnerSize, mCurrentBand);
+ sm->Translate(-mBorderPadding.left, 0);
// Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
+ // between any left and right floaters. The availSpace is translated
+ // after it's computed to be fully absolute.
mCurrentBand.ComputeAvailSpaceRect();
- mCurrentBand.availSpace.MoveBy(mBorderPadding.left, mY);
+ mCurrentBand.availSpace.MoveBy(mBorderPadding.left, 0);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsCSSBlockReflowState::GetAvailableSpace: band={%d,%d,%d,%d}",
@@ -731,12 +772,11 @@ nsCSSBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
-#if 0
+ // XXX temporary
if (aIID.Equals(kBlockFrameCID)) {
*aInstancePtr = (void*) (this);
return NS_OK;
}
-#endif
if (aIID.Equals(kIRunaroundIID)) {
*aInstancePtr = (void*) ((nsIRunaround*) this);
return NS_OK;
@@ -839,16 +879,23 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent) const
fprintf(out, "next-in-flow=%p ", mNextInFlow);
}
- // Output the rect
+ // Output the rect and state
out << mRect;
+ if (0 != mState) {
+ fprintf(out, " [state=%08x]", mState);
+ }
+
+ // Dump run-in floaters
+ if (nsnull != mRunInFloaters) {
+ fputs(" run-in-floaters=<\n", out);
+ ListFloaters(out, aIndent + 1, mRunInFloaters);
+ for (i = aIndent; --i >= 0; ) fputs(" ", out);
+ fputs(">", out);
+ }
// Output the children, one line at a time
if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
fputs("<\n", out);
-
aIndent++;
LineData* line = mLines;
while (nsnull != line) {
@@ -856,13 +903,10 @@ nsCSSBlockFrame::List(FILE* out, PRInt32 aIndent) const
line = line->mNext;
}
aIndent--;
-
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
+ }
+ else {
fputs("<>\n", out);
}
@@ -1053,7 +1097,8 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
// more extensive version.
nsCSSBlockReflowState state(aPresContext, aSpaceManager,
this, mStyleContext,
- aReflowState, aMetrics.maxElementSize);
+ aReflowState,
+ PRBool(nsnull != aMetrics.maxElementSize));
nsresult rv = NS_OK;
if (eReflowReason_Initial == state.reason) {
@@ -1264,6 +1309,10 @@ nsCSSBlockFrame::ComputeFinalSize(nsCSSBlockReflowState& aState,
aMetrics.height = aDesiredRect.height;
aMetrics.ascent = aMetrics.height;
aMetrics.descent = 0;
+ if (aState.mComputeMaxElementSize) {
+ *aMetrics.maxElementSize = aState.mMaxElementSize;
+ }
+ NS_ASSERTION(aDesiredRect.width < 1000000, "whoops");
}
// XXX move this somewhere else!!!
@@ -1492,6 +1541,10 @@ nsCSSBlockFrame::ResizeReflow(nsCSSBlockReflowState& aState)
nsresult
nsCSSBlockFrame::ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine)
{
+ if (nsnull != mRunInFloaters) {
+ aState.PlaceBelowCurrentLineFloaters(mRunInFloaters);
+ }
+
// Reflow the lines that are already ours
while (nsnull != aLine) {
nsInlineReflowStatus rs;
@@ -1501,6 +1554,7 @@ nsCSSBlockFrame::ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine)
}
return NS_FRAME_NOT_COMPLETE;
}
+ aState.mLineLayout.NextLine();
aState.mPrevLine = aLine;
aLine = aLine->mNext;
}
@@ -1573,6 +1627,7 @@ nsCSSBlockFrame::ReflowLinesAt(nsCSSBlockReflowState& aState, LineData* aLine)
}
return NS_FRAME_NOT_COMPLETE;
}
+ aState.mLineLayout.NextLine();
aState.mPrevLine = aLine;
aLine = aLine->mNext;
}
@@ -1733,16 +1788,22 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
if (NS_FRAME_FIRST_REFLOW & state) {
reason = eReflowReason_Initial;
}
-#if XXX_fix_me
- else if (nsnull != aState.reflowCommand) {
- reason = eReflowReason_Incremental;
+ else
+ if (nsnull != aState.reflowCommand) {
+ nsIFrame* target;
+ aState.reflowCommand->GetTarget(target);
+ if (this != target) {
+ reason = eReflowReason_Incremental;
+ }
}
-#endif
// Reflow the block frame. Use the run-around API if possible;
// otherwise treat it as a rectangular lump and place it.
nsresult rv;
- nsReflowMetrics metrics(aState.mMaxElementSize);/* XXX mMaxElementSize*/
+ nsSize kidMaxElementSize;
+ nsReflowMetrics metrics(aState.mComputeMaxElementSize
+ ? &kidMaxElementSize
+ : nsnull);
nsReflowStatus reflowStatus;
nsIRunaround* runAround;
if ((nsnull != aState.mSpaceManager) &&
@@ -1752,8 +1813,10 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
nsReflowState reflowState(aFrame, aState, availSize);
reflowState.reason = reason;
nsRect r;
+ aState.mSpaceManager->Translate(x, y);
rv = runAround->Reflow(aState.mPresContext, aState.mSpaceManager,
metrics, reflowState, r, reflowStatus);
+ aState.mSpaceManager->Translate(-x, -y);
metrics.width = r.width;
metrics.height = r.height;
metrics.ascent = r.height;
@@ -1779,7 +1842,7 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
// parent is not this because we are executing pullup code)
nsIFrame* parent;
aFrame->GetGeometricParent(parent);
- parent->DeleteChildsNextInFlow(aFrame);
+ ((nsCSSBlockFrame*)parent)->DeleteNextInFlowsFor(aFrame);
}
aLine->SetLastContentIsComplete();
aReflowResult = NS_INLINE_REFLOW_COMPLETE;
@@ -1801,6 +1864,16 @@ nsCSSBlockFrame::ReflowBlockFrame(nsCSSBlockReflowState& aState,
return PR_FALSE;
}
+ // Update max-element-size
+ if (aState.mComputeMaxElementSize) {
+ if (kidMaxElementSize.width > aState.mMaxElementSize.width) {
+ aState.mMaxElementSize.width = kidMaxElementSize.width;
+ }
+ if (kidMaxElementSize.height > aState.mMaxElementSize.height) {
+ aState.mMaxElementSize.height = kidMaxElementSize.height;
+ }
+ }
+
// Save away bounds before other adjustments
aLine->mBounds.x = x;
aLine->mBounds.y = y;
@@ -1867,8 +1940,9 @@ nsCSSBlockFrame::ReflowInlineFrame(nsCSSBlockReflowState& aState,
nsInlineReflowStatus& aReflowResult)
{
if (!aState.mInlineLayoutPrepared) {
+ aState.mLineLayout.Prepare(aState.mX);
aState.mInlineLayout.Prepare(aState.mUnconstrainedWidth, aState.mNoWrap,
- aState.mMaxElementSize);
+ aState.mComputeMaxElementSize);
aState.mInlineLayout.SetReflowSpace(aState.mCurrentBand.availSpace.x,
aState.mY,
aState.mCurrentBand.availSpace.width,
@@ -2075,6 +2149,17 @@ nsCSSBlockFrame::PlaceLine(nsCSSBlockReflowState& aState,
return PR_FALSE;
}
+ // Update max-element-size
+ if (aState.mComputeMaxElementSize) {
+ nsSize& lineMaxElementSize = aState.mInlineLayout.mMaxElementSize;
+ if (lineMaxElementSize.width > aState.mMaxElementSize.width) {
+ aState.mMaxElementSize.width = lineMaxElementSize.width;
+ }
+ if (lineMaxElementSize.height > aState.mMaxElementSize.height) {
+ aState.mMaxElementSize.height = lineMaxElementSize.height;
+ }
+ }
+
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
@@ -2083,7 +2168,7 @@ nsCSSBlockFrame::PlaceLine(nsCSSBlockReflowState& aState,
// Based on the last child we reflowed reflow status, we may need to
// clear past any floaters.
- PRBool updateReflowSpace = PR_FALSE;
+//XXX PRBool updateReflowSpace = PR_FALSE;
if (NS_INLINE_REFLOW_BREAK_AFTER ==
(aReflowStatus & NS_INLINE_REFLOW_REFLOW_MASK)) {
// Apply break to the line
@@ -2094,8 +2179,11 @@ nsCSSBlockFrame::PlaceLine(nsCSSBlockReflowState& aState,
case NS_STYLE_CLEAR_LEFT:
case NS_STYLE_CLEAR_RIGHT:
case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("nsCSSBlockFrame::PlaceLine: clearing floaters=%d",
+ breakType));
aState.ClearFloaters(breakType);
- updateReflowSpace = PR_TRUE;
+//XXX updateReflowSpace = PR_TRUE;
break;
}
// XXX page breaks, etc, need to be passed upwards too!
@@ -2125,15 +2213,17 @@ nsCSSBlockFrame::PlaceLine(nsCSSBlockReflowState& aState,
// The current y coordinate is now past our available space
// rectangle. Get a new band of space.
aState.GetAvailableSpace();
- updateReflowSpace = PR_TRUE;
+//XXX updateReflowSpace = PR_TRUE;
}
+#if XXX
if (updateReflowSpace) {
aState.mInlineLayout.SetReflowSpace(aState.mCurrentBand.availSpace.x,
aState.mY,
aState.mCurrentBand.availSpace.width,
aState.mCurrentBand.availSpace.height);
}
+#endif
return PR_TRUE;
}
@@ -2280,8 +2370,8 @@ nsCSSBlockFrame::ContentAppended(nsIPresShell* aShell,
return NS_OK;
}
-NS_IMETHODIMP
-nsCSSBlockFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
+PRBool
+nsCSSBlockFrame::DeleteNextInFlowsFor(nsIFrame* aChild)
{
NS_PRECONDITION(IsChild(aChild), "bad geometric parent");
@@ -2297,7 +2387,7 @@ nsCSSBlockFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
nsIFrame* nextNextInFlow;
nextInFlow->GetNextInFlow(nextNextInFlow);
if (nsnull != nextNextInFlow) {
- parent->DeleteChildsNextInFlow(nextInFlow);
+ parent->DeleteNextInFlowsFor(nextInFlow);
}
#ifdef NS_DEBUG
@@ -2351,7 +2441,7 @@ nsCSSBlockFrame::DeleteChildsNextInFlow(nsIFrame* aChild)
aChild->GetNextInFlow(nextInFlow);
NS_POSTCONDITION(nsnull == nextInFlow, "non null next-in-flow");
#endif
- return NS_OK;
+ return PR_TRUE;
}
PRBool
@@ -2605,7 +2695,7 @@ nsCSSBlockReflowState::PlaceBelowCurrentLineFloaters(nsVoidArray* aFloaterList)
nsISpaceManager* sm = mSpaceManager;
- // XXX Factor this code with PlaceFloater()...
+ // XXX Factor this code with PlaceCurrentLineFloater()...
nsRect region;
PRInt32 numFloaters = aFloaterList->Count();
for (PRInt32 i = 0; i < numFloaters; i++) {
@@ -2677,21 +2767,33 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
break;
}
- // Find the Y coordinate to clear to
+ // Find the Y coordinate to clear to. Note that the band trapezoid
+ // coordinates are relative to the last translation. Since we
+ // never translate by Y before getting a band, we can use absolute
+ // comparisons against mY.
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: mY=%d trapCount=%d",
+ mY, mCurrentBand.count));
nscoord clearYMost = mY;
nsRect tmp;
PRInt32 i;
for (i = 0; i < mCurrentBand.count; i++) {
const nsStyleDisplay* display;
nsBandTrapezoid* trapezoid = &mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: trap=%d state=%d",
+ i, trapezoid->state));
+ if (nsBandTrapezoid::Available != trapezoid->state) {
if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
PRInt32 fn, numFrames = trapezoid->frames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
+ nsIFrame* frame = (nsIFrame*) trapezoid->frames->ElementAt(fn);
+ frame->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: frame[%d]=%p floats=%d",
+ fn, frame, display->mFloats));
switch (display->mFloats) {
case NS_STYLE_FLOAT_LEFT:
if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
@@ -2700,6 +2802,9 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
nscoord ym = tmp.YMost();
if (ym > clearYMost) {
clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: left clearYMost=%d",
+ clearYMost));
}
}
break;
@@ -2710,6 +2815,9 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
nscoord ym = tmp.YMost();
if (ym > clearYMost) {
clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: right clearYMost=%d",
+ clearYMost));
}
}
break;
@@ -2719,14 +2827,23 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
else {
trapezoid->frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&)display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: frame=%p floats=%d",
+ trapezoid->frame, display->mFloats));
switch (display->mFloats) {
case NS_STYLE_FLOAT_LEFT:
if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
(NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
trapezoid->GetRect(tmp);
nscoord ym = tmp.YMost();
+NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: left? ym=%d clearYMost=%d",
+ ym, clearYMost));
if (ym > clearYMost) {
clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: left clearYMost=%d",
+ clearYMost));
}
}
break;
@@ -2737,6 +2854,9 @@ nsCSSBlockReflowState::ClearFloaters(PRUint8 aBreakType)
nscoord ym = tmp.YMost();
if (ym > clearYMost) {
clearYMost = ym;
+ NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
+ ("nsCSSBlockReflowState::ClearFloaters: right clearYMost=%d",
+ clearYMost));
}
}
break;
@@ -2884,6 +3004,54 @@ nsCSSBlockFrame::PaintChildren(nsIPresContext& aPresContext,
}
}
+// XXX move into nsFrame
+NS_IMETHODIMP
+nsCSSBlockFrame::HandleEvent(nsIPresContext& aPresContext,
+ nsGUIEvent* aEvent,
+ nsEventStatus& aEventStatus)
+{
+ aEventStatus = nsEventStatus_eIgnore;
+
+ nsIFrame* kid = (nsnull == mLines) ? nsnull : mLines->mFirstChild;
+ while (nsnull != kid) {
+ nsRect kidRect;
+ kid->GetRect(kidRect);
+ if (kidRect.Contains(aEvent->point)) {
+ aEvent->point.MoveBy(-kidRect.x, -kidRect.y);
+ kid->HandleEvent(aPresContext, aEvent, aEventStatus);
+ aEvent->point.MoveBy(kidRect.x, kidRect.y);
+ break;
+ }
+ kid->GetNextSibling(kid);
+ }
+
+ return NS_OK;
+}
+
+// XXX move into nsFrame
+NS_IMETHODIMP
+nsCSSBlockFrame::GetCursorAt(nsIPresContext& aPresContext,
+ const nsPoint& aPoint,
+ nsIFrame** aFrame,
+ PRInt32& aCursor)
+{
+ aCursor = NS_STYLE_CURSOR_INHERIT;
+
+ nsIFrame* kid = (nsnull == mLines) ? nsnull : mLines->mFirstChild;
+ nsPoint tmp;
+ while (nsnull != kid) {
+ nsRect kidRect;
+ kid->GetRect(kidRect);
+ if (kidRect.Contains(aPoint)) {
+ tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y);
+ kid->GetCursorAt(aPresContext, tmp, aFrame, aCursor);
+ break;
+ }
+ kid->GetNextSibling(kid);
+ }
+ return NS_OK;
+}
+
//////////////////////////////////////////////////////////////////////
// Debugging
diff --git a/mozilla/layout/css/layout/src/nsCSSBlockFrame.h b/mozilla/layout/css/layout/src/nsCSSBlockFrame.h
index 19d4aed1408..136d7e1ddca 100644
--- a/mozilla/layout/css/layout/src/nsCSSBlockFrame.h
+++ b/mozilla/layout/css/layout/src/nsCSSBlockFrame.h
@@ -19,7 +19,7 @@
#ifndef nsCSSBlockFrame_h___
#define nsCSSBlockFrame_h___
-#include "nsContainerFrame.h"
+#include "nsCSSContainerFrame.h"
#include "nsCSSLineLayout.h"
#include "nsCSSInlineLayout.h"
#include "nsVoidArray.h"
@@ -29,6 +29,10 @@ class nsCSSBlockFrame;
struct nsCSSInlineLayout;
struct LineData;
+/* 52b33130-0b99-11d2-932e-00805f8add32 */
+#define NS_BLOCK_FRAME_CID \
+{ 0x52b33130, 0x0b99, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
+
// XXX hide this as soon as list bullet code is cleaned up
struct nsCSSBlockReflowState : public nsReflowState {
@@ -37,7 +41,7 @@ struct nsCSSBlockReflowState : public nsReflowState {
nsCSSBlockFrame* aBlock,
nsIStyleContext* aBlockSC,
const nsReflowState& aReflowState,
- nsSize* aMaxElementSize);
+ PRBool aComputeMaxElementSize);
~nsCSSBlockReflowState();
@@ -67,14 +71,16 @@ struct nsCSSBlockReflowState : public nsReflowState {
nscoord mDeltaWidth;
nscoord mBottomEdge; // maximum Y
- PRPackedBool mUnconstrainedWidth, mUnconstrainedHeight;
+ PRPackedBool mUnconstrainedWidth;
+ PRPackedBool mUnconstrainedHeight;
PRPackedBool mNoWrap;
+ PRPackedBool mComputeMaxElementSize;
nscoord mX, mY;
nscoord mPrevPosBottomMargin;
nscoord mPrevNegBottomMargin;
nscoord mKidXMost;
- nsSize* mMaxElementSize;
+ nsSize mMaxElementSize;
nsCSSLineLayout mLineLayout;
diff --git a/mozilla/layout/css/layout/src/nsCSSContainerFrame.h b/mozilla/layout/css/layout/src/nsCSSContainerFrame.h
index 8e882139180..d578c4733d4 100644
--- a/mozilla/layout/css/layout/src/nsCSSContainerFrame.h
+++ b/mozilla/layout/css/layout/src/nsCSSContainerFrame.h
@@ -23,25 +23,12 @@
class nsCSSContainerFrame : public nsHTMLContainerFrame {
public:
-#if 0
- NS_IMETHOD ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer);
-#endif
+
+ virtual PRBool DeleteNextInFlowsFor(nsIFrame* aChild) = 0;
protected:
nsCSSContainerFrame(nsIContent* aContent, nsIFrame* aParent);
~nsCSSContainerFrame();
-
-#if 0
- PRInt32 NextChildOffset() const {
- return mLastContentOffset + (mLastContentIsComplete ? 1 : 0);
- }
-
- PRInt32 mFirstContentOffset;
- PRInt32 mLastContentOffset;
- PRBool mLastContentIsComplete; // XXX move into frame-state
-#endif
};
#endif /* nsCSSContainerFrame_h___ */
diff --git a/mozilla/layout/css/layout/src/nsCSSInlineFrame.cpp b/mozilla/layout/css/layout/src/nsCSSInlineFrame.cpp
index 8c142f0e3d8..906fe532271 100644
--- a/mozilla/layout/css/layout/src/nsCSSInlineFrame.cpp
+++ b/mozilla/layout/css/layout/src/nsCSSInlineFrame.cpp
@@ -25,6 +25,15 @@
#include "nsHTMLBase.h"// XXX rename to nsCSSBase?
// XXX TODO:
+
+// test: ...
: make sure that it works in pullup case and
+// non-pullup case
+
+// XXX As coded today, the reflow-status is mapped into
+// complete/not-complete before returning. If we want to support other
+// kinds of breaks we need to return the complete breaking status
+// outward properly.
+
// content appended INCREMENTAL reflow
// content inserted INCREMENTAL reflow
// content deleted INCREMENTAL reflow
@@ -33,7 +42,7 @@ nsCSSInlineReflowState::nsCSSInlineReflowState(nsCSSLineLayout& aLineLayout,
nsCSSInlineFrame* aInlineFrame,
nsIStyleContext* aInlineSC,
const nsReflowState& aRS,
- nsSize* aMaxElementSize)
+ PRBool aComputeMaxElementSize)
: nsReflowState(aInlineFrame, *aRS.parentReflowState, aRS.maxSize),
mInlineLayout(aLineLayout, aInlineFrame, aInlineSC)
{
@@ -52,10 +61,6 @@ nsCSSInlineReflowState::nsCSSInlineReflowState(nsCSSLineLayout& aLineLayout,
aInlineSC->GetStyleData(eStyleStruct_Spacing);
styleSpacing->CalcBorderPaddingFor(aInlineFrame, mBorderPadding);
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->SizeTo(0, 0);
- }
-
// If we're constrained adjust the available size so it excludes space
// needed for border/padding
nscoord width = maxSize.width;
@@ -79,7 +84,7 @@ nsCSSInlineReflowState::nsCSSInlineReflowState(nsCSSLineLayout& aLineLayout,
mInlineLayout.Init(this);
mInlineLayout.Prepare(PRBool(NS_UNCONSTRAINEDSIZE == width),
- mNoWrap, aMaxElementSize);
+ mNoWrap, aComputeMaxElementSize);
mInlineLayout.SetReflowSpace(mBorderPadding.left, mBorderPadding.top,
width, height/* XXX height??? */);
}
@@ -157,6 +162,12 @@ nsCSSInlineFrame::CreateContinuingFrame(nsIPresContext* aCX,
return NS_OK;
}
+PRBool
+nsCSSInlineFrame::DeleteNextInFlowsFor(nsIFrame* aChild)
+{
+ return DeleteChildsNextInFlow(aChild);
+}
+
NS_IMETHODIMP
nsCSSInlineFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
{
@@ -189,7 +200,8 @@ nsCSSInlineFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
}
nsCSSInlineReflowState state(aLineLayout, this, mStyleContext,
- aReflowState, aMetrics.maxElementSize);
+ aReflowState,
+ PRBool(nsnull != aMetrics.maxElementSize));
nsresult rv = NS_OK;
if (eReflowReason_Initial == state.reason) {
MoveOverflowToChildList();
@@ -297,9 +309,14 @@ nsCSSInlineFrame::ComputeFinalSize(nsCSSInlineReflowState& aState,
}
// Adjust max-element size if this frame's no-wrap flag is set.
- if ((nsnull != aMetrics.maxElementSize) && aState.mNoWrap) {
- aMetrics.maxElementSize->width = aMetrics.width;
- aMetrics.maxElementSize->height = aMetrics.height;
+ if (aState.mInlineLayout.mComputeMaxElementSize) {
+ if (aState.mNoWrap) {
+ aMetrics.maxElementSize->width = aMetrics.width;
+ aMetrics.maxElementSize->height = aMetrics.height;
+ }
+ else {
+ *aMetrics.maxElementSize = aState.mInlineLayout.mMaxElementSize;
+ }
}
}
@@ -315,23 +332,23 @@ nsCSSInlineFrame::FrameAppendedReflow(nsCSSInlineReflowState& aState)
// XXX What about the case where the last frame is text or contains
// text and we have just appended more text?
- nsInlineReflowStatus rv = NS_INLINE_REFLOW_COMPLETE;
+ nsInlineReflowStatus rs = NS_INLINE_REFLOW_COMPLETE;
if (0 != mChildCount) {
- rv = ReflowMapped(aState);
- if (IS_REFLOW_ERROR(rv)) {
- return rv;
+ if (!ReflowMapped(aState, rs)) {
+ return rs;
}
}
- if (NS_INLINE_REFLOW_COMPLETE == (NS_INLINE_REFLOW_REFLOW_MASK & rv)) {
+ if (NS_INLINE_REFLOW_COMPLETE == (NS_INLINE_REFLOW_REFLOW_MASK & rs)) {
// Note: There is nothing to pullup because this is a
// frame-appended reflow (therefore we are the last-in-flow)
NS_ASSERTION(nsnull == mNextInFlow, "bad frame-appended-reflow");
// Reflow new children
- rv = ReflowUnmapped(aState);
+ rs = ReflowUnmapped(aState);
}
- return rv;
+
+ return rs;
}
nsInlineReflowStatus
@@ -344,49 +361,51 @@ nsCSSInlineFrame::ChildIncrementalReflow(nsCSSInlineReflowState& aState)
nsInlineReflowStatus
nsCSSInlineFrame::ResizeReflow(nsCSSInlineReflowState& aState)
{
- nsInlineReflowStatus rv = NS_INLINE_REFLOW_COMPLETE;
+ nsInlineReflowStatus rs = NS_INLINE_REFLOW_COMPLETE;
if (0 != mChildCount) {
- rv = ReflowMapped(aState);
- if (IS_REFLOW_ERROR(rv)) {
- return rv;
+ if (!ReflowMapped(aState, rs)) {
+ return rs;
}
}
- if (NS_INLINE_REFLOW_COMPLETE == (NS_INLINE_REFLOW_REFLOW_MASK & rv)) {
+ if (NS_INLINE_REFLOW_COMPLETE == (NS_INLINE_REFLOW_REFLOW_MASK & rs)) {
// Try to fit some more children from our next in flow
if (nsnull != mNextInFlow) {
- rv = PullUpChildren(aState);
+ if (!PullUpChildren(aState, rs)) {
+ return rs;
+ }
}
}
// XXX This is here temporarily until inline is reworked to
// pre-fluff it's frame tree
- if (NS_INLINE_REFLOW_COMPLETE == (NS_INLINE_REFLOW_REFLOW_MASK & rv)) {
+ if (NS_INLINE_REFLOW_COMPLETE == (NS_INLINE_REFLOW_REFLOW_MASK & rs)) {
// Reflow new children
- rv = ReflowUnmapped(aState);
+ rs = ReflowUnmapped(aState);
}
- return rv;
+ return rs;
}
-nsInlineReflowStatus
-nsCSSInlineFrame::ReflowMapped(nsCSSInlineReflowState& aState)
+PRBool
+nsCSSInlineFrame::ReflowMapped(nsCSSInlineReflowState& aState,
+ nsInlineReflowStatus& aReflowStatus)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("enter nsCSSInlineFrame::ReflowMapped: childCount=%d", mChildCount));
nsresult rv;
- nsInlineReflowStatus reflowResult = NS_INLINE_REFLOW_NOT_COMPLETE;
+
+ PRBool keepGoing = PR_FALSE;
PRInt32 kidContentIndex = mFirstContentOffset;
nsIFrame* prevChild = nsnull;
nsIFrame* child = mFirstChild;
while (nsnull != child) {
- nsInlineReflowStatus rs = aState.mInlineLayout.ReflowAndPlaceFrame(child);
- if (IS_REFLOW_ERROR(rs)) {
- reflowResult = rs;
- goto done;
+ aReflowStatus = aState.mInlineLayout.ReflowAndPlaceFrame(child);
+ if (IS_REFLOW_ERROR(aReflowStatus)) {
+ return PR_FALSE;
}
- switch (NS_INLINE_REFLOW_REFLOW_MASK & rs) {
+ switch (NS_INLINE_REFLOW_REFLOW_MASK & aReflowStatus) {
case NS_INLINE_REFLOW_COMPLETE:
prevChild = child;
child->GetNextSibling(child);
@@ -399,8 +418,8 @@ nsCSSInlineFrame::ReflowMapped(nsCSSInlineReflowState& aState)
// won't know to create it.
rv = MaybeCreateNextInFlow(aState, child);
if (NS_OK != rv) {
- reflowResult = nsInlineReflowStatus(rv);
- goto done;
+ aReflowStatus = nsInlineReflowStatus(rv);
+ return PR_FALSE;
}
prevChild = child;
child->GetNextSibling(child);
@@ -423,9 +442,17 @@ nsCSSInlineFrame::ReflowMapped(nsCSSInlineReflowState& aState)
child->GetNextSibling(child);
if (nsnull != child) {
PushKids(aState, prevChild, child);
+ aReflowStatus = NS_INLINE_REFLOW_NOT_COMPLETE;
}
else {
- reflowResult = NS_INLINE_REFLOW_COMPLETE;
+ PRInt32 lastContentIndex;
+ lastContentIndex = mContent->ChildCount();
+ if (++kidContentIndex == lastContentIndex) {
+ aReflowStatus = NS_INLINE_REFLOW_COMPLETE;
+ }
+ else {
+ aReflowStatus = NS_INLINE_REFLOW_NOT_COMPLETE;
+ }
}
goto done;
@@ -434,6 +461,7 @@ nsCSSInlineFrame::ReflowMapped(nsCSSInlineReflowState& aState)
if (nsnull != prevChild) {
mLastContentOffset = kidContentIndex - 1;
PushKids(aState, prevChild, child);
+ aReflowStatus = NS_INLINE_REFLOW_NOT_COMPLETE;
}
else {
// We are trying to push our only child. It must be a block
@@ -451,148 +479,19 @@ nsCSSInlineFrame::ReflowMapped(nsCSSInlineReflowState& aState)
}
NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
mLastContentIsComplete = PR_TRUE;
+ keepGoing = PR_TRUE;
+
+done:;
aState.mLastChild = prevChild;
- reflowResult = NS_INLINE_REFLOW_COMPLETE;
-
-done:;
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("exit nsCSSInlineFrame::ReflowMapped: childCount=%d reflowResult=%x",
- mChildCount, reflowResult));
- return reflowResult;
+ ("exit nsCSSInlineFrame::ReflowMapped: childCount=%d rs=%x",
+ mChildCount, aReflowStatus));
+ return keepGoing;
}
-nsInlineReflowStatus
-nsCSSInlineFrame::ReflowUnmapped(nsCSSInlineReflowState& aState)
-{
- NS_PRECONDITION(mLastContentIsComplete == PR_TRUE, "huh?");
-
- nsresult rv;
- nsInlineReflowStatus reflowResult = NS_INLINE_REFLOW_NOT_COMPLETE;
-
- // Get the childPrevInFlow for our eventual first child if we are a
- // continuation and we have no children and the last child in our
- // prev-in-flow is incomplete. While we are at it, we also compute
- // our kidContentIndex.
- PRInt32 kidContentIndex;
- nsIFrame* childPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsCSSInlineFrame* prev = (nsCSSInlineFrame*)mPrevInFlow;
- NS_ASSERTION(prev->mLastContentOffset >= prev->mFirstContentOffset,
- "bad prevInFlow");
-
- kidContentIndex = prev->NextChildOffset();
- if (!prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(childPrevInFlow);
- }
- }
- else {
- kidContentIndex = NextChildOffset();
- }
-
- NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("enter nsCSSInlineFrame::ReflowUnmapped: kci=%d childPrevInFlow=%p",
- kidContentIndex, childPrevInFlow));
-
- nsIFrame* prevChild = aState.mLastChild;
- PRInt32 lastContentIndex;
- lastContentIndex = mContent->ChildCount();
- while (kidContentIndex < lastContentIndex) {
- nsIContent* kid;
- kid = mContent->ChildAt(kidContentIndex);
- if (nsnull == kid) {
- // Our content container is bad
- break;
- }
-
- // Create child
- nsIFrame* child;
- rv = nsHTMLBase::CreateFrame(aState.mPresContext, this, kid,
- childPrevInFlow, child);
- NS_RELEASE(kid);
- if (NS_OK != rv) {
- reflowResult = nsInlineReflowStatus(rv);
- goto done;
- }
- if (nsnull == prevChild) {
- mFirstChild = child;
- mFirstContentOffset = kidContentIndex;
- }
- else {
- prevChild->SetNextSibling(child);
- }
- mChildCount++;
- NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
- ("nsCSSInlineFrame::ReflowUnmapped: new-frame=%p prev-in-flow=%p",
- child, childPrevInFlow));
-
- // Reflow the child
- nsInlineReflowStatus rs = aState.mInlineLayout.ReflowAndPlaceFrame(child);
- if (IS_REFLOW_ERROR(rs)) {
- reflowResult = rs;
- goto done;
- }
- switch (NS_INLINE_REFLOW_REFLOW_MASK & rs) {
- case NS_INLINE_REFLOW_COMPLETE:
- prevChild = child;
- childPrevInFlow = nsnull;
- kidContentIndex++;
- mLastContentIsComplete = PR_TRUE;
- break;
-
- case NS_INLINE_REFLOW_NOT_COMPLETE:
- // Note: We don't need to create a next-in-flow for the child
- // because we know that we will be continued and our
- // continuation will re-enter the reflow-unmapped logic and pick
- // up from the prev-in-flows last child and continue it.
- mLastContentOffset = kidContentIndex;
- mLastContentIsComplete = PR_FALSE;
- NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
- goto done;
-
- case NS_INLINE_REFLOW_BREAK_AFTER:
- mLastContentOffset = kidContentIndex;
- mLastContentIsComplete = PR_TRUE;
- NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
- if (++kidContentIndex == lastContentIndex) {
- reflowResult = NS_INLINE_REFLOW_COMPLETE;
- }
- goto done;
-
- case NS_INLINE_REFLOW_BREAK_BEFORE:
- // We created the child but it turns out we can't keep it
- mLastContentIsComplete = PR_TRUE;
- if (nsnull != prevChild) {
- mLastContentOffset = kidContentIndex - 1;
- PushKids(aState, prevChild, child);
- }
- else {
- // We are trying to push our only child. It must be a block
- // that must be at the start of a line and we must not be at
- // the start of a line.
- NS_NOTYETIMPLEMENTED("XXX");
- }
- goto done;
- }
- }
- if (kidContentIndex == 0) {
- NS_ASSERTION(lastContentIndex == 0, "bad kid content index");
- mLastContentOffset = 0;
- } else {
- mLastContentOffset = kidContentIndex - 1;
- }
- NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
- mLastContentIsComplete = PR_TRUE;
- reflowResult = NS_INLINE_REFLOW_COMPLETE;
-
-done:;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("exit nsCSSInlineFrame::ReflowUnmapped: reflowResult=%x", reflowResult));
- return reflowResult;
-}
-
-nsInlineReflowStatus
-nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState)
+PRBool
+nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState,
+ nsInlineReflowStatus& aReflowStatus)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("enter nsCSSInlineFrame::PullUpChildren: childCount=%d",
@@ -610,8 +509,9 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState)
kidContentIndex = NextChildOffset();
}
+ PRBool keepGoing = PR_FALSE;
nsresult rv;
- nsInlineReflowStatus reflowResult = NS_INLINE_REFLOW_NOT_COMPLETE;
+ aReflowStatus = NS_INLINE_REFLOW_COMPLETE;
nsCSSInlineFrame* nextInFlow = (nsCSSInlineFrame*) mNextInFlow;
nsIFrame* prevChild = aState.mLastChild;
#ifdef NS_DEBUG
@@ -635,12 +535,11 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState)
("nsCSSInlineFrame::PullUpChildren: trying to pullup %p", child));
// Reflow it
- nsInlineReflowStatus rs = aState.mInlineLayout.ReflowAndPlaceFrame(child);
- if (IS_REFLOW_ERROR(rs)) {
- reflowResult = rs;
+ aReflowStatus = aState.mInlineLayout.ReflowAndPlaceFrame(child);
+ if (IS_REFLOW_ERROR(aReflowStatus)) {
goto done;
}
- switch (NS_INLINE_REFLOW_REFLOW_MASK & rs) {
+ switch (NS_INLINE_REFLOW_REFLOW_MASK & aReflowStatus) {
case NS_INLINE_REFLOW_COMPLETE:
prevChild = child;
child->GetNextSibling(child);
@@ -653,7 +552,7 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState)
// won't know to create it.
rv = MaybeCreateNextInFlow(aState, child);
if (NS_OK != rv) {
- reflowResult = nsInlineReflowStatus(rv);
+ aReflowStatus = nsInlineReflowStatus(rv);
goto done;
}
prevChild = child;
@@ -668,18 +567,22 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState)
mLastContentOffset = kidContentIndex;
mLastContentIsComplete = PR_TRUE;
NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
+ // XXX wrong!
{
PRInt32 lastContentIndex;
lastContentIndex = mContent->ChildCount();
- if (kidContentIndex == lastContentIndex) {
- // All of the children have been pulled up
- reflowResult = NS_INLINE_REFLOW_COMPLETE;
+ if (++kidContentIndex == lastContentIndex) {
+ aReflowStatus = NS_INLINE_REFLOW_COMPLETE;
+ }
+ else {
+ aReflowStatus = NS_INLINE_REFLOW_NOT_COMPLETE;
}
}
goto done;
case NS_INLINE_REFLOW_BREAK_BEFORE:
mLastContentIsComplete = PR_TRUE;
+ aReflowStatus = NS_INLINE_REFLOW_NOT_COMPLETE; // XXX wrong!
if (nsnull != prevChild) {
mLastContentOffset = kidContentIndex - 1;
NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
@@ -701,23 +604,20 @@ nsCSSInlineFrame::PullUpChildren(nsCSSInlineReflowState& aState)
}
NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
mLastContentIsComplete = PR_TRUE;
- reflowResult = NS_INLINE_REFLOW_COMPLETE;
+ keepGoing = PR_TRUE;
done:;
nextInFlow = (nsCSSInlineFrame*) mNextInFlow;
if ((nsnull != nextInFlow) && (nsnull == nextInFlow->mFirstChild)) {
- if (NS_INLINE_REFLOW_COMPLETE != reflowResult) {
- // XXX This is only necessary if we want to avoid setting the
- // mFirstContentOffset when we get our first child. I think it's
- // a bad trade.
+ if (NS_INLINE_REFLOW_COMPLETE != aReflowStatus) {
AdjustOffsetOfEmptyNextInFlows();
}
}
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("exit nsCSSInlineFrame::PullUpChildren: childCount=%d reflowResult=%x",
- mChildCount, reflowResult));
- return reflowResult;
+ ("exit nsCSSInlineFrame::PullUpChildren: childCount=%d rs=%x",
+ mChildCount, aReflowStatus));
+ return keepGoing;
}
nsIFrame*
@@ -794,6 +694,140 @@ nsCSSInlineFrame::MaybeCreateNextInFlow(nsCSSInlineReflowState& aState,
return NS_OK;
}
+nsInlineReflowStatus
+nsCSSInlineFrame::ReflowUnmapped(nsCSSInlineReflowState& aState)
+{
+ NS_PRECONDITION(mLastContentIsComplete == PR_TRUE, "huh?");
+
+ nsresult rv;
+ PRBool keepGoing = PR_FALSE;
+ nsInlineReflowStatus rs = NS_INLINE_REFLOW_COMPLETE;
+
+ // Get the childPrevInFlow for our eventual first child if we are a
+ // continuation and we have no children and the last child in our
+ // prev-in-flow is incomplete. While we are at it, we also compute
+ // our kidContentIndex.
+ PRInt32 kidContentIndex;
+ nsIFrame* childPrevInFlow = nsnull;
+ if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
+ nsCSSInlineFrame* prev = (nsCSSInlineFrame*)mPrevInFlow;
+ NS_ASSERTION(prev->mLastContentOffset >= prev->mFirstContentOffset,
+ "bad prevInFlow");
+
+ kidContentIndex = prev->NextChildOffset();
+ if (!prev->mLastContentIsComplete) {
+ // Our prev-in-flow's last child is not complete
+ prev->LastChild(childPrevInFlow);
+ }
+ }
+ else {
+ kidContentIndex = NextChildOffset();
+ }
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("enter nsCSSInlineFrame::ReflowUnmapped: kci=%d childPrevInFlow=%p",
+ kidContentIndex, childPrevInFlow));
+
+ nsIFrame* prevChild = aState.mLastChild;
+ PRInt32 lastContentIndex;
+ lastContentIndex = mContent->ChildCount();
+ while (kidContentIndex < lastContentIndex) {
+ nsIContent* kid;
+ kid = mContent->ChildAt(kidContentIndex);
+ if (nsnull == kid) {
+ // Our content container is bad
+ break;
+ }
+
+ // Create child
+ nsIFrame* child;
+ rv = nsHTMLBase::CreateFrame(aState.mPresContext, this, kid,
+ childPrevInFlow, child);
+ NS_RELEASE(kid);
+ if (NS_OK != rv) {
+ rs = nsInlineReflowStatus(rv);
+ goto done;
+ }
+ if (nsnull == prevChild) {
+ mFirstChild = child;
+ mFirstContentOffset = kidContentIndex;
+ }
+ else {
+ prevChild->SetNextSibling(child);
+ }
+ mChildCount++;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_NEW_FRAMES,
+ ("nsCSSInlineFrame::ReflowUnmapped: new-frame=%p prev-in-flow=%p",
+ child, childPrevInFlow));
+
+ // Reflow the child
+ rs = aState.mInlineLayout.ReflowAndPlaceFrame(child);
+ if (IS_REFLOW_ERROR(rs)) {
+ return rs;
+ }
+ switch (NS_INLINE_REFLOW_REFLOW_MASK & rs) {
+ case NS_INLINE_REFLOW_COMPLETE:
+ prevChild = child;
+ childPrevInFlow = nsnull;
+ kidContentIndex++;
+ mLastContentIsComplete = PR_TRUE;
+ break;
+
+ case NS_INLINE_REFLOW_NOT_COMPLETE:
+ // Note: We don't need to create a next-in-flow for the child
+ // because we know that we will be continued and our
+ // continuation will re-enter the reflow-unmapped logic and pick
+ // up from the prev-in-flows last child and continue it.
+ mLastContentOffset = kidContentIndex;
+ mLastContentIsComplete = PR_FALSE;
+ NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
+ goto done;
+
+ case NS_INLINE_REFLOW_BREAK_AFTER:
+ mLastContentOffset = kidContentIndex;
+ mLastContentIsComplete = PR_TRUE;
+ NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
+ // XXX wrong!
+ if (++kidContentIndex == lastContentIndex) {
+ rs = NS_INLINE_REFLOW_COMPLETE;
+ }
+ else {
+ rs = NS_INLINE_REFLOW_NOT_COMPLETE;
+ }
+ goto done;
+
+ case NS_INLINE_REFLOW_BREAK_BEFORE:
+ // We created the child but it turns out we can't keep it
+ mLastContentIsComplete = PR_TRUE;
+ rs = NS_INLINE_REFLOW_NOT_COMPLETE; // XXX wrong!
+ if (nsnull != prevChild) {
+ mLastContentOffset = kidContentIndex - 1;
+ PushKids(aState, prevChild, child);
+ }
+ else {
+ // We are trying to push our only child. It must be a block
+ // that must be at the start of a line and we must not be at
+ // the start of a line.
+ NS_NOTYETIMPLEMENTED("XXX");
+ }
+ goto done;
+ }
+ }
+ if (kidContentIndex == 0) {
+ NS_ASSERTION(lastContentIndex == 0, "bad kid content index");
+ mLastContentOffset = 0;
+ } else {
+ mLastContentOffset = kidContentIndex - 1;
+ }
+ NS_ASSERTION(mFirstContentOffset <= mLastContentOffset, "bad fco/lco");
+ mLastContentIsComplete = PR_TRUE;
+
+done:;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit nsCSSInlineFrame::ReflowUnmapped: rs=%x", rs));
+ return rs;
+}
+
void
nsCSSInlineFrame::PushKids(nsCSSInlineReflowState& aState,
nsIFrame* aPrevChild, nsIFrame* aPushedChild)
diff --git a/mozilla/layout/css/layout/src/nsCSSInlineFrame.h b/mozilla/layout/css/layout/src/nsCSSInlineFrame.h
index b293b1ecf11..479c7444821 100644
--- a/mozilla/layout/css/layout/src/nsCSSInlineFrame.h
+++ b/mozilla/layout/css/layout/src/nsCSSInlineFrame.h
@@ -33,7 +33,7 @@ struct nsCSSInlineReflowState : public nsReflowState {
nsCSSInlineFrame* aInlineFrame,
nsIStyleContext* aInlineSC,
const nsReflowState& aReflowState,
- nsSize* aMaxElementSize);
+ PRBool aComputeMaxElementSize);
~nsCSSInlineReflowState();
nsIPresContext* mPresContext;
@@ -79,6 +79,9 @@ public:
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState);
+ // nsCSSContainerFrame
+ virtual PRBool DeleteNextInFlowsFor(nsIFrame* aChild);
+
protected:
nsCSSInlineFrame(nsIContent* aContent, nsIFrame* aParent);
@@ -95,15 +98,17 @@ protected:
void ComputeFinalSize(nsCSSInlineReflowState& aState,
nsReflowMetrics& aMetrics);
- nsInlineReflowStatus ReflowMapped(nsCSSInlineReflowState& aState);
+ PRBool ReflowMapped(nsCSSInlineReflowState& aState,
+ nsInlineReflowStatus& aReflowStatus);
- nsInlineReflowStatus ReflowUnmapped(nsCSSInlineReflowState& aState);
-
- nsInlineReflowStatus PullUpChildren(nsCSSInlineReflowState& aState);
+ PRBool PullUpChildren(nsCSSInlineReflowState& aState,
+ nsInlineReflowStatus& aReflowStatus);
nsIFrame* PullOneChild(nsCSSInlineFrame* aNextInFlow,
nsIFrame* aLastChild);
+ nsInlineReflowStatus ReflowUnmapped(nsCSSInlineReflowState& aState);
+
nsresult MaybeCreateNextInFlow(nsCSSInlineReflowState& aState,
nsIFrame* aFrame);
diff --git a/mozilla/layout/css/layout/src/nsCSSInlineLayout.cpp b/mozilla/layout/css/layout/src/nsCSSInlineLayout.cpp
index 0b65added1d..6ee3fffb07f 100644
--- a/mozilla/layout/css/layout/src/nsCSSInlineLayout.cpp
+++ b/mozilla/layout/css/layout/src/nsCSSInlineLayout.cpp
@@ -25,17 +25,17 @@
#include "nsIFontMetrics.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
+#include "nsIReflowCommand.h"
#include "nsIRunaround.h"
nsCSSInlineLayout::nsCSSInlineLayout(nsCSSLineLayout& aLineLayout,
- nsIFrame* aContainerFrame,
+ nsCSSContainerFrame* aContainerFrame,
nsIStyleContext* aContainerStyle)
: mLineLayout(aLineLayout)
{
mContainerFrame = aContainerFrame;
mAscents = mAscentBuf;
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
- mMaxElementSize = nsnull;
mContainerFont = (const nsStyleFont*)
aContainerStyle->GetStyleData(eStyleStruct_Font);
@@ -80,13 +80,18 @@ nsCSSInlineLayout::SetAscent(nscoord aAscent)
}
void
-nsCSSInlineLayout::Prepare(PRBool aUnconstrainedWidth, PRBool aNoWrap,
- nsSize* aMaxElementSize)
+nsCSSInlineLayout::Prepare(PRBool aUnconstrainedWidth,
+ PRBool aNoWrap,
+ PRBool aComputeMaxElementSize)
{
mFrameNum = 0;
mUnconstrainedWidth = aUnconstrainedWidth;
mNoWrap = aNoWrap;
- mMaxElementSize = aMaxElementSize;
+ mComputeMaxElementSize = aComputeMaxElementSize;
+ if (aComputeMaxElementSize) {
+ mMaxElementSize.width = 0;
+ mMaxElementSize.height = 0;
+ }
mMaxAscent = 0;
mMaxDescent = 0;
}
@@ -128,7 +133,13 @@ nsCSSInlineLayout::ReflowAndPlaceFrame(nsIFrame* aFrame)
// reason will be wrong so we need to check the frame state.
nsReflowReason reason = eReflowReason_Resize;
if (nsnull != mContainerReflowState->reflowCommand) {
- reason = eReflowReason_Incremental;
+ // If the reflow command was targeted at the container we are
+ // reflowing for, don't make the reason incremental.
+ nsIFrame* target;
+ mContainerReflowState->reflowCommand->GetTarget(target);
+ if (mContainerFrame != target) {
+ reason = eReflowReason_Incremental;
+ }
}
else {
nsFrameState state;
@@ -141,7 +152,10 @@ nsCSSInlineLayout::ReflowAndPlaceFrame(nsIFrame* aFrame)
// Setup reflow state for reflowing the frame
nsReflowState reflowState(aFrame, *mContainerReflowState, maxSize, reason);
nsInlineReflowStatus rs;
- nsReflowMetrics metrics(mMaxElementSize);
+ nsSize frameMaxElementSize;
+ nsReflowMetrics metrics(mComputeMaxElementSize
+ ? &frameMaxElementSize
+ : nsnull);
PRBool isAware;
aFrame->WillReflow(*mLineLayout.mPresContext);
rs = ReflowFrame(aFrame, metrics, reflowState, isAware);
@@ -152,6 +166,10 @@ nsCSSInlineLayout::ReflowAndPlaceFrame(nsIFrame* aFrame)
return rs;
}
+ if (!isAware && ((0 != metrics.width) || (0 != metrics.height))) {
+ mLineLayout.SetSkipLeadingWhiteSpace(PR_FALSE);
+ }
+
// It's possible the frame didn't fit
if (metrics.width > maxSize.width) {
if (!IsFirstChild()) {
@@ -253,7 +271,7 @@ nsCSSInlineLayout::ReflowFrame(nsIFrame* aKidFrame,
// parent is not this because we are executing pullup code)
nsIFrame* parent;
aKidFrame->GetGeometricParent(parent);
- parent->DeleteChildsNextInFlow(aKidFrame);
+ ((nsCSSContainerFrame*)parent)->DeleteNextInFlowsFor(aKidFrame);
}
}
@@ -302,6 +320,7 @@ nsCSSInlineLayout::PlaceFrame(nsIFrame* aFrame,
}
}
}
+ nscoord totalWidth = 0;
if (!isBullet) {
// Place normal in-flow child
aFrame->SetRect(aFrameRect);
@@ -326,7 +345,7 @@ nsCSSInlineLayout::PlaceFrame(nsIFrame* aFrame,
horizontalMargins = aFrameMargin.left + aFrameMargin.right;
break;
}
- nscoord totalWidth = aFrameMetrics.width + horizontalMargins;
+ totalWidth = aFrameMetrics.width + horizontalMargins;
mX += totalWidth;
}
@@ -336,21 +355,18 @@ nsCSSInlineLayout::PlaceFrame(nsIFrame* aFrame,
aFrameRect.x, aFrameRect.y,
aFrameRect.width, aFrameRect.height));
-#if XXX_fix_me
// XXX this is not right; the max-element-size of a child depends on
// it's margins which it doesn't know how to add in
- if (nsnull != mMaxElementSize) {
- // XXX I'm not certain that this is doing the right thing; rethink this
- nscoord elementWidth = kidMaxElementSize->width + horizontalMargins;
- if (elementWidth > mMaxElementSize->width) {
- mMaxElementSize->width = elementWidth;
+ // Fold in child's max-element-size information into our own
+ if (mComputeMaxElementSize) {
+ if (aFrameMetrics.maxElementSize->width > mMaxElementSize.width) {
+ mMaxElementSize.width = aFrameMetrics.maxElementSize->width;
}
- if (aFrameMetrics.height > mMaxElementSize->height) {
- mMaxElementSize->height = aFrameMetrics.height;
+ if (aFrameMetrics.maxElementSize->height > mMaxElementSize.height) {
+ mMaxElementSize.height = aFrameMetrics.maxElementSize->height;
}
}
-#endif
if (aFrameMetrics.ascent > mMaxAscent) {
mMaxAscent = aFrameMetrics.ascent;
@@ -364,22 +380,6 @@ nsCSSInlineLayout::PlaceFrame(nsIFrame* aFrame,
}
mFrameNum++;
-#if XXX_fix_me
- mLine->mLastContentOffset = mKidContentIndex;
- switch (aFrameReflowStatus & NS_INLINE_REFLOW_REFLOW_MASK) {
- case NS_INLINE_REFLOW_COMPLETE:
- case NS_INLINE_REFLOW_BREAK_AFTER:
- mLine->mLastContentIsComplete = PR_TRUE;
- mKidPrevInFlow = nsnull;
- break;
-
- case NS_INLINE_REFLOW_NOT_COMPLETE:
- mLine->mLastContentIsComplete = PR_FALSE;
- mKidPrevInFlow = mKidFrame;
- break;
- }
-#endif
-
return aFrameReflowStatus;
}
diff --git a/mozilla/layout/css/layout/src/nsCSSInlineLayout.h b/mozilla/layout/css/layout/src/nsCSSInlineLayout.h
index 4f3b2d368f0..13e5c633346 100644
--- a/mozilla/layout/css/layout/src/nsCSSInlineLayout.h
+++ b/mozilla/layout/css/layout/src/nsCSSInlineLayout.h
@@ -19,7 +19,7 @@
#ifndef nsCSSInlineLayout_h___
#define nsCSSInlineLayout_h___
-#include "nsIFrame.h"
+#include "nsCSSContainerFrame.h"
#include "nsIInlineReflow.h"
class nsCSSLineLayout;
struct nsStyleDisplay;
@@ -34,7 +34,7 @@ struct nsStyleText;
*/
struct nsCSSInlineLayout {
nsCSSInlineLayout(nsCSSLineLayout& aLineLayout,
- nsIFrame* aContainerFrame,
+ nsCSSContainerFrame* aContainerFrame,
nsIStyleContext* aContainerStyle);
~nsCSSInlineLayout();
@@ -42,7 +42,7 @@ struct nsCSSInlineLayout {
void Prepare(PRBool aUnconstrainedWidth,
PRBool aNoWrap,
- nsSize* aMaxElementSize);
+ PRBool aComputeMaxElementSize);
void SetReflowSpace(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
@@ -79,7 +79,7 @@ struct nsCSSInlineLayout {
nsIFrame*& aNextInFlowResult);
nsCSSLineLayout& mLineLayout;
- nsIFrame* mContainerFrame;
+ nsCSSContainerFrame* mContainerFrame;
const nsStyleFont* mContainerFont;
const nsStyleText* mContainerText;
const nsStyleDisplay* mContainerDisplay;
@@ -88,6 +88,7 @@ struct nsCSSInlineLayout {
PRPackedBool mUnconstrainedWidth;
PRPackedBool mNoWrap;
+ PRPackedBool mComputeMaxElementSize;
nscoord mAvailWidth;
nscoord mAvailHeight;
nscoord mX, mY;
@@ -100,7 +101,7 @@ struct nsCSSInlineLayout {
nscoord mMaxAscent;
nscoord mMaxDescent;
- nsSize* mMaxElementSize;
+ nsSize mMaxElementSize;
};
#endif /* nsCSSInlineLayout_h___ */
diff --git a/mozilla/layout/css/layout/src/nsCSSLineLayout.cpp b/mozilla/layout/css/layout/src/nsCSSLineLayout.cpp
index 344a67eeda9..b1cbf7ad613 100644
--- a/mozilla/layout/css/layout/src/nsCSSLineLayout.cpp
+++ b/mozilla/layout/css/layout/src/nsCSSLineLayout.cpp
@@ -59,6 +59,7 @@ nsCSSLineLayout::nsCSSLineLayout(nsIPresContext* aPresContext,
mLineNumber = 0;
mLeftEdge = 0;
mColumn = 0;
+ mSkipLeadingWS = PR_TRUE;
}
nsCSSLineLayout::~nsCSSLineLayout()
diff --git a/mozilla/layout/css/layout/src/nsCSSLineLayout.h b/mozilla/layout/css/layout/src/nsCSSLineLayout.h
index df77b2aa66f..e0414863e74 100644
--- a/mozilla/layout/css/layout/src/nsCSSLineLayout.h
+++ b/mozilla/layout/css/layout/src/nsCSSLineLayout.h
@@ -72,6 +72,7 @@ public:
void Prepare(nscoord aLeftEdge) {
mLeftEdge = aLeftEdge;
mColumn = 0;
+ mSkipLeadingWS = PR_TRUE;
}
PRInt32 GetColumn() {
@@ -82,6 +83,10 @@ public:
mColumn = aNewColumn;
}
+ void NextLine() {
+ mLineNumber++;
+ }
+
nsIPresContext* mPresContext;
nsISpaceManager* mSpaceManager;
@@ -93,6 +98,15 @@ public:
nsCSSTextRun* mTextRuns;
nsCSSTextRun** mTextRunP;
nsCSSTextRun* mCurrentTextRun;
+
+ //XXX temporary?
+
+ void SetSkipLeadingWhiteSpace(PRBool aNewSetting) {
+ mSkipLeadingWS = aNewSetting;
+ }
+ PRBool GetSkipLeadingWhiteSpace() { return mSkipLeadingWS; }
+
+ PRBool mSkipLeadingWS;
};
#endif /* nsCSSLineLayout_h___ */
diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp
deleted file mode 100644
index bf4fc11255c..00000000000
--- a/mozilla/layout/generic/nsBlockFrame.cpp
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsBlockFrame.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIHTMLContent.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIAnchoredItems.h"
-#include "nsIReflowCommand.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIPtr.h"
-#include "nsHTMLAtoms.h"
-#include "nsHTMLIIDs.h"
-#include "nsHTMLValue.h"
-#include "nsCSSLayout.h"
-#include "nsIView.h"
-
-// XXX what do we do with catastrophic errors (rv < 0)? What is the
-// state of the reflow world after such an error?
-
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-//----------------------------------------------------------------------
-
-void nsBlockBandData::ComputeAvailSpaceRect()
-{
- nsBandTrapezoid* trapezoid = data;
-
- if (count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < count; i++) {
- nsBandTrapezoid* trapezoid = &data[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &data[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availSpace);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availSpace);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availSpace.x = availSpace.XMost();
- }
- availSpace.width = 0;
- }
-}
-
-//----------------------------------------------------------------------
-
-nsBlockReflowState::nsBlockReflowState()
-{
-}
-
-nsBlockReflowState::~nsBlockReflowState()
-{
-}
-
-nsresult
-nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock)
-{
- nsresult rv = NS_OK;
-
- mPresContext = aPresContext;
- mBlock = aBlock;
- mSpaceManager = aSpaceManager;
- mBlockIsPseudo = aBlock->IsPseudoFrame();
- mListPositionOutside = PR_FALSE;
- mCurrentLine = nsnull;
- mPrevKidFrame = nsnull;
- reflowState = &aReflowState;
-
- mX = 0;
- mY = 0;
- mStyleSizeFlags = 0;
- mAvailSize = reflowState->maxSize;
- mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE);
- mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE);
- mMaxElementSizePointer = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
- }
- mKidXMost = 0;
-
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = 0;
- mPrevMarginSynthetic = PR_FALSE;
-
- mNextListOrdinal = -1;
-
- return rv;
-}
-
-// Recover the block reflow state to what it should be if aLine is about
-// to be reflowed. aLine should not be nsnull
-nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
-{
- NS_PRECONDITION(nsnull != aLine, "null parameter");
- nsLineData* prevLine = aLine->mPrevLine;
-
- if (nsnull != prevLine) {
- // Compute the running y-offset, and the available height
- mY = prevLine->mBounds.YMost();
- if (!mUnconstrainedHeight) {
- mAvailSize.height -= mY;
- }
-
- // Compute the kid x-most
- for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
- nscoord xmost = l->mBounds.XMost();
- if (xmost > mKidXMost) {
- mKidXMost = xmost;
- }
- }
-
- // If the previous line is a block, then factor in its bottom margin
- if (prevLine->mIsBlock) {
- const nsStyleSpacing* kidSpacing;
- nsIFrame* kid = prevLine->mFirstChild;
-
- kid->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)kidSpacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kid, kidMargin);
- if (kidMargin.bottom < 0) {
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = -kidMargin.bottom;
- } else {
- mPrevPosBottomMargin = kidMargin.bottom;
- mPrevNegBottomMargin = 0;
- }
- }
- }
-
- return NS_OK;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsBlockFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsBlockFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsBlockFrame::~nsBlockFrame()
-{
- DestroyLines();
- delete mRunInFloaters;
-}
-
-void nsBlockFrame::DestroyLines()
-{
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- mLines = nsnull;
-}
-
-NS_METHOD
-nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
-{
- NS_PRECONDITION(0 != aInstancePtr, "null ptr");
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
- if (aIID.Equals(kBlockFrameCID)) {
- *aInstancePtr = (void*) (this);
- return NS_OK;
- }
- else if (aIID.Equals(kIRunaroundIID)) {
- *aInstancePtr = (void*) ((nsIRunaround*) this);
- return NS_OK;
- }
- else if (aIID.Equals(kIFloaterContainerIID)) {
- *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
- return NS_OK;
- }
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_METHOD
-nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
-{
- aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame)
-{
- nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
- if (nsnull == cf) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
- aContinuingFrame = cf;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::ListTag(FILE* out) const
-{
- if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
- fprintf(out, "*block<");
- nsIAtom* atom = mContent->GetTag();
- if (nsnull != atom) {
- nsAutoString tmp;
- atom->ToString(tmp);
- fputs(tmp, out);
- }
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, ">(%d)@%p", contentIndex, this);
- } else {
- nsHTMLContainerFrame::ListTag(out);
- }
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- NS_RELEASE(view);
- }
-
- // Output the first/last content offset
- fprintf(out, "[%d,%d,%c] ", mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
-
- // Output the children, one line at a time
- if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- aIndent++;
-
- nsLineData* line = mLines;
- while (nsnull != line) {
- line->List(out, aIndent);
- line = line->mNextLine;
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
-
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- nsresult rv = nsHTMLContainerFrame::VerifyTree();
- if (NS_OK != rv) {
- return rv;
- }
- rv = VerifyLines(PR_TRUE);
- return rv;
-#else
- return NS_OK;
-#endif
-}
-
-#ifdef NS_DEBUG
-nsresult
-nsBlockFrame::VerifyLines(PRBool aFinalCheck) const
-{
- nsresult rv = NS_OK;
-
- // Make sure that the list of children agrees with our child count.
- // If this is not the case then the child list and the line list are
- // not properly arranged.
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(mChildCount == len, "bad child list");
-
- // Verify that our lines are correctly setup
- PRInt32 offset = mFirstContentOffset;
- PRInt32 lineChildCount = 0;
- nsLineData* line = mLines;
- nsLineData* prevLine = nsnull;
- while (nsnull != line) {
- if (aFinalCheck) {
- NS_ASSERTION(((offset == line->mFirstContentOffset) &&
- (line->mFirstContentOffset <= line->mLastContentOffset)),
- "bad line mFirstContentOffset");
- NS_ASSERTION(line->mLastContentOffset <= mLastContentOffset,
- "bad line mLastContentOffset");
- offset = line->mLastContentOffset;
- if (line->mLastContentIsComplete) {
- offset++;
- }
- }
- lineChildCount += line->mChildCount;
- rv = line->Verify(aFinalCheck);
- if (NS_OK != rv) {
- return rv;
- }
- prevLine = line;
- line = line->mNextLine;
- }
- if (aFinalCheck && (nsnull != prevLine)) {
- NS_ASSERTION(prevLine->mLastContentOffset == mLastContentOffset,
- "bad mLastContentOffset");
- NS_ASSERTION(prevLine->mLastContentIsComplete == mLastContentIsComplete,
- "bad mLastContentIsComplete");
- }
- NS_ASSERTION(lineChildCount == mChildCount, "bad line counts");
-
- return rv;
-}
-#endif
-
-//----------------------------------------------------------------------
-
-// Remove a next-in-flow from from this block's list of lines
-
-// XXX problems here:
-// 1. we always have to start from the first line: slow!
-// 2. we can avoid this when the child is not the last child in a line
-
-void
-nsBlockFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
- // When a reflow indicates completion it's possible that
- // next-in-flows were just removed. We have to remove them from any
- // nsLineData's that follow the current line.
- nsLineData* line = mLines;
- while (nsnull != line) {
- if (line->mFirstChild == aNextInFlow) {
- // Remove child from line.
- if (0 == --line->mChildCount) {
- line->mFirstChild = nsnull;
- }
- else {
- // Fixup the line
- nsIFrame* nextKid;
- aNextInFlow->GetNextSibling(nextKid);
- line->mFirstChild = nextKid;
- nextKid->GetContentIndex(line->mFirstContentOffset);
- }
- break;
- }
- line = line->mNextLine;
- }
-}
-
-nsresult
-nsBlockFrame::ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(aLineLayout, aDesiredSize, aReflowState, aStatus);
- }
- else {
- aKidFrame->Reflow(aLineLayout.mPresContext, aDesiredSize, aReflowState,
- aStatus);
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
- nsIRunaround* reflowRunaround;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- // Get the band for this y-offset and see whether there are any floaters
- // that have changed the left/right edges.
- //
- // XXX In order to do this efficiently we should move all this code to
- // nsBlockFrame since it already has band data, and it's probably the only
- // one who calls this routine anyway
- nsBandData bandData;
- nsBandTrapezoid trapezoids[12];
- nsBandTrapezoid* trapezoid = trapezoids;
- nsRect availBand;
-
- bandData.trapezoids = trapezoids;
- bandData.size = 12;
- aSpaceManager->GetBandData(0, aReflowState.maxSize, bandData);
-
- if (bandData.count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < bandData.count; i++) {
- nsBandTrapezoid* trapezoid = &trapezoids[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &trapezoids[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availBand);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availBand);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availBand.x = availBand.XMost();
- }
- availBand.width = 0;
- }
-
- // Does the child frame support interface nsIRunaround?
- if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
- (void**)&reflowRunaround)) {
- // Yes, the child frame wants to interact directly with the space
- // manager.
- reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState,
- aDesiredRect, aStatus);
- } else {
- // No, use interface nsIFrame instead.
- if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
- if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) {
- // There are left/right floaters.
- aReflowState.maxSize.width = availBand.width;
- }
- }
-
- // XXX FIX ME
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-
- // Return the desired rect
- aDesiredRect.x = availBand.x;
- aDesiredRect.y = 0;
- aDesiredRect.width = aDesiredSize.width;
- aDesiredRect.height = aDesiredSize.height;
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
-
- return NS_OK;
-}
-
-nsLineData*
-nsBlockFrame::CreateLineForOverflowList(nsIFrame* aOverflowList)
-{
- nsLineData* newLine = new nsLineData();
- if (nsnull != newLine) {
- nsIFrame* kid = aOverflowList;
- newLine->mFirstChild = kid;
- kid->GetContentIndex(newLine->mFirstContentOffset);
- newLine->mLastContentOffset = -1;
- newLine->mLastContentIsComplete = PRPackedBool(0x255);
- PRInt32 kids = 0;
- while (nsnull != kid) {
- kids++;
- kid->GetNextSibling(kid);
- }
- newLine->mChildCount = kids;
- }
- return newLine;
-}
-
-void
-nsBlockFrame::DrainOverflowList()
-{
- nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
- if (nsnull != prevBlock) {
- nsIFrame* overflowList = prevBlock->mOverflowList;
- if (nsnull != overflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- NS_ASSERTION(nsnull == mLines, "bad overflow list");
-
- // Create a line to hold the entire overflow list
- nsLineData* newLine = CreateLineForOverflowList(overflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(overflowList);
- prevBlock->mOverflowList = nsnull;
-
- // The new line is the first line
- mLines = newLine;
- }
- }
-
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild,
- "overflow list but no mapped children");
-
- // Create a line to hold the overflow list
- nsLineData* newLine = CreateLineForOverflowList(mOverflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
-
- // The new line is appended after our other lines
- nsLineData* prevLine = nsnull;
- nsLineData* line = mLines;
- while (nsnull != line) {
- prevLine = line;
- line = line->mNextLine;
- }
- if (nsnull == prevLine) {
- mLines = newLine;
- }
- else {
- prevLine->mNextLine = newLine;
- newLine->mPrevLine = prevLine;
- }
- }
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_FALSE);
- }
-#endif
-}
-
-void
-nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint8 aBreakType)
-{
- for (;;) {
- if (aState.mCurrentBand.count <= 1) {
- // No floaters in this band therefore nothing to clear
- break;
- }
-
- // Find the Y coordinate to clear to
- nscoord clearYMost = aState.mY;
- nsRect tmp;
- PRInt32 i;
- for (i = 0; i < aState.mCurrentBand.count; i++) {
- const nsStyleDisplay* display;
- nsBandTrapezoid* trapezoid = &aState.mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 fn, numFrames = trapezoid->frames->Count();
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
-
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- }
-
- if (clearYMost == aState.mY) {
- // Nothing to clear
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::ClearFloaters: mY=%d clearYMost=%d\n",
- aState.mY, clearYMost));
-
- aState.mY = clearYMost + 1;
-
- // Get a new band
- GetAvailableSpace(aState, aState.mY);
- }
-}
-
-nsresult
-nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine)
-{
- // Before we place the line, make sure that it will fit in it's new
- // location. It always fits if the height isn't constrained or it's
- // the first line.
- if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
- if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
- // The line will not fit
- return PushLines(aState, aLine);
- }
- }
-
- // When the line is finally placed then we know that the child
- // frames have a stable location. This means that we can DidReflow
- // them marking them done. Note that when we are paginated this
- // optimization cannot be done because this may be a nested block
- // that will be pushed to a new page by the containing block and the
- // nested block can't know that during its reflow.
- // XXX and actually, this only always works for the block which is a
- // child of the body.
- if (!aState.mPresContext->IsPaginated()) {
- nsIAtom* tag = mContent->GetTag();
- if (nsHTMLAtoms::body == tag) {
- nsIFrame* child = aLine->mFirstChild;
- for (PRInt32 i = aLine->mChildCount; --i >= 0; ) {
- nsFrameState state;
- child->GetFrameState(state);
- if (NS_FRAME_IN_REFLOW & state) {
- child->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
- }
- child->GetNextSibling(child);
- }
-
- // Paint this portion of ourselves
- if (!aLine->mBounds.IsEmpty()) {
- Invalidate(aLine->mBounds);
- }
- }
- NS_IF_RELEASE(tag);
- }
-
- // Consume space and advance running values
- aState.mY += aLine->mBounds.height;
- if (nsnull != aState.mMaxElementSizePointer) {
- nsSize* maxSize = aState.mMaxElementSizePointer;
- if (aLineLayout.mState.mMaxElementSize.width > maxSize->width) {
- maxSize->width = aLineLayout.mState.mMaxElementSize.width;
- }
- if (aLineLayout.mState.mMaxElementSize.height > maxSize->height) {
- maxSize->height = aLineLayout.mState.mMaxElementSize.height;
- }
- }
- nscoord xmost = aLine->mBounds.XMost();
- if (xmost > aState.mKidXMost) {
- aState.mKidXMost = xmost;
- }
-
- // Process any pending break operations
- switch (aLineLayout.mPendingBreak) {
- default:
- break;
- case NS_STYLE_CLEAR_LEFT:
- case NS_STYLE_CLEAR_RIGHT:
- case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
- ClearFloaters(aState, aLineLayout.mPendingBreak);
- break;
- }
- // XXX for now clear the pending break; this is where support for
- // page breaks or column breaks could be partially handled.
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- // Any below current line floaters to place?
- // XXX We really want to know whether this is the initial reflow (reflow
- // unmapped) or a subsequent reflow in which case we only need to offset
- // the existing floaters...
- if (aState.mPendingFloaters.Count() > 0) {
- if (nsnull == aLine->mFloaters) {
- aLine->mFloaters = new nsVoidArray;
- }
- aLine->mFloaters->operator=(aState.mPendingFloaters);
- aState.mPendingFloaters.Clear();
- }
-
- if (nsnull != aLine->mFloaters) {
- PlaceBelowCurrentLineFloaters(aState, aLine->mFloaters, aState.mY);
- // XXX Factor in the height of the floaters as well when considering
- // whether the line fits.
- // The default policy is that if there isn't room for the floaters then
- // both the line and the floaters are pushed to the next-in-flow...
- }
-
- if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
- // The current y coordinate is now past our available space
- // rectangle. Get a new band of space.
- GetAvailableSpace(aState, aState.mY);
- }
-
- return NS_LINE_LAYOUT_COMPLETE;
-}
-
-// aY has borderpadding.top already factored in
-nsresult
-nsBlockFrame::GetAvailableSpace(nsBlockReflowState& aState, nscoord aY)
-{
- nsresult rv = NS_OK;
-
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Fill in band data for the specific Y coordinate
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->GetBandData(aY, aState.mAvailSize, aState.mCurrentBand);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
- aState.mCurrentBand.ComputeAvailSpaceRect();
-
- aState.mCurrentBand.availSpace.MoveBy(aState.mBorderPadding.left,
- aState.mY);
-
- return rv;
-}
-
-// Give aLine and any successive lines to the block's next-in-flow; if
-// we don't have a next-in-flow then push all the children onto our
-// overflow list.
-nsresult
-nsBlockFrame::PushLines(nsBlockReflowState& aState, nsLineData* aLine)
-{
- PRInt32 i;
-
- // Split our child-list in two; revert our last content offset and
- // completion status to the previous line.
- nsLineData* prevLine = aLine->mPrevLine;
- NS_PRECONDITION(nsnull != prevLine, "pushing first line");
- nsIFrame* prevKidFrame = prevLine->mFirstChild;
- for (i = prevLine->mChildCount - 1; --i >= 0; ) {
- prevKidFrame->GetNextSibling(prevKidFrame);
- }
-#ifdef NS_DEBUG
- nsIFrame* nextFrame;
- prevKidFrame->GetNextSibling(nextFrame);
- NS_ASSERTION(nextFrame == aLine->mFirstChild, "bad line list");
-#endif
- prevKidFrame->SetNextSibling(nsnull);
- prevLine->mNextLine = nsnull;
- mLastContentOffset = prevLine->mLastContentOffset;
- mLastContentIsComplete = prevLine->mLastContentIsComplete;
-
- // Push children to our next-in-flow if we have, or to our overflow list
- nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow;
- PRInt32 pushCount = 0;
- if (nsnull == nextInFlow) {
- // Place children on the overflow list
- mOverflowList = aLine->mFirstChild;
-
- // Destroy the lines
- nsLineData* line = aLine;
- while (nsnull != line) {
- pushCount += line->mChildCount;
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- }
- else {
- aLine->mPrevLine = nsnull;
-
- // Pass on the children to our next-in-flow
- nsLineData* line = aLine;
- prevLine = line;
- nsIFrame* lastKid = aLine->mFirstChild;
- nsIFrame* kid = lastKid;
- while (nsnull != line) {
- i = line->mChildCount;
- pushCount += i;
- NS_ASSERTION(kid == line->mFirstChild, "bad line list");
- while (--i >= 0) {
- kid->SetGeometricParent(nextInFlow);
- nsIFrame* contentParent;
- kid->GetContentParent(contentParent);
- if (this == contentParent) {
- kid->SetContentParent(nextInFlow);
- }
- lastKid = kid;
- kid->GetNextSibling(kid);
- }
- prevLine = line;
- line = line->mNextLine;
- }
-
- // Join the two line lists
- nsLineData* nextInFlowLine = nextInFlow->mLines;
- if (nsnull != nextInFlowLine) {
- lastKid->SetNextSibling(nextInFlowLine->mFirstChild);
- nextInFlowLine->mPrevLine = prevLine;
- }
- nsIFrame* firstKid = aLine->mFirstChild;
- prevLine->mNextLine = nextInFlowLine;
- nextInFlow->mLines = aLine;
- nextInFlow->mFirstChild = firstKid;
- nextInFlow->mChildCount += pushCount;
- firstKid->GetContentIndex(nextInFlow->mFirstContentOffset);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- nextInFlow->VerifyLines(PR_FALSE);
- }
-#endif
- }
- mChildCount -= pushCount;
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return NS_LINE_LAYOUT_NOT_COMPLETE;
-}
-
-nsresult
-nsBlockFrame::ReflowMapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // See if we have any run-in floaters to place
- if (nsnull != mRunInFloaters) {
- PlaceBelowCurrentLineFloaters(aState, mRunInFloaters, aState.mY);
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- nsLineData* line = mLines;
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != line) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);/* XXX move out of loop */
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-// XXX This is a short-term hack. It assumes that the caller has already recovered
-// the state, and that some space has been retrieved from the space manager...
-nsresult
-nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != aLine) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, aLine);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, aLine);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = aLine->mLastContentOffset;
- mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
- aLine = aLine->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // If we have no children and we have a prev-in-flow then we need to
- // pick up where it left off. If we have children, e.g. we're being
- // resized, then our content offset will have already been set
- // correctly.
- nsIFrame* kidPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsBlockFrame* prev = (nsBlockFrame*) mPrevInFlow;
- mFirstContentOffset = prev->NextChildOffset();// XXX Is this necessary?
- if (PR_FALSE == prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
-
- // Get to the last line where the new content may be added
- nsLineData* line = nsnull;
- nsLineData* prevLine = nsnull;
- if (nsnull != mLines) {
- line = mLines;
- while (nsnull != line->mNextLine) {
- line = line->mNextLine;
- }
- prevLine = line->mPrevLine;
-
- // If the last line is not complete then kidPrevInFlow should be
- // set to the last-line's last child.
- if (!line->mLastContentIsComplete) {
- kidPrevInFlow = line->GetLastChild();
- }
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- // Now reflow the new content until we are out of new content or out
- // of vertical space.
- PRInt32 kidIndex = NextChildOffset();
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- PRInt32 contentChildCount = mContent->ChildCount();
- while (kidIndex < contentChildCount) {
- if (nsnull == line) {
- if (!MoreToReflow(aState)) {
- break;
- }
- line = new nsLineData();
- if (nsnull == line) {
- rv = NS_ERROR_OUT_OF_MEMORY;
- goto done;
- }
- line->mFirstContentOffset = kidIndex;
- }
-
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Add line to the block; do this before placing the line in case
- // PushLines is needed.
- if (nsnull == prevLine) {
- // For the first line, initialize mFirstContentOffset
- mFirstContentOffset = line->mFirstContentOffset;
- mFirstChild = line->mFirstChild;
- mLines = line;
- }
- else {
- prevLine->mNextLine = line;
- line->mPrevLine = prevLine;
- }
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
- kidIndex = lineLayout.mState.mKidIndex;
- kidPrevInFlow = lineLayout.mKidPrevInFlow;
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- prevLine = line;
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
- if (aState.mBlockIsPseudo) {
- PropagateContentOffsets();
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState)
-{
- nsresult rv;
- rv = aState.Initialize(aPresContext, aSpaceManager,
- aReflowState, aMaxElementSize, this);
-
- // Apply border and padding adjustments for regular frames only
- if (!aState.mBlockIsPseudo) {
- const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStylePosition* myPosition = (const nsStylePosition*)
- mStyleContext->GetStyleData(eStyleStruct_Position);
-
- mySpacing->CalcBorderPaddingFor(this, aState.mBorderPadding);
- aState.mY = aState.mBorderPadding.top;
- aState.mX = aState.mBorderPadding.left;
-
- if (aState.mUnconstrainedWidth) {
- // If our width is unconstrained don't bother futzing with the
- // available width/height because they don't matter - we are
- // going to get reflowed again.
- aState.mDeltaWidth = NS_UNCONSTRAINEDSIZE;
- }
- else {
- // When we are constrained we need to apply the width/height
- // style properties. When we have a width/height it applies to
- // the content width/height of our box. The content width/height
- // doesn't include the border+padding so we have to add that in
- // instead of subtracting it out of our maxsize.
- nscoord lr =
- aState.mBorderPadding.left + aState.mBorderPadding.right;
-
- // Get and apply the stylistic size. Note: do not limit the
- // height until we are done reflowing.
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
- aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aState.mAvailSize.width = aState.mStyleSize.width + lr;
- }
- else {
- aState.mAvailSize.width -= lr;
- }
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
- }
- else {
- aState.mBorderPadding.SizeTo(0, 0, 0, 0);
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
-
- // Setup initial list ordinal value
- nsIAtom* tag = mContent->GetTag();
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- nsHTMLValue value;
- if (eContentAttr_HasValue ==
- ((nsIHTMLContent*)mContent)->GetAttribute(nsHTMLAtoms::start, value)) {
- if (eHTMLUnit_Integer == value.GetUnit()) {
- aState.mNextListOrdinal = value.GetIntValue();
- }
- }
- }
- NS_RELEASE(tag);
-
- // Setup list flags in block reflow state if this block is a list
- // item.
- const nsStyleDisplay* myDisplay = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_DISPLAY_LIST_ITEM == myDisplay->mDisplay) {
- const nsStyleList* myList = (const nsStyleList*)
- mStyleContext->GetStyleData(eStyleStruct_List);
- if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == myList->mListStylePosition) {
- aState.mListPositionOutside = PR_TRUE;
- }
- }
-
- return rv;
-}
-
-PRBool
-nsBlockFrame::MoreToReflow(nsBlockReflowState& aState)
-{
- PRBool rv = PR_FALSE;
- if (NextChildOffset() < mContent->ChildCount()) {
- rv = PR_TRUE;
- }
- return rv;
-}
-
-nsBlockReflowState*
-nsBlockFrame::FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame)
-{
- nsBlockReflowState* state = nsnull;
- if (nsnull != aFrame) {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
- while (nsnull != parent) {
- nsBlockFrame* block;
- nsresult rv = parent->QueryInterface(kBlockFrameCID, (void**) &block);
- if (NS_OK == rv) {
- nsIPresShell* shell = aPresContext->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(block);
- NS_RELEASE(shell);
- break;
- }
- parent->GetGeometricParent(parent);
- }
- }
- return state;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer)
-{
- return nsHTMLContainerFrame::ContentAppended(aShell, aPresContext, aContainer);
-}
-
-NS_METHOD
-nsBlockFrame::ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- return nsHTMLContainerFrame::ContentInserted(aShell, aPresContext, aContainer,
- aChild, aIndexInParent);
-}
-
-NS_METHOD
-nsBlockFrame::ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-NS_METHOD
-nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-// XXX if there is nothing special going on here, then remove this
-// implementation and let nsFrame do it.
-NS_METHOD
-nsBlockFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nsresult rv = NS_OK;
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = mRect.height;
- aMetrics.descent = 0;
- return rv;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PreReflowCheck();
- }
-#endif
-
- nsBlockReflowState state;
- nsresult rv = NS_OK;
-
- if (eReflowReason_Initial == aReflowState.reason) {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 == (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
- else {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 != (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- }
-
- aStatus = NS_FRAME_COMPLETE;
- rv = InitializeState(aPresContext, aSpaceManager, aReflowState,
- aDesiredSize.maxElementSize, state);
-
- NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d",
- aReflowState.reason, state.mDeltaWidth));
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- nsIPresShell* shell = state.mPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Is the reflow command target at us?
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
- if (this == target) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- if (nsIReflowCommand::FrameAppended == type) {
- nsLineData* lastLine = LastLine();
-
- // Restore the state
- if (nsnull != lastLine) {
- state.RecoverState(lastLine);
- }
-
- // Reflow unmapped children
- PRInt32 kidIndex = NextChildOffset();
- PRInt32 contentChildCount = mContent->ChildCount();
- if (kidIndex == contentChildCount) {
- // There is nothing to do here
- if (nsnull != lastLine) {
- state.mY = lastLine->mBounds.YMost();
- }
- }
- else {
- rv = ReflowUnmapped(state);
- }
- } else {
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- }
- } else {
- // The command is passing through us. Get the next frame in the
- // reflow chain
- nsIFrame* nextFrame;
- aReflowState.reflowCommand->GetNext(nextFrame);
-
- // Restore our state as if nextFrame is the next frame to reflow
- nsLineData* line = FindLine(nextFrame);
- state.RecoverState(line);
-
- // Get some available space to start reflowing with
- GetAvailableSpace(state, state.mY);
-
- // Reflow the affected line
- nsLineLayout lineLayout(state);
-
- state.mCurrentLine = &lineLayout;
- lineLayout.Initialize(state, line);
-
- // Have the line handle the incremental reflow
- nsRect oldBounds = line->mBounds;
- rv = lineLayout.IncrementalReflowFromChild(aReflowState.reflowCommand,
- nextFrame);
-
- // Now place the line. It's possible it won't fit
- rv = PlaceLine(state, lineLayout, line);
- // XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- state.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
-
- // Now figure out what to do with the frames that follow
- rv = IncrementalReflowAfter(state, line, rv, oldBounds);
- }
- }
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- } else {
- nsresult rv = NS_OK;
- nsIPresShell* shell = aPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Check for an overflow list
- DrainOverflowList();
-
- if (nsnull != mLines) {
- rv = ReflowMapped(state);
- }
-
- if (NS_OK == rv) {
- if ((nsnull != mLines) && (state.mAvailSize.height <= 0)) {
- // We are out of space
- }
- if (MoreToReflow(state)) {
- rv = ReflowUnmapped(state);
- }
- }
-
-#ifdef NS_DEBUG
- if (0 != mContent->ChildCount()) {
- NS_ASSERTION(nsnull != mLines, "reflowed zero children");
- }
-#endif
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsBlockFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredRect.width, aDesiredRect.height));
- return rv;
-}
-
-nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
-{
- // Find the line that contains the aFrame
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsIFrame* child = line->mFirstChild;
- for (PRInt32 count = line->mChildCount; count > 0; count--) {
- if (child == aFrame) {
- return line;
- }
-
- child->GetNextSibling(child);
- }
-
- // Move to the next line
- line = line->mNextLine;
- }
-
- return nsnull;
-}
-
-nsLineData* nsBlockFrame::LastLine()
-{
- nsLineData* lastLine = mLines;
-
- // Get the last line
- if (nsnull != lastLine) {
- while (nsnull != lastLine->mNextLine) {
- lastLine = lastLine->mNextLine;
- }
- }
-
- return lastLine;
-}
-
-nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds)
-{
- // Now just reflow all the lines that follow...
- // XXX Obviously this needs to be more efficient
- return ReflowMappedFrom(aState, aLine->mNextLine);
-}
-
-void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect)
-{
- aDesiredRect.x = 0;
- aDesiredRect.y = 0;
-
- // Special check for zero sized content: If our content is zero
- // sized then we collapse into nothingness.
- if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
- (0 == aState.mY - aState.mBorderPadding.top)) {
- aDesiredRect.width = 0;
- aDesiredRect.height = 0;
- }
- else {
- aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
- if (!aState.mUnconstrainedWidth) {
- // Make sure we're at least as wide as the max size we were given
- nscoord maxWidth = aState.mAvailSize.width + aState.mBorderPadding.left +
- aState.mBorderPadding.right;
- if (aDesiredRect.width < maxWidth) {
- aDesiredRect.width = maxWidth;
- }
- }
- aState.mY += aState.mBorderPadding.bottom;
- nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
- aState.mPrevNegBottomMargin;
- if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
- // It's possible that we don't have room for the last bottom
- // margin (the last bottom margin is the margin following a block
- // element that we contain; it isn't applied immediately because
- // of the margin collapsing logic). This can happen when we are
- // reflowed in a limited amount of space because we don't know in
- // advance what the last bottom margin will be.
- nscoord maxY = aMaxSize.height;
- if (aState.mY + lastBottomMargin > maxY) {
- lastBottomMargin = maxY - aState.mY;
- if (lastBottomMargin < 0) {
- lastBottomMargin = 0;
- }
- }
- }
- aState.mY += lastBottomMargin;
- aDesiredRect.height = aState.mY;
-
- if (!aState.mBlockIsPseudo) {
- // Clamp the desired rect height when style height applies
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredRect.height = aState.mBorderPadding.top +
- aState.mStyleSize.height + aState.mBorderPadding.bottom;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-
-void nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame)
-{
- // Compute the available space for the floater. Use the default
- // 'auto' width and height values
- nsSize kidAvailSize(0, NS_UNCONSTRAINEDSIZE);
- nsSize styleSize;
- PRIntn styleSizeFlags = nsCSSLayout::GetStyleSize(aPresContext, *aState.reflowState,
- styleSize);
-
- // XXX The width and height are for the content area only. Add in space for
- // border and padding
- if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
- kidAvailSize.width = styleSize.width;
- }
- if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
- kidAvailSize.height = styleSize.height;
- }
-
- // Resize reflow the anchored item into the available space
- // XXX Check for complete?
- nsReflowMetrics desiredSize(nsnull);
- nsReflowState reflowState(aFloaterFrame, *aState.reflowState, kidAvailSize,
- eReflowReason_Initial);
- nsReflowStatus status;
-
- aFloaterFrame->WillReflow(*aPresContext);
- aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status);
- aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
-
- aFloaterFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
-}
-
-PRBool
-nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
-
- if (nsnull != state) {
- // Get the frame associated with the space manager, and get its
- // nsIAnchoredItems interface
- nsIFrame* frame = state->mSpaceManager->GetFrame();
- nsIAnchoredItems* anchoredItems = nsnull;
-
- frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
- NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
- if (nsnull != anchoredItems) {
- anchoredItems->AddAnchoredItem(aFloater,
- nsIAnchoredItems::anHTMLFloater,
- this);
-
- // Reflow the floater
- ReflowFloater(aPresContext, *state, aFloater);
-
- // Determine whether we place it at the top or we place it below the
- // current line
- if (IsLeftMostChild(aPlaceholder)) {
- if (nsnull == mRunInFloaters) {
- mRunInFloaters = new nsVoidArray;
- }
- mRunInFloaters->AppendElement(aPlaceholder);
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- } else {
- // Add the placeholder to our to-do list
- state->mPendingFloaters.AppendElement(aPlaceholder);
- }
- return PR_TRUE;
- }
- }
-
- return PR_FALSE;
-}
-
-// XXX Deprecated
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
-#if 0
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
- if (nsnull != state) {
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- }
-#endif
-}
-
-PRBool
-nsBlockFrame::IsLeftMostChild(nsIFrame* aFrame)
-{
- do {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
-
- // See if there are any non-zero sized child frames that precede
- // aFrame in the child list
- nsIFrame* child;
- parent->FirstChild(child);
- while ((nsnull != child) && (aFrame != child)) {
- nsSize size;
-
- // Is the child zero-sized?
- child->GetSize(size);
- if ((size.width > 0) || (size.height > 0)) {
- // We found a non-zero sized child frame that precedes aFrame
- return PR_FALSE;
- }
- child->GetNextSibling(child);
- }
-
- // aFrame is the left-most non-zero sized frame in its geometric parent.
- // Walk up one level and check that its parent is left-most as well
- aFrame = parent;
- } while (aFrame != this);
- return PR_TRUE;
-}
-
-// Used when placing run-in floaters (floaters displayed at the top of the
-// block as supposed to below the current line)
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState)
-{
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Get the type of floater
- const nsStyleDisplay* floaterDisplay;
- aFloater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay);
-
- // Commit some space in the space manager, and adjust our current
- // band of available space.
- nsRect region;
- aFloater->GetRect(region);
- region.y = aState.mY;
- if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
- region.x = aState.mX;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats,
- "bad float type");
- region.x = aState.mCurrentBand.availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->AddRectRegion(aFloater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- aFloater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Update the band of available space to reflect space taken up by
- // the floater
- GetAvailableSpace(aState, aState.mY);
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-// XXX It's unclear what coordinate space aY is in. Is it relative to the
-// upper-left origin of the containing block, or relative to aState.mY?
-void
-nsBlockFrame::PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY)
-{
- NS_PRECONDITION(aFloaterList->Count() > 0, "no floaters");
-
- nsISpaceManager* sm = aState.mSpaceManager;
- nsBlockBandData* bd = &aState.mCurrentBand;
-
- // XXX Factor this code with PlaceFloater()...
- PRInt32 numFloaters = aFloaterList->Count();
- for (PRInt32 i = 0; i < numFloaters; i++) {
- nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)aFloaterList->ElementAt(i);
- nsIFrame* floater = placeholderFrame->GetAnchoredItem();
- nsRect region;
-
- // Get the band of available space
- // XXX This is inefficient to do this inside the loop...
- GetAvailableSpace(aState, aY);
-
- // Get the type of floater
- const nsStyleDisplay* sd;
- floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)sd);
-
- floater->GetRect(region);
- // XXX GetAvailableSpace() is translating availSpace by aState.mY...
- region.y = bd->availSpace.y - aState.mY;
- if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
- region.x = bd->availSpace.x;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
- region.x = bd->availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- // XXX Temporary incremental hack
- sm->RemoveRegion(floater);
- sm->AddRectRegion(floater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- floater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
- }
-
- // Pass on updated available space to the current line
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- GetAvailableSpace(aState, aY);
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineData*
-nsBlockFrame::GetFirstLine()
-{
- return mLines;
-}
-
-PRIntn
-nsBlockFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_TOP;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_BOTTOM;
- }
- return skip;
-}
diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h
deleted file mode 100644
index 77b3e0ee8ff..00000000000
--- a/mozilla/layout/generic/nsBlockFrame.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#ifndef nsBlockFrame_h___
-#define nsBlockFrame_h___
-
-#include "nsHTMLContainerFrame.h"
-#include "nsIFloaterContainer.h"
-#include "nsIRunaround.h"
-#include "nsISpaceManager.h"
-#include "nsLineLayout.h"
-#include "nsVoidArray.h"
-
-struct nsMargin;
-struct nsStyleDisplay;
-struct nsStyleFont;
-struct nsStyleText;
-class nsBlockFrame;
-struct nsBandData;
-
-struct nsBlockBandData : public nsBandData {
- // Trapezoids used during band processing
- nsBandTrapezoid data[12];
-
- // Bounding rect of available space between any left and right floaters
- nsRect availSpace;
-
- nsBlockBandData() {
- size = 12;
- trapezoids = data;
- }
-
- /**
- * Computes the bounding rect of the available space, i.e. space
- * between any left and right floaters Uses the current trapezoid
- * data, see nsISpaceManager::GetBandData(). Also updates member
- * data "availSpace".
- */
- void ComputeAvailSpaceRect();
-};
-
-struct nsBlockReflowState {
- nsBlockReflowState();
- ~nsBlockReflowState();
-
- nsresult Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock);
-
- nsresult RecoverState(nsLineData* aLine);
-
- nsIPresContext* mPresContext;
-
- nsBlockFrame* mBlock;
- PRBool mBlockIsPseudo;
-
- // Current line being reflowed
- nsLineLayout* mCurrentLine;
-
- // Previous line's last child frame
- nsIFrame* mPrevKidFrame;
-
- // Layout position information
- nscoord mX;
- nscoord mY;
- nsSize mAvailSize;
- nsSize mStyleSize;
- PRIntn mStyleSizeFlags;
- PRPackedBool mUnconstrainedWidth;
- PRPackedBool mUnconstrainedHeight;
- nsSize* mMaxElementSizePointer;
- nscoord mKidXMost;
- const nsReflowState* reflowState;
-
- // Change in width since last reflow
- nscoord mDeltaWidth;
-
- // Bottom margin information from the previous line (only when
- // the previous line contains a block element)
- nscoord mPrevNegBottomMargin;
- nscoord mPrevPosBottomMargin;
- PRBool mPrevMarginSynthetic;
-
- // Block frame border+padding information
- nsMargin mBorderPadding;
-
- // Space manager and current band information
- nsISpaceManager* mSpaceManager;
- nsBlockBandData mCurrentBand;
-
- // Array of floaters to place below current line
- nsVoidArray mPendingFloaters;
-
- // The next list ordinal for counting list bullets
- PRInt32 mNextListOrdinal;
- PRBool mListPositionOutside;
-};
-
-//----------------------------------------------------------------------
-
-/* 94e8e410-de21-11d1-89bf-006008911b81 */
-#define NS_BLOCKFRAME_CID \
- {0x94e8e410, 0xde21, 0x11d1, {0x89, 0xbf, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
-
-/**
- *
Block Reflow
- *
- * The block frame reflow machinery performs "2D" layout. Inline
- * elements are flowed into logical lines (left to right or right to
- * left) and the lines are stacked vertically. nsLineLayout is used
- * for this part of the process. Block elements are flowed directly by
- * the block reflow logic after flushing out any preceeding line.
- *
- * During reflow, the block frame will make available to child frames
- * it's reflow state using the presentation shell's cached data
- * mechanism.
- *
- *
Reflowing Mapped Content
- * Pullup
- * Reflowing Unmapped Content
- * Content Insertion Handling
- * Content Deletion Handling
- * Style Change Handling
- *
- * Assertions
- * mLastContentIsComplete always reflects the state of the last
- * child frame on our chlid list.
- */
-
-// XXX we don't use nsContainerFrame mOverFlowList!!! wasted memory
-
-class nsBlockFrame : public nsHTMLContainerFrame,
- public nsIRunaround,
- public nsIFloaterContainer
-{
-public:
- /**
- * Create a new block frame that maps the given piece of content.
- */
- static nsresult NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent);
-
- // nsISupports
- NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
-
- // nsIFrame
- NS_IMETHOD ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer);
- NS_IMETHOD ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent);
- NS_IMETHOD ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent);
- NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent);
- NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics);
- NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
- NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame);
- NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
- NS_IMETHOD ListTag(FILE* out) const;
- NS_IMETHOD VerifyTree() const;
-
- // nsIRunaround
- NS_IMETHOD Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus);
-
- // nsIFloaterContainer
- virtual PRBool AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder);
- virtual void PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder);
-
- // nsBlockFrame
- nsresult ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
-
- nsresult ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus);
-
- static nsBlockReflowState* FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame);
-
-protected:
- nsBlockFrame(nsIContent* aContent, nsIFrame* aParent);
-
- virtual ~nsBlockFrame();
-
- virtual PRIntn GetSkipSides() const;
-
- virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow);
-
- nsresult InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState);
-
- void ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect);
-
- nsLineData* LastLine();
- nsLineData* FindLine(nsIFrame* aFrame);
-
- nsresult IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds);
-
- void DestroyLines();
-
- void DrainOverflowList();
-
- nsLineData* CreateLineForOverflowList(nsIFrame* aOverflowList);
-
-#ifdef NS_DEBUG
- nsresult VerifyLines(PRBool aFinalCheck) const;
-#endif
-
- void ClearFloaters(nsBlockReflowState& aState,
- PRUint8 aBreakType);
-
- nsresult PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine);
-
- PRBool IsLeftMostChild(nsIFrame* aFrame);
-
- void PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState);
- void PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY);
-
- nsresult GetAvailableSpace(nsBlockReflowState& aState, nscoord aY);
-
- PRBool MoreToReflow(nsBlockReflowState& aState);
-
- nsresult PushLines(nsBlockReflowState& aState,
- nsLineData* aLine);
-
- nsresult ReflowMapped(nsBlockReflowState& aState);
- nsresult ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine);
-
- nsresult ReflowUnmapped(nsBlockReflowState& aState);
-
- nsLineData* GetFirstLine();
-
- void ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame);
-
- void SetFirstChild(nsIFrame* aFirstChild) {
- if (nsnull == mFirstChild) {
- mFirstChild = aFirstChild;
- }
- }
-
- nsLineData* mLines;
- nsVoidArray* mRunInFloaters; // placeholder frames for floaters to display
- // at the top line
-
- friend struct nsLineLayout;
-};
-
-#endif /* nsBlockFrame_h___ */
diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp
deleted file mode 100644
index bf4fc11255c..00000000000
--- a/mozilla/layout/generic/nsBlockReflowState.cpp
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsBlockFrame.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIHTMLContent.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIAnchoredItems.h"
-#include "nsIReflowCommand.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIPtr.h"
-#include "nsHTMLAtoms.h"
-#include "nsHTMLIIDs.h"
-#include "nsHTMLValue.h"
-#include "nsCSSLayout.h"
-#include "nsIView.h"
-
-// XXX what do we do with catastrophic errors (rv < 0)? What is the
-// state of the reflow world after such an error?
-
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-//----------------------------------------------------------------------
-
-void nsBlockBandData::ComputeAvailSpaceRect()
-{
- nsBandTrapezoid* trapezoid = data;
-
- if (count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < count; i++) {
- nsBandTrapezoid* trapezoid = &data[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &data[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availSpace);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availSpace);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availSpace.x = availSpace.XMost();
- }
- availSpace.width = 0;
- }
-}
-
-//----------------------------------------------------------------------
-
-nsBlockReflowState::nsBlockReflowState()
-{
-}
-
-nsBlockReflowState::~nsBlockReflowState()
-{
-}
-
-nsresult
-nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock)
-{
- nsresult rv = NS_OK;
-
- mPresContext = aPresContext;
- mBlock = aBlock;
- mSpaceManager = aSpaceManager;
- mBlockIsPseudo = aBlock->IsPseudoFrame();
- mListPositionOutside = PR_FALSE;
- mCurrentLine = nsnull;
- mPrevKidFrame = nsnull;
- reflowState = &aReflowState;
-
- mX = 0;
- mY = 0;
- mStyleSizeFlags = 0;
- mAvailSize = reflowState->maxSize;
- mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE);
- mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE);
- mMaxElementSizePointer = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
- }
- mKidXMost = 0;
-
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = 0;
- mPrevMarginSynthetic = PR_FALSE;
-
- mNextListOrdinal = -1;
-
- return rv;
-}
-
-// Recover the block reflow state to what it should be if aLine is about
-// to be reflowed. aLine should not be nsnull
-nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
-{
- NS_PRECONDITION(nsnull != aLine, "null parameter");
- nsLineData* prevLine = aLine->mPrevLine;
-
- if (nsnull != prevLine) {
- // Compute the running y-offset, and the available height
- mY = prevLine->mBounds.YMost();
- if (!mUnconstrainedHeight) {
- mAvailSize.height -= mY;
- }
-
- // Compute the kid x-most
- for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
- nscoord xmost = l->mBounds.XMost();
- if (xmost > mKidXMost) {
- mKidXMost = xmost;
- }
- }
-
- // If the previous line is a block, then factor in its bottom margin
- if (prevLine->mIsBlock) {
- const nsStyleSpacing* kidSpacing;
- nsIFrame* kid = prevLine->mFirstChild;
-
- kid->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)kidSpacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kid, kidMargin);
- if (kidMargin.bottom < 0) {
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = -kidMargin.bottom;
- } else {
- mPrevPosBottomMargin = kidMargin.bottom;
- mPrevNegBottomMargin = 0;
- }
- }
- }
-
- return NS_OK;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsBlockFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsBlockFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsBlockFrame::~nsBlockFrame()
-{
- DestroyLines();
- delete mRunInFloaters;
-}
-
-void nsBlockFrame::DestroyLines()
-{
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- mLines = nsnull;
-}
-
-NS_METHOD
-nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
-{
- NS_PRECONDITION(0 != aInstancePtr, "null ptr");
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
- if (aIID.Equals(kBlockFrameCID)) {
- *aInstancePtr = (void*) (this);
- return NS_OK;
- }
- else if (aIID.Equals(kIRunaroundIID)) {
- *aInstancePtr = (void*) ((nsIRunaround*) this);
- return NS_OK;
- }
- else if (aIID.Equals(kIFloaterContainerIID)) {
- *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
- return NS_OK;
- }
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_METHOD
-nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
-{
- aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame)
-{
- nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
- if (nsnull == cf) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
- aContinuingFrame = cf;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::ListTag(FILE* out) const
-{
- if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
- fprintf(out, "*block<");
- nsIAtom* atom = mContent->GetTag();
- if (nsnull != atom) {
- nsAutoString tmp;
- atom->ToString(tmp);
- fputs(tmp, out);
- }
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, ">(%d)@%p", contentIndex, this);
- } else {
- nsHTMLContainerFrame::ListTag(out);
- }
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- NS_RELEASE(view);
- }
-
- // Output the first/last content offset
- fprintf(out, "[%d,%d,%c] ", mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
-
- // Output the children, one line at a time
- if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- aIndent++;
-
- nsLineData* line = mLines;
- while (nsnull != line) {
- line->List(out, aIndent);
- line = line->mNextLine;
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
-
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- nsresult rv = nsHTMLContainerFrame::VerifyTree();
- if (NS_OK != rv) {
- return rv;
- }
- rv = VerifyLines(PR_TRUE);
- return rv;
-#else
- return NS_OK;
-#endif
-}
-
-#ifdef NS_DEBUG
-nsresult
-nsBlockFrame::VerifyLines(PRBool aFinalCheck) const
-{
- nsresult rv = NS_OK;
-
- // Make sure that the list of children agrees with our child count.
- // If this is not the case then the child list and the line list are
- // not properly arranged.
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(mChildCount == len, "bad child list");
-
- // Verify that our lines are correctly setup
- PRInt32 offset = mFirstContentOffset;
- PRInt32 lineChildCount = 0;
- nsLineData* line = mLines;
- nsLineData* prevLine = nsnull;
- while (nsnull != line) {
- if (aFinalCheck) {
- NS_ASSERTION(((offset == line->mFirstContentOffset) &&
- (line->mFirstContentOffset <= line->mLastContentOffset)),
- "bad line mFirstContentOffset");
- NS_ASSERTION(line->mLastContentOffset <= mLastContentOffset,
- "bad line mLastContentOffset");
- offset = line->mLastContentOffset;
- if (line->mLastContentIsComplete) {
- offset++;
- }
- }
- lineChildCount += line->mChildCount;
- rv = line->Verify(aFinalCheck);
- if (NS_OK != rv) {
- return rv;
- }
- prevLine = line;
- line = line->mNextLine;
- }
- if (aFinalCheck && (nsnull != prevLine)) {
- NS_ASSERTION(prevLine->mLastContentOffset == mLastContentOffset,
- "bad mLastContentOffset");
- NS_ASSERTION(prevLine->mLastContentIsComplete == mLastContentIsComplete,
- "bad mLastContentIsComplete");
- }
- NS_ASSERTION(lineChildCount == mChildCount, "bad line counts");
-
- return rv;
-}
-#endif
-
-//----------------------------------------------------------------------
-
-// Remove a next-in-flow from from this block's list of lines
-
-// XXX problems here:
-// 1. we always have to start from the first line: slow!
-// 2. we can avoid this when the child is not the last child in a line
-
-void
-nsBlockFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
- // When a reflow indicates completion it's possible that
- // next-in-flows were just removed. We have to remove them from any
- // nsLineData's that follow the current line.
- nsLineData* line = mLines;
- while (nsnull != line) {
- if (line->mFirstChild == aNextInFlow) {
- // Remove child from line.
- if (0 == --line->mChildCount) {
- line->mFirstChild = nsnull;
- }
- else {
- // Fixup the line
- nsIFrame* nextKid;
- aNextInFlow->GetNextSibling(nextKid);
- line->mFirstChild = nextKid;
- nextKid->GetContentIndex(line->mFirstContentOffset);
- }
- break;
- }
- line = line->mNextLine;
- }
-}
-
-nsresult
-nsBlockFrame::ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(aLineLayout, aDesiredSize, aReflowState, aStatus);
- }
- else {
- aKidFrame->Reflow(aLineLayout.mPresContext, aDesiredSize, aReflowState,
- aStatus);
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
- nsIRunaround* reflowRunaround;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- // Get the band for this y-offset and see whether there are any floaters
- // that have changed the left/right edges.
- //
- // XXX In order to do this efficiently we should move all this code to
- // nsBlockFrame since it already has band data, and it's probably the only
- // one who calls this routine anyway
- nsBandData bandData;
- nsBandTrapezoid trapezoids[12];
- nsBandTrapezoid* trapezoid = trapezoids;
- nsRect availBand;
-
- bandData.trapezoids = trapezoids;
- bandData.size = 12;
- aSpaceManager->GetBandData(0, aReflowState.maxSize, bandData);
-
- if (bandData.count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < bandData.count; i++) {
- nsBandTrapezoid* trapezoid = &trapezoids[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &trapezoids[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availBand);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availBand);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availBand.x = availBand.XMost();
- }
- availBand.width = 0;
- }
-
- // Does the child frame support interface nsIRunaround?
- if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
- (void**)&reflowRunaround)) {
- // Yes, the child frame wants to interact directly with the space
- // manager.
- reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState,
- aDesiredRect, aStatus);
- } else {
- // No, use interface nsIFrame instead.
- if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
- if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) {
- // There are left/right floaters.
- aReflowState.maxSize.width = availBand.width;
- }
- }
-
- // XXX FIX ME
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-
- // Return the desired rect
- aDesiredRect.x = availBand.x;
- aDesiredRect.y = 0;
- aDesiredRect.width = aDesiredSize.width;
- aDesiredRect.height = aDesiredSize.height;
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
-
- return NS_OK;
-}
-
-nsLineData*
-nsBlockFrame::CreateLineForOverflowList(nsIFrame* aOverflowList)
-{
- nsLineData* newLine = new nsLineData();
- if (nsnull != newLine) {
- nsIFrame* kid = aOverflowList;
- newLine->mFirstChild = kid;
- kid->GetContentIndex(newLine->mFirstContentOffset);
- newLine->mLastContentOffset = -1;
- newLine->mLastContentIsComplete = PRPackedBool(0x255);
- PRInt32 kids = 0;
- while (nsnull != kid) {
- kids++;
- kid->GetNextSibling(kid);
- }
- newLine->mChildCount = kids;
- }
- return newLine;
-}
-
-void
-nsBlockFrame::DrainOverflowList()
-{
- nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
- if (nsnull != prevBlock) {
- nsIFrame* overflowList = prevBlock->mOverflowList;
- if (nsnull != overflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- NS_ASSERTION(nsnull == mLines, "bad overflow list");
-
- // Create a line to hold the entire overflow list
- nsLineData* newLine = CreateLineForOverflowList(overflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(overflowList);
- prevBlock->mOverflowList = nsnull;
-
- // The new line is the first line
- mLines = newLine;
- }
- }
-
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild,
- "overflow list but no mapped children");
-
- // Create a line to hold the overflow list
- nsLineData* newLine = CreateLineForOverflowList(mOverflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
-
- // The new line is appended after our other lines
- nsLineData* prevLine = nsnull;
- nsLineData* line = mLines;
- while (nsnull != line) {
- prevLine = line;
- line = line->mNextLine;
- }
- if (nsnull == prevLine) {
- mLines = newLine;
- }
- else {
- prevLine->mNextLine = newLine;
- newLine->mPrevLine = prevLine;
- }
- }
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_FALSE);
- }
-#endif
-}
-
-void
-nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint8 aBreakType)
-{
- for (;;) {
- if (aState.mCurrentBand.count <= 1) {
- // No floaters in this band therefore nothing to clear
- break;
- }
-
- // Find the Y coordinate to clear to
- nscoord clearYMost = aState.mY;
- nsRect tmp;
- PRInt32 i;
- for (i = 0; i < aState.mCurrentBand.count; i++) {
- const nsStyleDisplay* display;
- nsBandTrapezoid* trapezoid = &aState.mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 fn, numFrames = trapezoid->frames->Count();
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
-
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- }
-
- if (clearYMost == aState.mY) {
- // Nothing to clear
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::ClearFloaters: mY=%d clearYMost=%d\n",
- aState.mY, clearYMost));
-
- aState.mY = clearYMost + 1;
-
- // Get a new band
- GetAvailableSpace(aState, aState.mY);
- }
-}
-
-nsresult
-nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine)
-{
- // Before we place the line, make sure that it will fit in it's new
- // location. It always fits if the height isn't constrained or it's
- // the first line.
- if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
- if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
- // The line will not fit
- return PushLines(aState, aLine);
- }
- }
-
- // When the line is finally placed then we know that the child
- // frames have a stable location. This means that we can DidReflow
- // them marking them done. Note that when we are paginated this
- // optimization cannot be done because this may be a nested block
- // that will be pushed to a new page by the containing block and the
- // nested block can't know that during its reflow.
- // XXX and actually, this only always works for the block which is a
- // child of the body.
- if (!aState.mPresContext->IsPaginated()) {
- nsIAtom* tag = mContent->GetTag();
- if (nsHTMLAtoms::body == tag) {
- nsIFrame* child = aLine->mFirstChild;
- for (PRInt32 i = aLine->mChildCount; --i >= 0; ) {
- nsFrameState state;
- child->GetFrameState(state);
- if (NS_FRAME_IN_REFLOW & state) {
- child->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
- }
- child->GetNextSibling(child);
- }
-
- // Paint this portion of ourselves
- if (!aLine->mBounds.IsEmpty()) {
- Invalidate(aLine->mBounds);
- }
- }
- NS_IF_RELEASE(tag);
- }
-
- // Consume space and advance running values
- aState.mY += aLine->mBounds.height;
- if (nsnull != aState.mMaxElementSizePointer) {
- nsSize* maxSize = aState.mMaxElementSizePointer;
- if (aLineLayout.mState.mMaxElementSize.width > maxSize->width) {
- maxSize->width = aLineLayout.mState.mMaxElementSize.width;
- }
- if (aLineLayout.mState.mMaxElementSize.height > maxSize->height) {
- maxSize->height = aLineLayout.mState.mMaxElementSize.height;
- }
- }
- nscoord xmost = aLine->mBounds.XMost();
- if (xmost > aState.mKidXMost) {
- aState.mKidXMost = xmost;
- }
-
- // Process any pending break operations
- switch (aLineLayout.mPendingBreak) {
- default:
- break;
- case NS_STYLE_CLEAR_LEFT:
- case NS_STYLE_CLEAR_RIGHT:
- case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
- ClearFloaters(aState, aLineLayout.mPendingBreak);
- break;
- }
- // XXX for now clear the pending break; this is where support for
- // page breaks or column breaks could be partially handled.
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- // Any below current line floaters to place?
- // XXX We really want to know whether this is the initial reflow (reflow
- // unmapped) or a subsequent reflow in which case we only need to offset
- // the existing floaters...
- if (aState.mPendingFloaters.Count() > 0) {
- if (nsnull == aLine->mFloaters) {
- aLine->mFloaters = new nsVoidArray;
- }
- aLine->mFloaters->operator=(aState.mPendingFloaters);
- aState.mPendingFloaters.Clear();
- }
-
- if (nsnull != aLine->mFloaters) {
- PlaceBelowCurrentLineFloaters(aState, aLine->mFloaters, aState.mY);
- // XXX Factor in the height of the floaters as well when considering
- // whether the line fits.
- // The default policy is that if there isn't room for the floaters then
- // both the line and the floaters are pushed to the next-in-flow...
- }
-
- if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
- // The current y coordinate is now past our available space
- // rectangle. Get a new band of space.
- GetAvailableSpace(aState, aState.mY);
- }
-
- return NS_LINE_LAYOUT_COMPLETE;
-}
-
-// aY has borderpadding.top already factored in
-nsresult
-nsBlockFrame::GetAvailableSpace(nsBlockReflowState& aState, nscoord aY)
-{
- nsresult rv = NS_OK;
-
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Fill in band data for the specific Y coordinate
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->GetBandData(aY, aState.mAvailSize, aState.mCurrentBand);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
- aState.mCurrentBand.ComputeAvailSpaceRect();
-
- aState.mCurrentBand.availSpace.MoveBy(aState.mBorderPadding.left,
- aState.mY);
-
- return rv;
-}
-
-// Give aLine and any successive lines to the block's next-in-flow; if
-// we don't have a next-in-flow then push all the children onto our
-// overflow list.
-nsresult
-nsBlockFrame::PushLines(nsBlockReflowState& aState, nsLineData* aLine)
-{
- PRInt32 i;
-
- // Split our child-list in two; revert our last content offset and
- // completion status to the previous line.
- nsLineData* prevLine = aLine->mPrevLine;
- NS_PRECONDITION(nsnull != prevLine, "pushing first line");
- nsIFrame* prevKidFrame = prevLine->mFirstChild;
- for (i = prevLine->mChildCount - 1; --i >= 0; ) {
- prevKidFrame->GetNextSibling(prevKidFrame);
- }
-#ifdef NS_DEBUG
- nsIFrame* nextFrame;
- prevKidFrame->GetNextSibling(nextFrame);
- NS_ASSERTION(nextFrame == aLine->mFirstChild, "bad line list");
-#endif
- prevKidFrame->SetNextSibling(nsnull);
- prevLine->mNextLine = nsnull;
- mLastContentOffset = prevLine->mLastContentOffset;
- mLastContentIsComplete = prevLine->mLastContentIsComplete;
-
- // Push children to our next-in-flow if we have, or to our overflow list
- nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow;
- PRInt32 pushCount = 0;
- if (nsnull == nextInFlow) {
- // Place children on the overflow list
- mOverflowList = aLine->mFirstChild;
-
- // Destroy the lines
- nsLineData* line = aLine;
- while (nsnull != line) {
- pushCount += line->mChildCount;
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- }
- else {
- aLine->mPrevLine = nsnull;
-
- // Pass on the children to our next-in-flow
- nsLineData* line = aLine;
- prevLine = line;
- nsIFrame* lastKid = aLine->mFirstChild;
- nsIFrame* kid = lastKid;
- while (nsnull != line) {
- i = line->mChildCount;
- pushCount += i;
- NS_ASSERTION(kid == line->mFirstChild, "bad line list");
- while (--i >= 0) {
- kid->SetGeometricParent(nextInFlow);
- nsIFrame* contentParent;
- kid->GetContentParent(contentParent);
- if (this == contentParent) {
- kid->SetContentParent(nextInFlow);
- }
- lastKid = kid;
- kid->GetNextSibling(kid);
- }
- prevLine = line;
- line = line->mNextLine;
- }
-
- // Join the two line lists
- nsLineData* nextInFlowLine = nextInFlow->mLines;
- if (nsnull != nextInFlowLine) {
- lastKid->SetNextSibling(nextInFlowLine->mFirstChild);
- nextInFlowLine->mPrevLine = prevLine;
- }
- nsIFrame* firstKid = aLine->mFirstChild;
- prevLine->mNextLine = nextInFlowLine;
- nextInFlow->mLines = aLine;
- nextInFlow->mFirstChild = firstKid;
- nextInFlow->mChildCount += pushCount;
- firstKid->GetContentIndex(nextInFlow->mFirstContentOffset);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- nextInFlow->VerifyLines(PR_FALSE);
- }
-#endif
- }
- mChildCount -= pushCount;
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return NS_LINE_LAYOUT_NOT_COMPLETE;
-}
-
-nsresult
-nsBlockFrame::ReflowMapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // See if we have any run-in floaters to place
- if (nsnull != mRunInFloaters) {
- PlaceBelowCurrentLineFloaters(aState, mRunInFloaters, aState.mY);
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- nsLineData* line = mLines;
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != line) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);/* XXX move out of loop */
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-// XXX This is a short-term hack. It assumes that the caller has already recovered
-// the state, and that some space has been retrieved from the space manager...
-nsresult
-nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != aLine) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, aLine);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, aLine);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = aLine->mLastContentOffset;
- mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
- aLine = aLine->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // If we have no children and we have a prev-in-flow then we need to
- // pick up where it left off. If we have children, e.g. we're being
- // resized, then our content offset will have already been set
- // correctly.
- nsIFrame* kidPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsBlockFrame* prev = (nsBlockFrame*) mPrevInFlow;
- mFirstContentOffset = prev->NextChildOffset();// XXX Is this necessary?
- if (PR_FALSE == prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
-
- // Get to the last line where the new content may be added
- nsLineData* line = nsnull;
- nsLineData* prevLine = nsnull;
- if (nsnull != mLines) {
- line = mLines;
- while (nsnull != line->mNextLine) {
- line = line->mNextLine;
- }
- prevLine = line->mPrevLine;
-
- // If the last line is not complete then kidPrevInFlow should be
- // set to the last-line's last child.
- if (!line->mLastContentIsComplete) {
- kidPrevInFlow = line->GetLastChild();
- }
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- // Now reflow the new content until we are out of new content or out
- // of vertical space.
- PRInt32 kidIndex = NextChildOffset();
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- PRInt32 contentChildCount = mContent->ChildCount();
- while (kidIndex < contentChildCount) {
- if (nsnull == line) {
- if (!MoreToReflow(aState)) {
- break;
- }
- line = new nsLineData();
- if (nsnull == line) {
- rv = NS_ERROR_OUT_OF_MEMORY;
- goto done;
- }
- line->mFirstContentOffset = kidIndex;
- }
-
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Add line to the block; do this before placing the line in case
- // PushLines is needed.
- if (nsnull == prevLine) {
- // For the first line, initialize mFirstContentOffset
- mFirstContentOffset = line->mFirstContentOffset;
- mFirstChild = line->mFirstChild;
- mLines = line;
- }
- else {
- prevLine->mNextLine = line;
- line->mPrevLine = prevLine;
- }
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
- kidIndex = lineLayout.mState.mKidIndex;
- kidPrevInFlow = lineLayout.mKidPrevInFlow;
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- prevLine = line;
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
- if (aState.mBlockIsPseudo) {
- PropagateContentOffsets();
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState)
-{
- nsresult rv;
- rv = aState.Initialize(aPresContext, aSpaceManager,
- aReflowState, aMaxElementSize, this);
-
- // Apply border and padding adjustments for regular frames only
- if (!aState.mBlockIsPseudo) {
- const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStylePosition* myPosition = (const nsStylePosition*)
- mStyleContext->GetStyleData(eStyleStruct_Position);
-
- mySpacing->CalcBorderPaddingFor(this, aState.mBorderPadding);
- aState.mY = aState.mBorderPadding.top;
- aState.mX = aState.mBorderPadding.left;
-
- if (aState.mUnconstrainedWidth) {
- // If our width is unconstrained don't bother futzing with the
- // available width/height because they don't matter - we are
- // going to get reflowed again.
- aState.mDeltaWidth = NS_UNCONSTRAINEDSIZE;
- }
- else {
- // When we are constrained we need to apply the width/height
- // style properties. When we have a width/height it applies to
- // the content width/height of our box. The content width/height
- // doesn't include the border+padding so we have to add that in
- // instead of subtracting it out of our maxsize.
- nscoord lr =
- aState.mBorderPadding.left + aState.mBorderPadding.right;
-
- // Get and apply the stylistic size. Note: do not limit the
- // height until we are done reflowing.
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
- aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aState.mAvailSize.width = aState.mStyleSize.width + lr;
- }
- else {
- aState.mAvailSize.width -= lr;
- }
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
- }
- else {
- aState.mBorderPadding.SizeTo(0, 0, 0, 0);
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
-
- // Setup initial list ordinal value
- nsIAtom* tag = mContent->GetTag();
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- nsHTMLValue value;
- if (eContentAttr_HasValue ==
- ((nsIHTMLContent*)mContent)->GetAttribute(nsHTMLAtoms::start, value)) {
- if (eHTMLUnit_Integer == value.GetUnit()) {
- aState.mNextListOrdinal = value.GetIntValue();
- }
- }
- }
- NS_RELEASE(tag);
-
- // Setup list flags in block reflow state if this block is a list
- // item.
- const nsStyleDisplay* myDisplay = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_DISPLAY_LIST_ITEM == myDisplay->mDisplay) {
- const nsStyleList* myList = (const nsStyleList*)
- mStyleContext->GetStyleData(eStyleStruct_List);
- if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == myList->mListStylePosition) {
- aState.mListPositionOutside = PR_TRUE;
- }
- }
-
- return rv;
-}
-
-PRBool
-nsBlockFrame::MoreToReflow(nsBlockReflowState& aState)
-{
- PRBool rv = PR_FALSE;
- if (NextChildOffset() < mContent->ChildCount()) {
- rv = PR_TRUE;
- }
- return rv;
-}
-
-nsBlockReflowState*
-nsBlockFrame::FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame)
-{
- nsBlockReflowState* state = nsnull;
- if (nsnull != aFrame) {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
- while (nsnull != parent) {
- nsBlockFrame* block;
- nsresult rv = parent->QueryInterface(kBlockFrameCID, (void**) &block);
- if (NS_OK == rv) {
- nsIPresShell* shell = aPresContext->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(block);
- NS_RELEASE(shell);
- break;
- }
- parent->GetGeometricParent(parent);
- }
- }
- return state;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer)
-{
- return nsHTMLContainerFrame::ContentAppended(aShell, aPresContext, aContainer);
-}
-
-NS_METHOD
-nsBlockFrame::ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- return nsHTMLContainerFrame::ContentInserted(aShell, aPresContext, aContainer,
- aChild, aIndexInParent);
-}
-
-NS_METHOD
-nsBlockFrame::ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-NS_METHOD
-nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-// XXX if there is nothing special going on here, then remove this
-// implementation and let nsFrame do it.
-NS_METHOD
-nsBlockFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nsresult rv = NS_OK;
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = mRect.height;
- aMetrics.descent = 0;
- return rv;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PreReflowCheck();
- }
-#endif
-
- nsBlockReflowState state;
- nsresult rv = NS_OK;
-
- if (eReflowReason_Initial == aReflowState.reason) {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 == (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
- else {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 != (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- }
-
- aStatus = NS_FRAME_COMPLETE;
- rv = InitializeState(aPresContext, aSpaceManager, aReflowState,
- aDesiredSize.maxElementSize, state);
-
- NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d",
- aReflowState.reason, state.mDeltaWidth));
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- nsIPresShell* shell = state.mPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Is the reflow command target at us?
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
- if (this == target) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- if (nsIReflowCommand::FrameAppended == type) {
- nsLineData* lastLine = LastLine();
-
- // Restore the state
- if (nsnull != lastLine) {
- state.RecoverState(lastLine);
- }
-
- // Reflow unmapped children
- PRInt32 kidIndex = NextChildOffset();
- PRInt32 contentChildCount = mContent->ChildCount();
- if (kidIndex == contentChildCount) {
- // There is nothing to do here
- if (nsnull != lastLine) {
- state.mY = lastLine->mBounds.YMost();
- }
- }
- else {
- rv = ReflowUnmapped(state);
- }
- } else {
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- }
- } else {
- // The command is passing through us. Get the next frame in the
- // reflow chain
- nsIFrame* nextFrame;
- aReflowState.reflowCommand->GetNext(nextFrame);
-
- // Restore our state as if nextFrame is the next frame to reflow
- nsLineData* line = FindLine(nextFrame);
- state.RecoverState(line);
-
- // Get some available space to start reflowing with
- GetAvailableSpace(state, state.mY);
-
- // Reflow the affected line
- nsLineLayout lineLayout(state);
-
- state.mCurrentLine = &lineLayout;
- lineLayout.Initialize(state, line);
-
- // Have the line handle the incremental reflow
- nsRect oldBounds = line->mBounds;
- rv = lineLayout.IncrementalReflowFromChild(aReflowState.reflowCommand,
- nextFrame);
-
- // Now place the line. It's possible it won't fit
- rv = PlaceLine(state, lineLayout, line);
- // XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- state.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
-
- // Now figure out what to do with the frames that follow
- rv = IncrementalReflowAfter(state, line, rv, oldBounds);
- }
- }
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- } else {
- nsresult rv = NS_OK;
- nsIPresShell* shell = aPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Check for an overflow list
- DrainOverflowList();
-
- if (nsnull != mLines) {
- rv = ReflowMapped(state);
- }
-
- if (NS_OK == rv) {
- if ((nsnull != mLines) && (state.mAvailSize.height <= 0)) {
- // We are out of space
- }
- if (MoreToReflow(state)) {
- rv = ReflowUnmapped(state);
- }
- }
-
-#ifdef NS_DEBUG
- if (0 != mContent->ChildCount()) {
- NS_ASSERTION(nsnull != mLines, "reflowed zero children");
- }
-#endif
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsBlockFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredRect.width, aDesiredRect.height));
- return rv;
-}
-
-nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
-{
- // Find the line that contains the aFrame
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsIFrame* child = line->mFirstChild;
- for (PRInt32 count = line->mChildCount; count > 0; count--) {
- if (child == aFrame) {
- return line;
- }
-
- child->GetNextSibling(child);
- }
-
- // Move to the next line
- line = line->mNextLine;
- }
-
- return nsnull;
-}
-
-nsLineData* nsBlockFrame::LastLine()
-{
- nsLineData* lastLine = mLines;
-
- // Get the last line
- if (nsnull != lastLine) {
- while (nsnull != lastLine->mNextLine) {
- lastLine = lastLine->mNextLine;
- }
- }
-
- return lastLine;
-}
-
-nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds)
-{
- // Now just reflow all the lines that follow...
- // XXX Obviously this needs to be more efficient
- return ReflowMappedFrom(aState, aLine->mNextLine);
-}
-
-void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect)
-{
- aDesiredRect.x = 0;
- aDesiredRect.y = 0;
-
- // Special check for zero sized content: If our content is zero
- // sized then we collapse into nothingness.
- if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
- (0 == aState.mY - aState.mBorderPadding.top)) {
- aDesiredRect.width = 0;
- aDesiredRect.height = 0;
- }
- else {
- aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
- if (!aState.mUnconstrainedWidth) {
- // Make sure we're at least as wide as the max size we were given
- nscoord maxWidth = aState.mAvailSize.width + aState.mBorderPadding.left +
- aState.mBorderPadding.right;
- if (aDesiredRect.width < maxWidth) {
- aDesiredRect.width = maxWidth;
- }
- }
- aState.mY += aState.mBorderPadding.bottom;
- nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
- aState.mPrevNegBottomMargin;
- if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
- // It's possible that we don't have room for the last bottom
- // margin (the last bottom margin is the margin following a block
- // element that we contain; it isn't applied immediately because
- // of the margin collapsing logic). This can happen when we are
- // reflowed in a limited amount of space because we don't know in
- // advance what the last bottom margin will be.
- nscoord maxY = aMaxSize.height;
- if (aState.mY + lastBottomMargin > maxY) {
- lastBottomMargin = maxY - aState.mY;
- if (lastBottomMargin < 0) {
- lastBottomMargin = 0;
- }
- }
- }
- aState.mY += lastBottomMargin;
- aDesiredRect.height = aState.mY;
-
- if (!aState.mBlockIsPseudo) {
- // Clamp the desired rect height when style height applies
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredRect.height = aState.mBorderPadding.top +
- aState.mStyleSize.height + aState.mBorderPadding.bottom;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-
-void nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame)
-{
- // Compute the available space for the floater. Use the default
- // 'auto' width and height values
- nsSize kidAvailSize(0, NS_UNCONSTRAINEDSIZE);
- nsSize styleSize;
- PRIntn styleSizeFlags = nsCSSLayout::GetStyleSize(aPresContext, *aState.reflowState,
- styleSize);
-
- // XXX The width and height are for the content area only. Add in space for
- // border and padding
- if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
- kidAvailSize.width = styleSize.width;
- }
- if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
- kidAvailSize.height = styleSize.height;
- }
-
- // Resize reflow the anchored item into the available space
- // XXX Check for complete?
- nsReflowMetrics desiredSize(nsnull);
- nsReflowState reflowState(aFloaterFrame, *aState.reflowState, kidAvailSize,
- eReflowReason_Initial);
- nsReflowStatus status;
-
- aFloaterFrame->WillReflow(*aPresContext);
- aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status);
- aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
-
- aFloaterFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
-}
-
-PRBool
-nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
-
- if (nsnull != state) {
- // Get the frame associated with the space manager, and get its
- // nsIAnchoredItems interface
- nsIFrame* frame = state->mSpaceManager->GetFrame();
- nsIAnchoredItems* anchoredItems = nsnull;
-
- frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
- NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
- if (nsnull != anchoredItems) {
- anchoredItems->AddAnchoredItem(aFloater,
- nsIAnchoredItems::anHTMLFloater,
- this);
-
- // Reflow the floater
- ReflowFloater(aPresContext, *state, aFloater);
-
- // Determine whether we place it at the top or we place it below the
- // current line
- if (IsLeftMostChild(aPlaceholder)) {
- if (nsnull == mRunInFloaters) {
- mRunInFloaters = new nsVoidArray;
- }
- mRunInFloaters->AppendElement(aPlaceholder);
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- } else {
- // Add the placeholder to our to-do list
- state->mPendingFloaters.AppendElement(aPlaceholder);
- }
- return PR_TRUE;
- }
- }
-
- return PR_FALSE;
-}
-
-// XXX Deprecated
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
-#if 0
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
- if (nsnull != state) {
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- }
-#endif
-}
-
-PRBool
-nsBlockFrame::IsLeftMostChild(nsIFrame* aFrame)
-{
- do {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
-
- // See if there are any non-zero sized child frames that precede
- // aFrame in the child list
- nsIFrame* child;
- parent->FirstChild(child);
- while ((nsnull != child) && (aFrame != child)) {
- nsSize size;
-
- // Is the child zero-sized?
- child->GetSize(size);
- if ((size.width > 0) || (size.height > 0)) {
- // We found a non-zero sized child frame that precedes aFrame
- return PR_FALSE;
- }
- child->GetNextSibling(child);
- }
-
- // aFrame is the left-most non-zero sized frame in its geometric parent.
- // Walk up one level and check that its parent is left-most as well
- aFrame = parent;
- } while (aFrame != this);
- return PR_TRUE;
-}
-
-// Used when placing run-in floaters (floaters displayed at the top of the
-// block as supposed to below the current line)
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState)
-{
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Get the type of floater
- const nsStyleDisplay* floaterDisplay;
- aFloater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay);
-
- // Commit some space in the space manager, and adjust our current
- // band of available space.
- nsRect region;
- aFloater->GetRect(region);
- region.y = aState.mY;
- if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
- region.x = aState.mX;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats,
- "bad float type");
- region.x = aState.mCurrentBand.availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->AddRectRegion(aFloater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- aFloater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Update the band of available space to reflect space taken up by
- // the floater
- GetAvailableSpace(aState, aState.mY);
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-// XXX It's unclear what coordinate space aY is in. Is it relative to the
-// upper-left origin of the containing block, or relative to aState.mY?
-void
-nsBlockFrame::PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY)
-{
- NS_PRECONDITION(aFloaterList->Count() > 0, "no floaters");
-
- nsISpaceManager* sm = aState.mSpaceManager;
- nsBlockBandData* bd = &aState.mCurrentBand;
-
- // XXX Factor this code with PlaceFloater()...
- PRInt32 numFloaters = aFloaterList->Count();
- for (PRInt32 i = 0; i < numFloaters; i++) {
- nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)aFloaterList->ElementAt(i);
- nsIFrame* floater = placeholderFrame->GetAnchoredItem();
- nsRect region;
-
- // Get the band of available space
- // XXX This is inefficient to do this inside the loop...
- GetAvailableSpace(aState, aY);
-
- // Get the type of floater
- const nsStyleDisplay* sd;
- floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)sd);
-
- floater->GetRect(region);
- // XXX GetAvailableSpace() is translating availSpace by aState.mY...
- region.y = bd->availSpace.y - aState.mY;
- if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
- region.x = bd->availSpace.x;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
- region.x = bd->availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- // XXX Temporary incremental hack
- sm->RemoveRegion(floater);
- sm->AddRectRegion(floater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- floater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
- }
-
- // Pass on updated available space to the current line
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- GetAvailableSpace(aState, aY);
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineData*
-nsBlockFrame::GetFirstLine()
-{
- return mLines;
-}
-
-PRIntn
-nsBlockFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_TOP;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_BOTTOM;
- }
- return skip;
-}
diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h
deleted file mode 100644
index bf4fc11255c..00000000000
--- a/mozilla/layout/generic/nsBlockReflowState.h
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsBlockFrame.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIHTMLContent.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIAnchoredItems.h"
-#include "nsIReflowCommand.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIPtr.h"
-#include "nsHTMLAtoms.h"
-#include "nsHTMLIIDs.h"
-#include "nsHTMLValue.h"
-#include "nsCSSLayout.h"
-#include "nsIView.h"
-
-// XXX what do we do with catastrophic errors (rv < 0)? What is the
-// state of the reflow world after such an error?
-
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-//----------------------------------------------------------------------
-
-void nsBlockBandData::ComputeAvailSpaceRect()
-{
- nsBandTrapezoid* trapezoid = data;
-
- if (count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < count; i++) {
- nsBandTrapezoid* trapezoid = &data[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &data[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availSpace);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availSpace);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availSpace.x = availSpace.XMost();
- }
- availSpace.width = 0;
- }
-}
-
-//----------------------------------------------------------------------
-
-nsBlockReflowState::nsBlockReflowState()
-{
-}
-
-nsBlockReflowState::~nsBlockReflowState()
-{
-}
-
-nsresult
-nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock)
-{
- nsresult rv = NS_OK;
-
- mPresContext = aPresContext;
- mBlock = aBlock;
- mSpaceManager = aSpaceManager;
- mBlockIsPseudo = aBlock->IsPseudoFrame();
- mListPositionOutside = PR_FALSE;
- mCurrentLine = nsnull;
- mPrevKidFrame = nsnull;
- reflowState = &aReflowState;
-
- mX = 0;
- mY = 0;
- mStyleSizeFlags = 0;
- mAvailSize = reflowState->maxSize;
- mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE);
- mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE);
- mMaxElementSizePointer = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
- }
- mKidXMost = 0;
-
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = 0;
- mPrevMarginSynthetic = PR_FALSE;
-
- mNextListOrdinal = -1;
-
- return rv;
-}
-
-// Recover the block reflow state to what it should be if aLine is about
-// to be reflowed. aLine should not be nsnull
-nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
-{
- NS_PRECONDITION(nsnull != aLine, "null parameter");
- nsLineData* prevLine = aLine->mPrevLine;
-
- if (nsnull != prevLine) {
- // Compute the running y-offset, and the available height
- mY = prevLine->mBounds.YMost();
- if (!mUnconstrainedHeight) {
- mAvailSize.height -= mY;
- }
-
- // Compute the kid x-most
- for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
- nscoord xmost = l->mBounds.XMost();
- if (xmost > mKidXMost) {
- mKidXMost = xmost;
- }
- }
-
- // If the previous line is a block, then factor in its bottom margin
- if (prevLine->mIsBlock) {
- const nsStyleSpacing* kidSpacing;
- nsIFrame* kid = prevLine->mFirstChild;
-
- kid->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)kidSpacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kid, kidMargin);
- if (kidMargin.bottom < 0) {
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = -kidMargin.bottom;
- } else {
- mPrevPosBottomMargin = kidMargin.bottom;
- mPrevNegBottomMargin = 0;
- }
- }
- }
-
- return NS_OK;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsBlockFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsBlockFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsBlockFrame::~nsBlockFrame()
-{
- DestroyLines();
- delete mRunInFloaters;
-}
-
-void nsBlockFrame::DestroyLines()
-{
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- mLines = nsnull;
-}
-
-NS_METHOD
-nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
-{
- NS_PRECONDITION(0 != aInstancePtr, "null ptr");
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
- if (aIID.Equals(kBlockFrameCID)) {
- *aInstancePtr = (void*) (this);
- return NS_OK;
- }
- else if (aIID.Equals(kIRunaroundIID)) {
- *aInstancePtr = (void*) ((nsIRunaround*) this);
- return NS_OK;
- }
- else if (aIID.Equals(kIFloaterContainerIID)) {
- *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
- return NS_OK;
- }
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_METHOD
-nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
-{
- aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame)
-{
- nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
- if (nsnull == cf) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
- aContinuingFrame = cf;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::ListTag(FILE* out) const
-{
- if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
- fprintf(out, "*block<");
- nsIAtom* atom = mContent->GetTag();
- if (nsnull != atom) {
- nsAutoString tmp;
- atom->ToString(tmp);
- fputs(tmp, out);
- }
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, ">(%d)@%p", contentIndex, this);
- } else {
- nsHTMLContainerFrame::ListTag(out);
- }
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- NS_RELEASE(view);
- }
-
- // Output the first/last content offset
- fprintf(out, "[%d,%d,%c] ", mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
-
- // Output the children, one line at a time
- if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- aIndent++;
-
- nsLineData* line = mLines;
- while (nsnull != line) {
- line->List(out, aIndent);
- line = line->mNextLine;
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
-
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- nsresult rv = nsHTMLContainerFrame::VerifyTree();
- if (NS_OK != rv) {
- return rv;
- }
- rv = VerifyLines(PR_TRUE);
- return rv;
-#else
- return NS_OK;
-#endif
-}
-
-#ifdef NS_DEBUG
-nsresult
-nsBlockFrame::VerifyLines(PRBool aFinalCheck) const
-{
- nsresult rv = NS_OK;
-
- // Make sure that the list of children agrees with our child count.
- // If this is not the case then the child list and the line list are
- // not properly arranged.
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(mChildCount == len, "bad child list");
-
- // Verify that our lines are correctly setup
- PRInt32 offset = mFirstContentOffset;
- PRInt32 lineChildCount = 0;
- nsLineData* line = mLines;
- nsLineData* prevLine = nsnull;
- while (nsnull != line) {
- if (aFinalCheck) {
- NS_ASSERTION(((offset == line->mFirstContentOffset) &&
- (line->mFirstContentOffset <= line->mLastContentOffset)),
- "bad line mFirstContentOffset");
- NS_ASSERTION(line->mLastContentOffset <= mLastContentOffset,
- "bad line mLastContentOffset");
- offset = line->mLastContentOffset;
- if (line->mLastContentIsComplete) {
- offset++;
- }
- }
- lineChildCount += line->mChildCount;
- rv = line->Verify(aFinalCheck);
- if (NS_OK != rv) {
- return rv;
- }
- prevLine = line;
- line = line->mNextLine;
- }
- if (aFinalCheck && (nsnull != prevLine)) {
- NS_ASSERTION(prevLine->mLastContentOffset == mLastContentOffset,
- "bad mLastContentOffset");
- NS_ASSERTION(prevLine->mLastContentIsComplete == mLastContentIsComplete,
- "bad mLastContentIsComplete");
- }
- NS_ASSERTION(lineChildCount == mChildCount, "bad line counts");
-
- return rv;
-}
-#endif
-
-//----------------------------------------------------------------------
-
-// Remove a next-in-flow from from this block's list of lines
-
-// XXX problems here:
-// 1. we always have to start from the first line: slow!
-// 2. we can avoid this when the child is not the last child in a line
-
-void
-nsBlockFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
- // When a reflow indicates completion it's possible that
- // next-in-flows were just removed. We have to remove them from any
- // nsLineData's that follow the current line.
- nsLineData* line = mLines;
- while (nsnull != line) {
- if (line->mFirstChild == aNextInFlow) {
- // Remove child from line.
- if (0 == --line->mChildCount) {
- line->mFirstChild = nsnull;
- }
- else {
- // Fixup the line
- nsIFrame* nextKid;
- aNextInFlow->GetNextSibling(nextKid);
- line->mFirstChild = nextKid;
- nextKid->GetContentIndex(line->mFirstContentOffset);
- }
- break;
- }
- line = line->mNextLine;
- }
-}
-
-nsresult
-nsBlockFrame::ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(aLineLayout, aDesiredSize, aReflowState, aStatus);
- }
- else {
- aKidFrame->Reflow(aLineLayout.mPresContext, aDesiredSize, aReflowState,
- aStatus);
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
- nsIRunaround* reflowRunaround;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- // Get the band for this y-offset and see whether there are any floaters
- // that have changed the left/right edges.
- //
- // XXX In order to do this efficiently we should move all this code to
- // nsBlockFrame since it already has band data, and it's probably the only
- // one who calls this routine anyway
- nsBandData bandData;
- nsBandTrapezoid trapezoids[12];
- nsBandTrapezoid* trapezoid = trapezoids;
- nsRect availBand;
-
- bandData.trapezoids = trapezoids;
- bandData.size = 12;
- aSpaceManager->GetBandData(0, aReflowState.maxSize, bandData);
-
- if (bandData.count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < bandData.count; i++) {
- nsBandTrapezoid* trapezoid = &trapezoids[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &trapezoids[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availBand);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availBand);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availBand.x = availBand.XMost();
- }
- availBand.width = 0;
- }
-
- // Does the child frame support interface nsIRunaround?
- if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
- (void**)&reflowRunaround)) {
- // Yes, the child frame wants to interact directly with the space
- // manager.
- reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState,
- aDesiredRect, aStatus);
- } else {
- // No, use interface nsIFrame instead.
- if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
- if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) {
- // There are left/right floaters.
- aReflowState.maxSize.width = availBand.width;
- }
- }
-
- // XXX FIX ME
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-
- // Return the desired rect
- aDesiredRect.x = availBand.x;
- aDesiredRect.y = 0;
- aDesiredRect.width = aDesiredSize.width;
- aDesiredRect.height = aDesiredSize.height;
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
-
- return NS_OK;
-}
-
-nsLineData*
-nsBlockFrame::CreateLineForOverflowList(nsIFrame* aOverflowList)
-{
- nsLineData* newLine = new nsLineData();
- if (nsnull != newLine) {
- nsIFrame* kid = aOverflowList;
- newLine->mFirstChild = kid;
- kid->GetContentIndex(newLine->mFirstContentOffset);
- newLine->mLastContentOffset = -1;
- newLine->mLastContentIsComplete = PRPackedBool(0x255);
- PRInt32 kids = 0;
- while (nsnull != kid) {
- kids++;
- kid->GetNextSibling(kid);
- }
- newLine->mChildCount = kids;
- }
- return newLine;
-}
-
-void
-nsBlockFrame::DrainOverflowList()
-{
- nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
- if (nsnull != prevBlock) {
- nsIFrame* overflowList = prevBlock->mOverflowList;
- if (nsnull != overflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- NS_ASSERTION(nsnull == mLines, "bad overflow list");
-
- // Create a line to hold the entire overflow list
- nsLineData* newLine = CreateLineForOverflowList(overflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(overflowList);
- prevBlock->mOverflowList = nsnull;
-
- // The new line is the first line
- mLines = newLine;
- }
- }
-
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild,
- "overflow list but no mapped children");
-
- // Create a line to hold the overflow list
- nsLineData* newLine = CreateLineForOverflowList(mOverflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
-
- // The new line is appended after our other lines
- nsLineData* prevLine = nsnull;
- nsLineData* line = mLines;
- while (nsnull != line) {
- prevLine = line;
- line = line->mNextLine;
- }
- if (nsnull == prevLine) {
- mLines = newLine;
- }
- else {
- prevLine->mNextLine = newLine;
- newLine->mPrevLine = prevLine;
- }
- }
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_FALSE);
- }
-#endif
-}
-
-void
-nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint8 aBreakType)
-{
- for (;;) {
- if (aState.mCurrentBand.count <= 1) {
- // No floaters in this band therefore nothing to clear
- break;
- }
-
- // Find the Y coordinate to clear to
- nscoord clearYMost = aState.mY;
- nsRect tmp;
- PRInt32 i;
- for (i = 0; i < aState.mCurrentBand.count; i++) {
- const nsStyleDisplay* display;
- nsBandTrapezoid* trapezoid = &aState.mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 fn, numFrames = trapezoid->frames->Count();
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
-
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- }
-
- if (clearYMost == aState.mY) {
- // Nothing to clear
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::ClearFloaters: mY=%d clearYMost=%d\n",
- aState.mY, clearYMost));
-
- aState.mY = clearYMost + 1;
-
- // Get a new band
- GetAvailableSpace(aState, aState.mY);
- }
-}
-
-nsresult
-nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine)
-{
- // Before we place the line, make sure that it will fit in it's new
- // location. It always fits if the height isn't constrained or it's
- // the first line.
- if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
- if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
- // The line will not fit
- return PushLines(aState, aLine);
- }
- }
-
- // When the line is finally placed then we know that the child
- // frames have a stable location. This means that we can DidReflow
- // them marking them done. Note that when we are paginated this
- // optimization cannot be done because this may be a nested block
- // that will be pushed to a new page by the containing block and the
- // nested block can't know that during its reflow.
- // XXX and actually, this only always works for the block which is a
- // child of the body.
- if (!aState.mPresContext->IsPaginated()) {
- nsIAtom* tag = mContent->GetTag();
- if (nsHTMLAtoms::body == tag) {
- nsIFrame* child = aLine->mFirstChild;
- for (PRInt32 i = aLine->mChildCount; --i >= 0; ) {
- nsFrameState state;
- child->GetFrameState(state);
- if (NS_FRAME_IN_REFLOW & state) {
- child->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
- }
- child->GetNextSibling(child);
- }
-
- // Paint this portion of ourselves
- if (!aLine->mBounds.IsEmpty()) {
- Invalidate(aLine->mBounds);
- }
- }
- NS_IF_RELEASE(tag);
- }
-
- // Consume space and advance running values
- aState.mY += aLine->mBounds.height;
- if (nsnull != aState.mMaxElementSizePointer) {
- nsSize* maxSize = aState.mMaxElementSizePointer;
- if (aLineLayout.mState.mMaxElementSize.width > maxSize->width) {
- maxSize->width = aLineLayout.mState.mMaxElementSize.width;
- }
- if (aLineLayout.mState.mMaxElementSize.height > maxSize->height) {
- maxSize->height = aLineLayout.mState.mMaxElementSize.height;
- }
- }
- nscoord xmost = aLine->mBounds.XMost();
- if (xmost > aState.mKidXMost) {
- aState.mKidXMost = xmost;
- }
-
- // Process any pending break operations
- switch (aLineLayout.mPendingBreak) {
- default:
- break;
- case NS_STYLE_CLEAR_LEFT:
- case NS_STYLE_CLEAR_RIGHT:
- case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
- ClearFloaters(aState, aLineLayout.mPendingBreak);
- break;
- }
- // XXX for now clear the pending break; this is where support for
- // page breaks or column breaks could be partially handled.
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- // Any below current line floaters to place?
- // XXX We really want to know whether this is the initial reflow (reflow
- // unmapped) or a subsequent reflow in which case we only need to offset
- // the existing floaters...
- if (aState.mPendingFloaters.Count() > 0) {
- if (nsnull == aLine->mFloaters) {
- aLine->mFloaters = new nsVoidArray;
- }
- aLine->mFloaters->operator=(aState.mPendingFloaters);
- aState.mPendingFloaters.Clear();
- }
-
- if (nsnull != aLine->mFloaters) {
- PlaceBelowCurrentLineFloaters(aState, aLine->mFloaters, aState.mY);
- // XXX Factor in the height of the floaters as well when considering
- // whether the line fits.
- // The default policy is that if there isn't room for the floaters then
- // both the line and the floaters are pushed to the next-in-flow...
- }
-
- if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
- // The current y coordinate is now past our available space
- // rectangle. Get a new band of space.
- GetAvailableSpace(aState, aState.mY);
- }
-
- return NS_LINE_LAYOUT_COMPLETE;
-}
-
-// aY has borderpadding.top already factored in
-nsresult
-nsBlockFrame::GetAvailableSpace(nsBlockReflowState& aState, nscoord aY)
-{
- nsresult rv = NS_OK;
-
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Fill in band data for the specific Y coordinate
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->GetBandData(aY, aState.mAvailSize, aState.mCurrentBand);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
- aState.mCurrentBand.ComputeAvailSpaceRect();
-
- aState.mCurrentBand.availSpace.MoveBy(aState.mBorderPadding.left,
- aState.mY);
-
- return rv;
-}
-
-// Give aLine and any successive lines to the block's next-in-flow; if
-// we don't have a next-in-flow then push all the children onto our
-// overflow list.
-nsresult
-nsBlockFrame::PushLines(nsBlockReflowState& aState, nsLineData* aLine)
-{
- PRInt32 i;
-
- // Split our child-list in two; revert our last content offset and
- // completion status to the previous line.
- nsLineData* prevLine = aLine->mPrevLine;
- NS_PRECONDITION(nsnull != prevLine, "pushing first line");
- nsIFrame* prevKidFrame = prevLine->mFirstChild;
- for (i = prevLine->mChildCount - 1; --i >= 0; ) {
- prevKidFrame->GetNextSibling(prevKidFrame);
- }
-#ifdef NS_DEBUG
- nsIFrame* nextFrame;
- prevKidFrame->GetNextSibling(nextFrame);
- NS_ASSERTION(nextFrame == aLine->mFirstChild, "bad line list");
-#endif
- prevKidFrame->SetNextSibling(nsnull);
- prevLine->mNextLine = nsnull;
- mLastContentOffset = prevLine->mLastContentOffset;
- mLastContentIsComplete = prevLine->mLastContentIsComplete;
-
- // Push children to our next-in-flow if we have, or to our overflow list
- nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow;
- PRInt32 pushCount = 0;
- if (nsnull == nextInFlow) {
- // Place children on the overflow list
- mOverflowList = aLine->mFirstChild;
-
- // Destroy the lines
- nsLineData* line = aLine;
- while (nsnull != line) {
- pushCount += line->mChildCount;
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- }
- else {
- aLine->mPrevLine = nsnull;
-
- // Pass on the children to our next-in-flow
- nsLineData* line = aLine;
- prevLine = line;
- nsIFrame* lastKid = aLine->mFirstChild;
- nsIFrame* kid = lastKid;
- while (nsnull != line) {
- i = line->mChildCount;
- pushCount += i;
- NS_ASSERTION(kid == line->mFirstChild, "bad line list");
- while (--i >= 0) {
- kid->SetGeometricParent(nextInFlow);
- nsIFrame* contentParent;
- kid->GetContentParent(contentParent);
- if (this == contentParent) {
- kid->SetContentParent(nextInFlow);
- }
- lastKid = kid;
- kid->GetNextSibling(kid);
- }
- prevLine = line;
- line = line->mNextLine;
- }
-
- // Join the two line lists
- nsLineData* nextInFlowLine = nextInFlow->mLines;
- if (nsnull != nextInFlowLine) {
- lastKid->SetNextSibling(nextInFlowLine->mFirstChild);
- nextInFlowLine->mPrevLine = prevLine;
- }
- nsIFrame* firstKid = aLine->mFirstChild;
- prevLine->mNextLine = nextInFlowLine;
- nextInFlow->mLines = aLine;
- nextInFlow->mFirstChild = firstKid;
- nextInFlow->mChildCount += pushCount;
- firstKid->GetContentIndex(nextInFlow->mFirstContentOffset);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- nextInFlow->VerifyLines(PR_FALSE);
- }
-#endif
- }
- mChildCount -= pushCount;
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return NS_LINE_LAYOUT_NOT_COMPLETE;
-}
-
-nsresult
-nsBlockFrame::ReflowMapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // See if we have any run-in floaters to place
- if (nsnull != mRunInFloaters) {
- PlaceBelowCurrentLineFloaters(aState, mRunInFloaters, aState.mY);
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- nsLineData* line = mLines;
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != line) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);/* XXX move out of loop */
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-// XXX This is a short-term hack. It assumes that the caller has already recovered
-// the state, and that some space has been retrieved from the space manager...
-nsresult
-nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != aLine) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, aLine);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, aLine);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = aLine->mLastContentOffset;
- mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
- aLine = aLine->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // If we have no children and we have a prev-in-flow then we need to
- // pick up where it left off. If we have children, e.g. we're being
- // resized, then our content offset will have already been set
- // correctly.
- nsIFrame* kidPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsBlockFrame* prev = (nsBlockFrame*) mPrevInFlow;
- mFirstContentOffset = prev->NextChildOffset();// XXX Is this necessary?
- if (PR_FALSE == prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
-
- // Get to the last line where the new content may be added
- nsLineData* line = nsnull;
- nsLineData* prevLine = nsnull;
- if (nsnull != mLines) {
- line = mLines;
- while (nsnull != line->mNextLine) {
- line = line->mNextLine;
- }
- prevLine = line->mPrevLine;
-
- // If the last line is not complete then kidPrevInFlow should be
- // set to the last-line's last child.
- if (!line->mLastContentIsComplete) {
- kidPrevInFlow = line->GetLastChild();
- }
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- // Now reflow the new content until we are out of new content or out
- // of vertical space.
- PRInt32 kidIndex = NextChildOffset();
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- PRInt32 contentChildCount = mContent->ChildCount();
- while (kidIndex < contentChildCount) {
- if (nsnull == line) {
- if (!MoreToReflow(aState)) {
- break;
- }
- line = new nsLineData();
- if (nsnull == line) {
- rv = NS_ERROR_OUT_OF_MEMORY;
- goto done;
- }
- line->mFirstContentOffset = kidIndex;
- }
-
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Add line to the block; do this before placing the line in case
- // PushLines is needed.
- if (nsnull == prevLine) {
- // For the first line, initialize mFirstContentOffset
- mFirstContentOffset = line->mFirstContentOffset;
- mFirstChild = line->mFirstChild;
- mLines = line;
- }
- else {
- prevLine->mNextLine = line;
- line->mPrevLine = prevLine;
- }
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
- kidIndex = lineLayout.mState.mKidIndex;
- kidPrevInFlow = lineLayout.mKidPrevInFlow;
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- prevLine = line;
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
- if (aState.mBlockIsPseudo) {
- PropagateContentOffsets();
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState)
-{
- nsresult rv;
- rv = aState.Initialize(aPresContext, aSpaceManager,
- aReflowState, aMaxElementSize, this);
-
- // Apply border and padding adjustments for regular frames only
- if (!aState.mBlockIsPseudo) {
- const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStylePosition* myPosition = (const nsStylePosition*)
- mStyleContext->GetStyleData(eStyleStruct_Position);
-
- mySpacing->CalcBorderPaddingFor(this, aState.mBorderPadding);
- aState.mY = aState.mBorderPadding.top;
- aState.mX = aState.mBorderPadding.left;
-
- if (aState.mUnconstrainedWidth) {
- // If our width is unconstrained don't bother futzing with the
- // available width/height because they don't matter - we are
- // going to get reflowed again.
- aState.mDeltaWidth = NS_UNCONSTRAINEDSIZE;
- }
- else {
- // When we are constrained we need to apply the width/height
- // style properties. When we have a width/height it applies to
- // the content width/height of our box. The content width/height
- // doesn't include the border+padding so we have to add that in
- // instead of subtracting it out of our maxsize.
- nscoord lr =
- aState.mBorderPadding.left + aState.mBorderPadding.right;
-
- // Get and apply the stylistic size. Note: do not limit the
- // height until we are done reflowing.
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
- aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aState.mAvailSize.width = aState.mStyleSize.width + lr;
- }
- else {
- aState.mAvailSize.width -= lr;
- }
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
- }
- else {
- aState.mBorderPadding.SizeTo(0, 0, 0, 0);
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
-
- // Setup initial list ordinal value
- nsIAtom* tag = mContent->GetTag();
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- nsHTMLValue value;
- if (eContentAttr_HasValue ==
- ((nsIHTMLContent*)mContent)->GetAttribute(nsHTMLAtoms::start, value)) {
- if (eHTMLUnit_Integer == value.GetUnit()) {
- aState.mNextListOrdinal = value.GetIntValue();
- }
- }
- }
- NS_RELEASE(tag);
-
- // Setup list flags in block reflow state if this block is a list
- // item.
- const nsStyleDisplay* myDisplay = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_DISPLAY_LIST_ITEM == myDisplay->mDisplay) {
- const nsStyleList* myList = (const nsStyleList*)
- mStyleContext->GetStyleData(eStyleStruct_List);
- if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == myList->mListStylePosition) {
- aState.mListPositionOutside = PR_TRUE;
- }
- }
-
- return rv;
-}
-
-PRBool
-nsBlockFrame::MoreToReflow(nsBlockReflowState& aState)
-{
- PRBool rv = PR_FALSE;
- if (NextChildOffset() < mContent->ChildCount()) {
- rv = PR_TRUE;
- }
- return rv;
-}
-
-nsBlockReflowState*
-nsBlockFrame::FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame)
-{
- nsBlockReflowState* state = nsnull;
- if (nsnull != aFrame) {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
- while (nsnull != parent) {
- nsBlockFrame* block;
- nsresult rv = parent->QueryInterface(kBlockFrameCID, (void**) &block);
- if (NS_OK == rv) {
- nsIPresShell* shell = aPresContext->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(block);
- NS_RELEASE(shell);
- break;
- }
- parent->GetGeometricParent(parent);
- }
- }
- return state;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer)
-{
- return nsHTMLContainerFrame::ContentAppended(aShell, aPresContext, aContainer);
-}
-
-NS_METHOD
-nsBlockFrame::ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- return nsHTMLContainerFrame::ContentInserted(aShell, aPresContext, aContainer,
- aChild, aIndexInParent);
-}
-
-NS_METHOD
-nsBlockFrame::ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-NS_METHOD
-nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-// XXX if there is nothing special going on here, then remove this
-// implementation and let nsFrame do it.
-NS_METHOD
-nsBlockFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nsresult rv = NS_OK;
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = mRect.height;
- aMetrics.descent = 0;
- return rv;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PreReflowCheck();
- }
-#endif
-
- nsBlockReflowState state;
- nsresult rv = NS_OK;
-
- if (eReflowReason_Initial == aReflowState.reason) {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 == (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
- else {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 != (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- }
-
- aStatus = NS_FRAME_COMPLETE;
- rv = InitializeState(aPresContext, aSpaceManager, aReflowState,
- aDesiredSize.maxElementSize, state);
-
- NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d",
- aReflowState.reason, state.mDeltaWidth));
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- nsIPresShell* shell = state.mPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Is the reflow command target at us?
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
- if (this == target) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- if (nsIReflowCommand::FrameAppended == type) {
- nsLineData* lastLine = LastLine();
-
- // Restore the state
- if (nsnull != lastLine) {
- state.RecoverState(lastLine);
- }
-
- // Reflow unmapped children
- PRInt32 kidIndex = NextChildOffset();
- PRInt32 contentChildCount = mContent->ChildCount();
- if (kidIndex == contentChildCount) {
- // There is nothing to do here
- if (nsnull != lastLine) {
- state.mY = lastLine->mBounds.YMost();
- }
- }
- else {
- rv = ReflowUnmapped(state);
- }
- } else {
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- }
- } else {
- // The command is passing through us. Get the next frame in the
- // reflow chain
- nsIFrame* nextFrame;
- aReflowState.reflowCommand->GetNext(nextFrame);
-
- // Restore our state as if nextFrame is the next frame to reflow
- nsLineData* line = FindLine(nextFrame);
- state.RecoverState(line);
-
- // Get some available space to start reflowing with
- GetAvailableSpace(state, state.mY);
-
- // Reflow the affected line
- nsLineLayout lineLayout(state);
-
- state.mCurrentLine = &lineLayout;
- lineLayout.Initialize(state, line);
-
- // Have the line handle the incremental reflow
- nsRect oldBounds = line->mBounds;
- rv = lineLayout.IncrementalReflowFromChild(aReflowState.reflowCommand,
- nextFrame);
-
- // Now place the line. It's possible it won't fit
- rv = PlaceLine(state, lineLayout, line);
- // XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- state.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
-
- // Now figure out what to do with the frames that follow
- rv = IncrementalReflowAfter(state, line, rv, oldBounds);
- }
- }
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- } else {
- nsresult rv = NS_OK;
- nsIPresShell* shell = aPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Check for an overflow list
- DrainOverflowList();
-
- if (nsnull != mLines) {
- rv = ReflowMapped(state);
- }
-
- if (NS_OK == rv) {
- if ((nsnull != mLines) && (state.mAvailSize.height <= 0)) {
- // We are out of space
- }
- if (MoreToReflow(state)) {
- rv = ReflowUnmapped(state);
- }
- }
-
-#ifdef NS_DEBUG
- if (0 != mContent->ChildCount()) {
- NS_ASSERTION(nsnull != mLines, "reflowed zero children");
- }
-#endif
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsBlockFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredRect.width, aDesiredRect.height));
- return rv;
-}
-
-nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
-{
- // Find the line that contains the aFrame
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsIFrame* child = line->mFirstChild;
- for (PRInt32 count = line->mChildCount; count > 0; count--) {
- if (child == aFrame) {
- return line;
- }
-
- child->GetNextSibling(child);
- }
-
- // Move to the next line
- line = line->mNextLine;
- }
-
- return nsnull;
-}
-
-nsLineData* nsBlockFrame::LastLine()
-{
- nsLineData* lastLine = mLines;
-
- // Get the last line
- if (nsnull != lastLine) {
- while (nsnull != lastLine->mNextLine) {
- lastLine = lastLine->mNextLine;
- }
- }
-
- return lastLine;
-}
-
-nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds)
-{
- // Now just reflow all the lines that follow...
- // XXX Obviously this needs to be more efficient
- return ReflowMappedFrom(aState, aLine->mNextLine);
-}
-
-void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect)
-{
- aDesiredRect.x = 0;
- aDesiredRect.y = 0;
-
- // Special check for zero sized content: If our content is zero
- // sized then we collapse into nothingness.
- if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
- (0 == aState.mY - aState.mBorderPadding.top)) {
- aDesiredRect.width = 0;
- aDesiredRect.height = 0;
- }
- else {
- aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
- if (!aState.mUnconstrainedWidth) {
- // Make sure we're at least as wide as the max size we were given
- nscoord maxWidth = aState.mAvailSize.width + aState.mBorderPadding.left +
- aState.mBorderPadding.right;
- if (aDesiredRect.width < maxWidth) {
- aDesiredRect.width = maxWidth;
- }
- }
- aState.mY += aState.mBorderPadding.bottom;
- nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
- aState.mPrevNegBottomMargin;
- if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
- // It's possible that we don't have room for the last bottom
- // margin (the last bottom margin is the margin following a block
- // element that we contain; it isn't applied immediately because
- // of the margin collapsing logic). This can happen when we are
- // reflowed in a limited amount of space because we don't know in
- // advance what the last bottom margin will be.
- nscoord maxY = aMaxSize.height;
- if (aState.mY + lastBottomMargin > maxY) {
- lastBottomMargin = maxY - aState.mY;
- if (lastBottomMargin < 0) {
- lastBottomMargin = 0;
- }
- }
- }
- aState.mY += lastBottomMargin;
- aDesiredRect.height = aState.mY;
-
- if (!aState.mBlockIsPseudo) {
- // Clamp the desired rect height when style height applies
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredRect.height = aState.mBorderPadding.top +
- aState.mStyleSize.height + aState.mBorderPadding.bottom;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-
-void nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame)
-{
- // Compute the available space for the floater. Use the default
- // 'auto' width and height values
- nsSize kidAvailSize(0, NS_UNCONSTRAINEDSIZE);
- nsSize styleSize;
- PRIntn styleSizeFlags = nsCSSLayout::GetStyleSize(aPresContext, *aState.reflowState,
- styleSize);
-
- // XXX The width and height are for the content area only. Add in space for
- // border and padding
- if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
- kidAvailSize.width = styleSize.width;
- }
- if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
- kidAvailSize.height = styleSize.height;
- }
-
- // Resize reflow the anchored item into the available space
- // XXX Check for complete?
- nsReflowMetrics desiredSize(nsnull);
- nsReflowState reflowState(aFloaterFrame, *aState.reflowState, kidAvailSize,
- eReflowReason_Initial);
- nsReflowStatus status;
-
- aFloaterFrame->WillReflow(*aPresContext);
- aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status);
- aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
-
- aFloaterFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
-}
-
-PRBool
-nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
-
- if (nsnull != state) {
- // Get the frame associated with the space manager, and get its
- // nsIAnchoredItems interface
- nsIFrame* frame = state->mSpaceManager->GetFrame();
- nsIAnchoredItems* anchoredItems = nsnull;
-
- frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
- NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
- if (nsnull != anchoredItems) {
- anchoredItems->AddAnchoredItem(aFloater,
- nsIAnchoredItems::anHTMLFloater,
- this);
-
- // Reflow the floater
- ReflowFloater(aPresContext, *state, aFloater);
-
- // Determine whether we place it at the top or we place it below the
- // current line
- if (IsLeftMostChild(aPlaceholder)) {
- if (nsnull == mRunInFloaters) {
- mRunInFloaters = new nsVoidArray;
- }
- mRunInFloaters->AppendElement(aPlaceholder);
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- } else {
- // Add the placeholder to our to-do list
- state->mPendingFloaters.AppendElement(aPlaceholder);
- }
- return PR_TRUE;
- }
- }
-
- return PR_FALSE;
-}
-
-// XXX Deprecated
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
-#if 0
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
- if (nsnull != state) {
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- }
-#endif
-}
-
-PRBool
-nsBlockFrame::IsLeftMostChild(nsIFrame* aFrame)
-{
- do {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
-
- // See if there are any non-zero sized child frames that precede
- // aFrame in the child list
- nsIFrame* child;
- parent->FirstChild(child);
- while ((nsnull != child) && (aFrame != child)) {
- nsSize size;
-
- // Is the child zero-sized?
- child->GetSize(size);
- if ((size.width > 0) || (size.height > 0)) {
- // We found a non-zero sized child frame that precedes aFrame
- return PR_FALSE;
- }
- child->GetNextSibling(child);
- }
-
- // aFrame is the left-most non-zero sized frame in its geometric parent.
- // Walk up one level and check that its parent is left-most as well
- aFrame = parent;
- } while (aFrame != this);
- return PR_TRUE;
-}
-
-// Used when placing run-in floaters (floaters displayed at the top of the
-// block as supposed to below the current line)
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState)
-{
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Get the type of floater
- const nsStyleDisplay* floaterDisplay;
- aFloater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay);
-
- // Commit some space in the space manager, and adjust our current
- // band of available space.
- nsRect region;
- aFloater->GetRect(region);
- region.y = aState.mY;
- if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
- region.x = aState.mX;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats,
- "bad float type");
- region.x = aState.mCurrentBand.availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->AddRectRegion(aFloater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- aFloater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Update the band of available space to reflect space taken up by
- // the floater
- GetAvailableSpace(aState, aState.mY);
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-// XXX It's unclear what coordinate space aY is in. Is it relative to the
-// upper-left origin of the containing block, or relative to aState.mY?
-void
-nsBlockFrame::PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY)
-{
- NS_PRECONDITION(aFloaterList->Count() > 0, "no floaters");
-
- nsISpaceManager* sm = aState.mSpaceManager;
- nsBlockBandData* bd = &aState.mCurrentBand;
-
- // XXX Factor this code with PlaceFloater()...
- PRInt32 numFloaters = aFloaterList->Count();
- for (PRInt32 i = 0; i < numFloaters; i++) {
- nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)aFloaterList->ElementAt(i);
- nsIFrame* floater = placeholderFrame->GetAnchoredItem();
- nsRect region;
-
- // Get the band of available space
- // XXX This is inefficient to do this inside the loop...
- GetAvailableSpace(aState, aY);
-
- // Get the type of floater
- const nsStyleDisplay* sd;
- floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)sd);
-
- floater->GetRect(region);
- // XXX GetAvailableSpace() is translating availSpace by aState.mY...
- region.y = bd->availSpace.y - aState.mY;
- if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
- region.x = bd->availSpace.x;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
- region.x = bd->availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- // XXX Temporary incremental hack
- sm->RemoveRegion(floater);
- sm->AddRectRegion(floater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- floater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
- }
-
- // Pass on updated available space to the current line
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- GetAvailableSpace(aState, aY);
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineData*
-nsBlockFrame::GetFirstLine()
-{
- return mLines;
-}
-
-PRIntn
-nsBlockFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_TOP;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_BOTTOM;
- }
- return skip;
-}
diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.cpp b/mozilla/layout/generic/nsHTMLContainerFrame.cpp
index 12ea5df79c8..7905c8f03a0 100644
--- a/mozilla/layout/generic/nsHTMLContainerFrame.cpp
+++ b/mozilla/layout/generic/nsHTMLContainerFrame.cpp
@@ -207,62 +207,6 @@ static void AdjustIndexInParents(nsIFrame* aContainerFrame,
}
}
-nsresult
-nsHTMLContainerFrame::CreateFrameFor(nsIPresContext* aPresContext,
- nsIContent* aContent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aResult)
-{
- // Get the style data for the frame
- const nsStylePosition* position = (const nsStylePosition*)
- aStyleContext->GetStyleData(eStyleStruct_Position);
- const nsStyleDisplay* display = (const nsStyleDisplay*)
- aStyleContext->GetStyleData(eStyleStruct_Display);
- nsIFrame* frame = nsnull;
-
- // See whether it wants any special handling
- nsresult rv;
- if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) {
- rv = nsAbsoluteFrame::NewFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else if (display->mFloats != NS_STYLE_FLOAT_NONE) {
- rv = nsPlaceholderFrame::NewFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else if ((NS_STYLE_OVERFLOW_SCROLL == display->mOverflow) ||
- (NS_STYLE_OVERFLOW_AUTO == display->mOverflow)) {
- rv = NS_NewScrollFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
- rv = nsFrame::NewFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else {
- // Ask the content delegate to create the frame
- nsIContentDelegate* delegate = aContent->GetDelegate(aPresContext);
- rv = delegate->CreateFrame(aPresContext, aContent, this,
- aStyleContext, frame);
- NS_RELEASE(delegate);
- }
- if (NS_OK == rv) {
- // Wrap the frame in a view if necessary
- rv = nsHTMLBase::CreateViewForFrame(aPresContext, frame, aStyleContext,
- PR_FALSE);
- }
- aResult = frame;
- return rv;
-}
-
NS_METHOD nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
@@ -321,7 +265,8 @@ NS_METHOD nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
nsIStyleContext* kidSC;
kidSC = aPresContext->ResolveStyleContextFor(aChild, parent);
nsIFrame* newFrame;
- nsresult rv = parent->CreateFrameFor(aPresContext, aChild, kidSC, newFrame);
+//XXX nsresult rv = parent->CreateFrameFor(aPresContext, aChild, kidSC, newFrame);
+ nsresult rv = nsHTMLBase::CreateFrame(aPresContext, this, aChild, nsnull, newFrame);
if (NS_OK != rv) {
return rv;
}
@@ -369,23 +314,25 @@ NS_METHOD nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
nsresult
nsHTMLContainerFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
{
- const nsStyleDisplay* display = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("nsHTMLContainerFrame::ProcessInitialReflow: display=%d",
- display->mDisplay));
- if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
- // This container is a list-item container. Therefore it needs a
- // bullet content object.
- nsIHTMLContent* bullet;
- nsresult rv = NS_NewHTMLBullet(&bullet);
- if (NS_OK != rv) {
- return rv;
- }
+ if (nsnull == mPrevInFlow) {
+ const nsStyleDisplay* display = (const nsStyleDisplay*)
+ mStyleContext->GetStyleData(eStyleStruct_Display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("nsHTMLContainerFrame::ProcessInitialReflow: display=%d",
+ display->mDisplay));
+ if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
+ // This container is a list-item container. Therefore it needs a
+ // bullet content object.
+ nsIHTMLContent* bullet;
+ nsresult rv = NS_NewHTMLBullet(&bullet);
+ if (NS_OK != rv) {
+ return rv;
+ }
- // Insert the bullet. Do not allow an incremental reflow operation
- // to occur.
- mContent->InsertChildAt(bullet, 0, PR_FALSE);
+ // Insert the bullet. Do not allow an incremental reflow operation
+ // to occur.
+ mContent->InsertChildAt(bullet, 0, PR_FALSE);
+ }
}
return NS_OK;
diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.h b/mozilla/layout/generic/nsHTMLContainerFrame.h
index aefa2feb007..c7d4a11a232 100644
--- a/mozilla/layout/generic/nsHTMLContainerFrame.h
+++ b/mozilla/layout/generic/nsHTMLContainerFrame.h
@@ -56,12 +56,8 @@ protected:
virtual PRIntn GetSkipSides() const = 0;
- nsresult CreateFrameFor(nsIPresContext* aPresContext,
- nsIContent* aContent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aResult);
-
nsresult ProcessInitialReflow(nsIPresContext* aPresContext);
};
#endif /* nsHTMLContainerFrame_h___ */
+
diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp
deleted file mode 100644
index 06a623a8d1b..00000000000
--- a/mozilla/layout/generic/nsInlineFrame.cpp
+++ /dev/null
@@ -1,1288 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsInlineFrame.h"
-#include "nsBlockFrame.h"
-#include "nsSize.h"
-#include "nsIContent.h"
-#include "nsIContentDelegate.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsCSSLayout.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIReflowCommand.h"
-#include "nsHTMLAtoms.h"
-#include "nsAbsoluteFrame.h"
-#include "nsLeafFrame.h"
-#include "nsIPtr.h"
-
-// XXX To Do:
-// 2. horizontal child margins
-// 3. borders/padding and splitting
-// 4. child relative positioning
-// 5. absolutely positioned children
-// 6. direction support
-// 7. CSS line-height property
-
-/* XXX */
-#include "nsHTMLIIDs.h"
-#include "nsBlockFrame.h"
-
-#define DEFAULT_ASCENT_LEN 10
-
-NS_DEF_PTR(nsIStyleContext);
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIContentDelegate);
-
-class nsInlineState
-{
-public:
- const nsStyleFont* font; // style font
- nsMargin borderPadding; // inner margin
- nsSize mStyleSize;
- PRIntn mStyleSizeFlags;
- nsSize availSize; // available space in which to reflow (starts as max size minus insets)
- nsSize* maxElementSize; // maximum element size (may be null)
- nscoord x; // running x-offset (starts at left inner edge)
- const nscoord y; // y-offset (top inner edge)
- nscoord maxAscent; // max child ascent
- nscoord maxDescent; // max child descent
- nscoord* ascents; // ascent information for each child
- PRBool unconstrainedWidth;
- PRBool unconstrainedHeight;
- nsLineLayout* lineLayout;
- PRBool atBreakPoint;
- const nsReflowState& reflowState;
- PRBool mNoWrap;
-
- // Constructor
- nsInlineState(nsIPresContext* aPresContext,
- nsIFrame* aInlineFrame,
- const nsStyleFont* aStyleFont,
- const nsMargin& aBorderPadding,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize)
- : x(aBorderPadding.left), // determined by inner edge
- y(aBorderPadding.top), // determined by inner edge
- reflowState(aReflowState)
- {
- nsBlockReflowState* brs =
- nsBlockFrame::FindBlockReflowState(aPresContext, aInlineFrame);
- lineLayout = brs->mCurrentLine;
- atBreakPoint = PR_TRUE;
-
- font = aStyleFont;
- borderPadding = aBorderPadding;
-
- unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE);
- unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE);
-
- // If we're constrained adjust the available size so it excludes space
- // needed for border/padding
- availSize.width = reflowState.maxSize.width;
- if (PR_FALSE == unconstrainedWidth) {
- availSize.width -= aBorderPadding.left + aBorderPadding.right;
- }
- availSize.height = reflowState.maxSize.height;
- if (PR_FALSE == unconstrainedHeight) {
- availSize.height -= aBorderPadding.top + aBorderPadding.bottom;
- }
-
- // Initialize max element size
- maxElementSize = aMaxElementSize;
- if (nsnull != maxElementSize) {
- maxElementSize->SizeTo(0, 0);
- }
-
- ascents = ascentBuf;
- maxAscent = 0;
- maxDescent = 0;
- mNoWrap = PR_FALSE;
- }
-
- void SetNumAscents(PRIntn aNumAscents) {
- // We keep around ascent information so that we can vertically align
- // children after we figure out how many children fit.
- if (aNumAscents > DEFAULT_ASCENT_LEN) {
- ascents = new nscoord[aNumAscents];
- }
- }
-
- // Destructor
- ~nsInlineState() {
- if (ascents != ascentBuf) {
- delete ascents;
- }
- }
-
-private:
- nscoord ascentBuf[DEFAULT_ASCENT_LEN];
-};
-
-/////////////////////////////////////////////////////////////////////////////
-//
-
-nsresult nsInlineFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsInlineFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsInlineFrame::nsInlineFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
- NS_PRECONDITION(!IsPseudoFrame(), "can not be a pseudo frame");
-}
-
-nsInlineFrame::~nsInlineFrame()
-{
-}
-
-nsReflowStatus
-nsInlineFrame::ReflowChild(nsInlineState& aState,
- nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState)
-{
- nsReflowStatus status;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
-
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(*aState.lineLayout, aDesiredSize, aReflowState, status);
- }
- else {
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, status);
- }
-
- if (NS_FRAME_IS_COMPLETE(status)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return status;
-}
-
-void nsInlineFrame::PlaceChild(nsIFrame* aChild,
- PRInt32 aIndex,
- nsInlineState& aState,
- const nsReflowMetrics& aChildSize,
- const nsSize* aChildMaxElementSize)
-{
- // Set the child's rect
- aChild->SetRect(nsRect(aState.x, aState.y, aChildSize.width, aChildSize.height));
-
- // Adjust the running x-offset
- aState.x += aChildSize.width;
-
- // Update the array of ascents and the max ascent and descent
- aState.ascents[aIndex] = aChildSize.ascent;
- if (aChildSize.ascent > aState.maxAscent) {
- aState.maxAscent = aChildSize.ascent;
- }
- if (aChildSize.descent > aState.maxDescent) {
- aState.maxDescent = aChildSize.descent;
- }
-
- // If we're constrained then update the available width
- if (!aState.unconstrainedWidth) {
- aState.availSize.width -= aChildSize.width;
- }
-
- // Update the maximum element size
- if (nsnull != aChildMaxElementSize) {
- if (aChildMaxElementSize->width > aState.maxElementSize->width) {
- aState.maxElementSize->width = aChildMaxElementSize->width;
- }
- if (aChildMaxElementSize->height > aState.maxElementSize->height) {
- aState.maxElementSize->height = aChildMaxElementSize->height;
- }
- }
-}
-
-// XXX an image shouldn't be allowed to continue a word but text
-// should. hmmm.
-
-PRBool
-nsInlineFrame::CanFitChild(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame)
-{
- PRBool result = PR_TRUE;
- aState.atBreakPoint = nsnull == aState.lineLayout->mBreakFrame;
- if ((aState.availSize.width <= 0) &&
- (aChildFrame != mFirstChild) && (nsnull != mFirstChild)) {
- // If we are at a breakable position then it's ok to be out of
- // room. Otherwise the child is allowed to fit.
- if (aState.atBreakPoint) {
- result = PR_FALSE;
- }
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsInlineFrame::CanFitChild: availSize=%d result=%s",
- aState.availSize.width, result ? "true" : "false"));
- return result;
-}
-
-// XXX dup first-child check because of calling code not being nice! ick!
-PRBool
-nsInlineFrame::DidFitChild(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- nsReflowMetrics& aChildMetrics)
-{
- if ((aChildMetrics.width > aState.availSize.width) &&
- (aChildFrame != mFirstChild) && (nsnull != mFirstChild)) {
- // If we *were* at a breakable position then it's ok to be out of
- // room. Otherwise the child is allowed to fit.
- if (aState.atBreakPoint) {
- return PR_FALSE;
- }
- }
- return PR_TRUE;
-}
-
-/**
- * Reflow the frames we've already created
- *
- * @param aPresContext presentation context to use
- * @param aState current inline state
- * @param aChildFrame the first child frame to reflow
- * @param aChildIndex the first child frame's index in the frame list
- * @return true if we successfully reflowed all the mapped children and false
- * otherwise, e.g. we pushed children to the next in flow
- */
-PRBool
-nsInlineFrame::ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
- NS_PRECONDITION(nsnull != aChildFrame, "no children");
-
- PRInt32 childCount = aChildIndex;
- nsIFrame* prevKidFrame = nsnull;
-
- // Remember our original mLastContentIsComplete so that if we end up
- // having to push children, we have the correct value to hand to
- // PushChildren.
- PRBool originalLastContentIsComplete = mLastContentIsComplete;
-
- nsSize kidMaxElementSize;
- nsSize* pKidMaxElementSize = (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
- PRBool result = PR_TRUE;
-
- for (nsIFrame* kidFrame = aChildFrame; nsnull != kidFrame; ) {
- // If the previous child just reflowed has indicated a pending
- // break, stop reflowing our remaining children. This can only
- // happen when a prev-in-flow has pushed some junk into this
- // frame.
- if (NS_STYLE_CLEAR_NONE != aState.lineLayout->mPendingBreak) {
- PushChildren(kidFrame, prevKidFrame, originalLastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
-
- result = PR_FALSE;
- break;
- }
-
- // If the frame being reflowed is not appropriate (e.g. a block
- // frame) then we should stop! This can only happen when a
- // prev-in-flow has pushed some junk into this frame.
- const nsStyleDisplay* kidDisplay;
- kidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)kidDisplay);
- if ((NS_STYLE_DISPLAY_BLOCK == kidDisplay->mDisplay) ||
- (NS_STYLE_DISPLAY_LIST_ITEM == kidDisplay->mDisplay)) {
- if (mFirstChild != kidFrame) {
- PushChildren(kidFrame, prevKidFrame, originalLastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
- result = PR_FALSE;
- break;
- }
- }
-
- nsReflowMetrics kidSize(pKidMaxElementSize);
- nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize,
- eReflowReason_Resize);
- nsReflowStatus status;
-
- // Reflow the child into the available space
- PRBool room = CanFitChild(aPresContext, aState, kidFrame);
- if (room) {
- kidFrame->WillReflow(*aPresContext);
- status = ReflowChild(aState, kidFrame, aPresContext, kidSize, kidReflowState);
- }
-
- // Did the child fit?
- if (!room || !DidFitChild(aPresContext, aState, kidFrame, kidSize)) {
- // The child is too wide to fit in the available space, and it's
- // not our first child
-
- // Since we are giving the next-in-flow our last child, we
- // give it our original mLastContentIsComplete too (in case we
- // are pushing into an empty next-in-flow)
- PushChildren(kidFrame, prevKidFrame, originalLastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
-
- result = PR_FALSE;
- break;
- }
-
- // Place and size the child. We'll deal with vertical alignment when
- // we're all done
- PlaceChild(kidFrame, childCount, aState, kidSize, pKidMaxElementSize);
- childCount++;
-
- // Remember where we just were in case we end up pushing children
- prevKidFrame = kidFrame;
-
- // Is the child complete?
- mLastContentIsComplete = NS_FRAME_IS_COMPLETE(status);
- if (NS_FRAME_IS_NOT_COMPLETE(status)) {
- // No, the child isn't complete
- nsIFrame* kidNextInFlow;
-
- kidFrame->GetNextInFlow(kidNextInFlow);
- PRBool lastContentIsComplete = mLastContentIsComplete;
- if (nsnull == kidNextInFlow) {
- // The child doesn't have a next-in-flow so create a continuing
- // frame. This hooks the child into the flow
- nsIFrame* continuingFrame;
-
- nsIStyleContextPtr kidSC;
- kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
- kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
- continuingFrame);
- NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
-
- // Add the continuing frame to the sibling list
- nsIFrame* nextSib;
-
- kidFrame->GetNextSibling(nextSib);
- continuingFrame->SetNextSibling(nextSib);
- kidFrame->SetNextSibling(continuingFrame);
- if (nsnull == nextSib) {
- // Assume that the continuation frame we just created is
- // complete, for now. It will get reflowed by our
- // next-in-flow (we are going to push it now)
- lastContentIsComplete = PR_TRUE;
- }
- }
-
- // We've used up all of our available space so push the remaining
- // children to the next-in-flow
- nsIFrame* nextSibling;
-
- kidFrame->GetNextSibling(nextSibling);
- if (nsnull != nextSibling) {
- PushChildren(nextSibling, kidFrame, lastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
- }
- result = PR_FALSE;
- break;
- }
-
- // Get the next child frame
- kidFrame->GetNextSibling(kidFrame);
- }
-
- // Update the child count member data
- mChildCount = childCount;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- NS_POSTCONDITION(LengthOf(mFirstChild) == mChildCount, "bad child count");
-
- nsIFrame* lastChild;
- PRInt32 lastIndexInParent;
-
- LastChild(lastChild);
- lastChild->GetContentIndex(lastIndexInParent);
- NS_POSTCONDITION(lastIndexInParent == mLastContentOffset, "bad last content offset");
- VerifyLastIsComplete();
- }
-#endif
- return result;
-}
-
-/**
- * Try and pull-up frames from our next-in-flow
- *
- * @param aPresContext presentation context to use
- * @param aState current inline state
- * @return true if we successfully pulled-up all the children and false
- * otherwise, e.g. child didn't fit
- */
-PRBool nsInlineFrame::PullUpChildren(nsIPresContext* aPresContext,
- nsInlineState& aState)
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("enter nsInlineFrame::PullUpChildren: [%d,%d,%c] childCount=%d",
- mFirstContentOffset,
- mLastContentOffset,
- mLastContentIsComplete ? 'T' : 'F',
- mChildCount));
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
-
- nsInlineFrame* nextInFlow = (nsInlineFrame*)mNextInFlow;
- nsSize kidMaxElementSize;
- nsSize* pKidMaxElementSize = (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
-#ifdef NS_DEBUG
- PRInt32 kidIndex = NextChildOffset();
-#endif
- nsIFrame* prevKidFrame;
-
- LastChild(prevKidFrame);
-
- PRBool result = PR_TRUE;
-
- while (nsnull != nextInFlow) {
- nsReflowMetrics kidSize(pKidMaxElementSize);
- nsReflowStatus status;
-
- // Get the next child
- nsIFrame* kidFrame = nextInFlow->mFirstChild;
-
- // Any more child frames?
- if (nsnull == kidFrame) {
- // No. Any frames on its overflow list?
- if (nsnull != nextInFlow->mOverflowList) {
- // Move the overflow list to become the child list
- NS_ABORT();
- nextInFlow->AppendChildren(nextInFlow->mOverflowList);
- nextInFlow->mOverflowList = nsnull;
- kidFrame = nextInFlow->mFirstChild;
- } else {
- // We've pulled up all the children, so move to the next-in-flow.
- nextInFlow = (nsInlineFrame*)nextInFlow->mNextInFlow;
- continue;
- }
- }
-
- // It's time to stop pulling up if our last child wants a break
- if (NS_STYLE_CLEAR_NONE != aState.lineLayout->mPendingBreak) {
- result = PR_FALSE;
- break;
- }
-
- // If the frame being pulled up is not appropriate (e.g. a block
- // frame) then we should stop!
- const nsStyleDisplay* kidDisplay;
- kidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)kidDisplay);
- if ((NS_STYLE_DISPLAY_BLOCK == kidDisplay->mDisplay) ||
- (NS_STYLE_DISPLAY_LIST_ITEM == kidDisplay->mDisplay)) {
- result = PR_FALSE;
- break;
- }
-
- // If there is no room, stop pulling up
- if (!CanFitChild(aPresContext, aState, kidFrame)) {
- result = PR_FALSE;
- break;
- }
-
-// XXX inline reflow avoidance will be done by nsLineLayout
-#if XXX
- // See if the child fits in the available space. If it fits or
- // it's splittable then reflow it. The reason we can't just move
- // it is that we still need ascent/descent information
- nsSize kidFrameSize;
- nsSplittableType kidIsSplittable;
-
- kidFrame->GetSize(kidFrameSize);
- kidFrame->IsSplittable(kidIsSplittable);
- if ((kidFrameSize.width > aState.availSize.width) &&
- NS_FRAME_IS_NOT_SPLITTABLE(kidIsSplittable)) {
- result = PR_FALSE;
- break;
- }
-#endif
-
- nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize,
- eReflowReason_Resize);
- kidFrame->WillReflow(*aPresContext);
- status = ReflowChild(aState, kidFrame, aPresContext, kidSize, kidReflowState);
-
- // Did the child fit?
- if (!DidFitChild(aPresContext, aState, kidFrame, kidSize)) {
- // The child is too wide to fit in the available space, and it's
- // not our first child
- result = PR_FALSE;
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("nsInlineFrame::PullUpChildren: pulled frame=%p [%c][%x]",
- kidFrame,
- NS_FRAME_IS_COMPLETE(status) ? 'T' : 'F',
- status));
-
- // Place and size the child. We'll deal with vertical alignment when
- // we're all done
- PlaceChild(kidFrame, mChildCount, aState, kidSize, pKidMaxElementSize);
-
- // Remove the frame from its current parent
- kidFrame->GetNextSibling(nextInFlow->mFirstChild);
- nextInFlow->mChildCount--;
- // Update the next-in-flows first content offset
- if (nsnull != nextInFlow->mFirstChild) {
- nextInFlow->SetFirstContentOffset(nextInFlow->mFirstChild);
- }
-
- // Link the frame into our list of children
- kidFrame->SetGeometricParent(this);
- nsIFrame* kidContentParent;
-
- kidFrame->GetContentParent(kidContentParent);
- if (nextInFlow == kidContentParent) {
- kidFrame->SetContentParent(this);
- }
- if (nsnull == prevKidFrame) {
- mFirstChild = kidFrame;
- SetFirstContentOffset(kidFrame);
- } else {
- prevKidFrame->SetNextSibling(kidFrame);
- }
- kidFrame->SetNextSibling(nsnull);
- mChildCount++;
- prevKidFrame = kidFrame;
-
- // Is the child we just pulled up complete?
- mLastContentIsComplete = NS_FRAME_IS_COMPLETE(status);
- if (NS_FRAME_IS_NOT_COMPLETE(status)) {
- // No the child isn't complete
- nsIFrame* kidNextInFlow;
-
- kidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull == kidNextInFlow) {
- // The child doesn't have a next-in-flow so create a
- // continuing frame. The creation appends it to the flow and
- // prepares it for reflow.
- nsIFrame* continuingFrame;
-
- nsIStyleContextPtr kidSC;
- kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
- kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
- continuingFrame);
- NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
-
- // Add the continuing frame to our sibling list and then push
- // it to the next-in-flow. This ensures the next-in-flow's
- // content offsets and child count are set properly. Note that
- // we can safely assume that the continuation is complete so
- // we pass PR_TRUE into PushChidren in case our next-in-flow
- // was just drained and now needs to know it's
- // mLastContentIsComplete state.
- kidFrame->SetNextSibling(continuingFrame);
-
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("nsInlineFrame::PullUpChildren: pushing frame=%p",
- continuingFrame));
- PushChildren(continuingFrame, kidFrame, PR_TRUE);
-
- // After we push the continuation frame we don't need to fuss
- // with mLastContentIsComplete beause the continuation frame
- // is no longer on *our* list.
- }
-
- // If the child isn't complete then it means that we've used up
- // all of our available space.
- result = PR_FALSE;
- break;
- }
- }
-
- // Update our last content offset
- if (nsnull != prevKidFrame) {
- NS_ASSERTION(IsLastChild(prevKidFrame), "bad last child");
- SetLastContentOffset(prevKidFrame);
- }
-
- // We need to make sure the first content offset is correct for any empty
- // next-in-flow frames (frames where we pulled up all the child frames)
- nextInFlow = (nsInlineFrame*)mNextInFlow;
- if ((nsnull != nextInFlow) && (nsnull == nextInFlow->mFirstChild)) {
- // We have at least one empty frame. Did we succesfully pull up all the
- // child frames?
- if (PR_FALSE == result) {
- // No, so we need to adjust the first content offset of all the empty
- // frames
- AdjustOffsetOfEmptyNextInFlows();
-#ifdef NS_DEBUG
- } else {
- // Yes, we successfully pulled up all the child frames which means all
- // the next-in-flows must be empty. Do a sanity check
- if (GetVerifyTreeEnable()) {
- while (nsnull != nextInFlow) {
- NS_ASSERTION(nsnull == nextInFlow->mFirstChild,
- "non-empty next-in-flow");
- nextInFlow = (nsInlineFrame*)nextInFlow->mNextInFlow;
- }
- }
-#endif
- }
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("exit nsInlineFrame::PullUpChildren: [%d,%d,%c] childCount=%d",
- mFirstContentOffset,
- mLastContentOffset,
- mLastContentIsComplete ? 'T' : 'F',
- mChildCount));
- return result;
-}
-
-/**
- * Create new frames for content we haven't yet mapped
- *
- * @param aPresContext presentation context to use
- * @param aState current inline state
- * @return NS_FRAME_COMPLETE if all content has been mapped and 0 if we
- * should be continued
- */
-nsReflowStatus
-nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
- nsInlineState& aState)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
- nsIFrame* kidPrevInFlow = nsnull;
- nsReflowStatus result = NS_FRAME_NOT_COMPLETE;
-
- // If we have no children and we have a prev-in-flow then we need to pick
- // up where it left off. If we have children, e.g. we're being resized, then
- // our content offset should already be set correctly...
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsInlineFrame* prev = (nsInlineFrame*)mPrevInFlow;
- NS_ASSERTION(prev->mLastContentOffset >= prev->mFirstContentOffset,
- "bad prevInFlow");
-
- mFirstContentOffset = prev->NextChildOffset();
- if (!prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
- mLastContentIsComplete = PR_TRUE;
-
- // Place our children, one at a time until we are out of children
- nsSize kidMaxElementSize;
- nsSize* pKidMaxElementSize =
- (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
- PRInt32 kidIndex = NextChildOffset();
- nsIFrame* prevKidFrame;
-
- PRBool breakAfter = PR_FALSE;
- LastChild(prevKidFrame);
- for (;;) {
- // Get the next content object
- nsIContentPtr kid = mContent->ChildAt(kidIndex);
- if (kid.IsNull()) {
- result = NS_FRAME_COMPLETE;
- break;
- }
-
- // It's time to stop pulling up if our previous child wants a line
- // break
- if (NS_STYLE_CLEAR_NONE != aState.lineLayout->mPendingBreak) {
- break;
- }
-
- // Make sure we still have room left
- if (!CanFitChild(aPresContext, aState, nsnull)) {
- // Note: return status was set to 0 above...
- break;
- }
-
- // Resolve style for the child
- nsIStyleContextPtr kidStyleContext =
- aPresContext->ResolveStyleContextFor(kid, this);
-
- // Figure out how we should treat the child
- nsIFrame* kidFrame;
- const nsStyleDisplay* kidDisplay =
- (const nsStyleDisplay*)kidStyleContext->GetStyleData(eStyleStruct_Display);
- const nsStylePosition* kidPosition = (const nsStylePosition*)
- kidStyleContext->GetStyleData(eStyleStruct_Position);
-
- // Check whether it wants to floated or absolutely positioned
- nsresult rv;
- if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) {
- rv = nsAbsoluteFrame::NewFrame(&kidFrame, kid, this);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(aPresContext, kidStyleContext);
- }
- } else if (kidDisplay->mFloats != NS_STYLE_FLOAT_NONE) {
- rv = nsPlaceholderFrame::NewFrame(&kidFrame, kid, this);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(aPresContext, kidStyleContext);
- }
- } else if (nsnull == kidPrevInFlow) {
- nsIContentDelegatePtr kidDel;
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- if (kidIndex != mFirstContentOffset) {
- // We don't allow block elements to be placed in us anywhere
- // other than at our left margin.
- goto done;
- }
- // FALLTHROUGH
-
- case NS_STYLE_DISPLAY_INLINE:
- kidDel = kid->GetDelegate(aPresContext);
- rv = kidDel->CreateFrame(aPresContext, kid, this,
- kidStyleContext, kidFrame);
- break;
-
- default:
- NS_ASSERTION(nsnull == kidPrevInFlow, "bad prev in flow");
- rv = nsFrame::NewFrame(&kidFrame, kid, this);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(aPresContext, kidStyleContext);
- }
- break;
- }
- } else {
- rv = kidPrevInFlow->CreateContinuingFrame(aPresContext, this,
- kidStyleContext, kidFrame);
- }
-
- // Try to reflow the child into the available space. It might not
- // fit or might need continuing.
- nsReflowMetrics kidSize(pKidMaxElementSize);
- nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize,
- eReflowReason_Resize);
- kidFrame->WillReflow(*aPresContext);
- nsReflowStatus status = ReflowChild(aState, kidFrame, aPresContext, kidSize,
- kidReflowState);
-
- // Did the child fit?
- if (!DidFitChild(aPresContext, aState, kidFrame, kidSize)) {
- // The child is too wide to fit in the available space, and it's
- // not our first child. Add the frame to our overflow list
- NS_ASSERTION(nsnull == mOverflowList, "bad overflow list");
- mOverflowList = kidFrame;
- prevKidFrame->SetNextSibling(nsnull);
- break;
- }
-
- // Place and size the child. We'll deal with vertical alignment when
- // we're all done
- PlaceChild(kidFrame, mChildCount, aState, kidSize, pKidMaxElementSize);
-
- // Link child frame into the list of children
- if (nsnull != prevKidFrame) {
- prevKidFrame->SetNextSibling(kidFrame);
- } else {
- mFirstChild = kidFrame; // our first child
- SetFirstContentOffset(kidFrame);
- }
- prevKidFrame = kidFrame;
- mChildCount++;
- kidIndex++;
-
- // Did the child complete?
- if (NS_FRAME_IS_NOT_COMPLETE(status)) {
- // If the child isn't complete then it means that we've used up
- // all of our available space
- mLastContentIsComplete = PR_FALSE;
- break;
- }
- kidPrevInFlow = nsnull;
-
- // If we need to break after the kidFrame, then do so now
- if (breakAfter) {
- break;
- }
- }
-
-done:;
- // Update the content mapping
- NS_ASSERTION(IsLastChild(prevKidFrame), "bad last child");
- SetLastContentOffset(prevKidFrame);
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(len == mChildCount, "bad child count");
- VerifyLastIsComplete();
- }
-#endif
- return result;
-}
-
-void
-nsInlineFrame::InitializeState(nsIPresContext* aPresContext,
- const nsReflowState& aReflowState,
- nsInlineState& aState)
-{
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState, aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- // When we are given a width, change the reflow behavior to
- // unconstrained.
- aState.unconstrainedWidth = PR_TRUE;
- aState.availSize.width = NS_UNCONSTRAINEDSIZE;
- }
-}
-
-NS_METHOD nsInlineFrame::Reflow(nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("enter nsInlineFrame::Reflow: this=%p: childCount=%d",
- this, mChildCount));
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- PreReflowCheck();
- }
-#endif
-
- if (eReflowReason_Initial == aReflowState.reason) {
- nsresult rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
-
- PRBool reflowMappedOK = PR_TRUE;
-
- aStatus = NS_FRAME_COMPLETE; // initialize out parameter
-
- // Get the style molecule
- const nsStyleFont* styleFont = (const nsStyleFont*)
- mStyleContext->GetStyleData(eStyleStruct_Font);
- const nsStyleSpacing* styleSpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStyleText* styleText = (const nsStyleText*)
- mStyleContext->GetStyleData(eStyleStruct_Text);
-
- // Check for an overflow list
- if (eReflowReason_Incremental != aReflowState.reason) {
- MoveOverflowToChildList();
- }
-
- // Initialize our reflow state. We must wait until after we've processed
- // the overflow list, because our first content offset might change
- nsMargin borderPadding;
- styleSpacing->CalcBorderPaddingFor(this, borderPadding);
- nsInlineState state(aPresContext, this, styleFont, borderPadding,
- aReflowState, aDesiredSize.maxElementSize);
- InitializeState(aPresContext, aReflowState, state);
- state.SetNumAscents(mContent->ChildCount() - mFirstContentOffset);
- state.mNoWrap = NS_STYLE_WHITESPACE_NORMAL != styleText->mWhiteSpace;
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- NS_ASSERTION(nsnull != aReflowState.reflowCommand, "null reflow command");
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
-
- if (target == this) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- switch (type) {
- case nsIReflowCommand::FrameAppended:
- // Recover our state
- RecoverState(aPresContext, state, nsnull);
- aStatus = ReflowUnmappedChildren(aPresContext, state);
- break;
-
- default:
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- break;
- }
-
- } else {
- // The command is passing through us. Get the next frame in the reflow chain
- nsIFrame* kidFrame;
- aReflowState.reflowCommand->GetNext(kidFrame);
-
- nsReflowMetrics kidSize(aDesiredSize.maxElementSize);
- nsReflowState kidReflowState(kidFrame, aReflowState, state.availSize);
-
- // Restore our state as if nextFrame is the next frame to reflow
- PRInt32 kidIndex = RecoverState(aPresContext, state, kidFrame);
-
- // Reflow the child into the available space
- kidFrame->WillReflow(*aPresContext);
- aStatus = ReflowChild(state, kidFrame, aPresContext, kidSize, kidReflowState);
-
- // Did the child fit?
- if (!DidFitChild(aPresContext, state, kidFrame, kidSize)) {
- nsIFrame* prevFrame;
-
- // The child is too wide to fit in the available space, and
- // it's not our first child
- PrevChild(kidFrame, prevFrame);
- PushChildren(kidFrame, prevFrame, mLastContentIsComplete);
- SetLastContentOffset(prevFrame);
- mChildCount = kidIndex - 1;
- aStatus = NS_FRAME_NOT_COMPLETE;
-
- } else {
- // Place and size the child
- PlaceChild(kidFrame, kidIndex, state, kidSize, nsnull);
-
- nsIFrame* kidNextInFlow;
- kidFrame->GetNextInFlow(kidNextInFlow);
-
- // Is the child complete?
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- // Check whether the frame has next-in-flow(s) that are no longer needed
- if (nsnull != kidNextInFlow) {
- // Remove the next-in-flow(s)
- DeleteChildsNextInFlow(kidFrame);
- }
-
- // Adjust the frames that follow
- aStatus = IncrementalReflowAfter(aPresContext, state, kidFrame, kidIndex);
-
- } else {
- nsIFrame* nextSibling;
-
- // No, the child isn't complete
- if (nsnull == kidNextInFlow) {
- // The child doesn't have a next-in-flow so create a continuing
- // frame.
- nsIFrame* continuingFrame;
-
- nsIStyleContextPtr kidSC;
- kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
- kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame);
-
- // Link the child into the sibling list
- kidFrame->GetNextSibling(nextSibling);
- continuingFrame->SetNextSibling(nextSibling);
- kidFrame->SetNextSibling(continuingFrame);
- }
-
- // We've used up all of our available space, so push the remaining
- // children to the next-in-flow
- kidFrame->GetNextSibling(nextSibling);
- if (nsnull != nextSibling) {
- PushChildren(nextSibling, kidFrame, mLastContentIsComplete);
- }
-
- SetLastContentOffset(kidFrame);
- mChildCount = kidIndex;
- }
- }
- }
-
- } else {
- // Reflow any existing frames
- if (nsnull != mFirstChild) {
- reflowMappedOK = ReflowMappedChildrenFrom(aPresContext, state, mFirstChild, 0);
-
- if (PR_FALSE == reflowMappedOK) {
- // We didn't successfully reflow our mapped frames; therefore, we're not complete
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
- }
-
- // Did we successfully relow our mapped children?
- if (PR_TRUE == reflowMappedOK) {
-#if XXX
- // Any space left?
- if (state.availSize.width <= 0) {
- // No space left. Don't try to pull-up children or reflow unmapped
- if (NextChildOffset() < mContent->ChildCount()) {
- // No room left to map the remaining content; therefore, we're not complete
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
- } else
-#endif
- if (NextChildOffset() < mContent->ChildCount()) {
- // Try and pull-up some children from a next-in-flow
- if (PullUpChildren(aPresContext, state)) {
- // If we still have unmapped children then create some new frames
- if (NextChildOffset() < mContent->ChildCount()) {
- aStatus = ReflowUnmappedChildren(aPresContext, state);
- }
- } else {
- // We were unable to pull-up all the existing frames from the next in flow;
- // therefore, we're not complete
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
- }
- }
-
- #if 0
- // XXX I don't think our return size properly accounts for the lineHeight
- // (which may not == state.maxAscent + state.maxDescent)
- // Return our size and our status
- #endif
- }
-
- // Vertically align the children
- nscoord lineHeight =
- nsCSSLayout::VerticallyAlignChildren(aPresContext, this, styleFont,
- borderPadding.top,
- mFirstChild, mChildCount,
- state.ascents, state.maxAscent);
-
- ComputeFinalSize(aPresContext, state, aDesiredSize);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("exit nsInlineFrame::Reflow: this=%p: childCount=%d status=%scomplete",
- this, mChildCount,
- NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not "));
- return NS_OK;
-}
-
-void
-nsInlineFrame::ComputeFinalSize(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsReflowMetrics& aDesiredSize)
-{
- // Compute default size
- aDesiredSize.width = aState.x + aState.borderPadding.right;
- aDesiredSize.ascent = aState.borderPadding.top + aState.maxAscent;
- aDesiredSize.descent = aState.maxDescent + aState.borderPadding.bottom;
- aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
-
- // Apply width/height style properties
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aDesiredSize.width = aState.borderPadding.left + aState.mStyleSize.width +
- aState.borderPadding.right;
- }
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredSize.height = aState.borderPadding.top + aState.mStyleSize.height +
- aState.borderPadding.bottom;
- }
-
- if ((nsnull != aDesiredSize.maxElementSize) && aState.mNoWrap) {
- aDesiredSize.maxElementSize->width = aDesiredSize.width;
- aDesiredSize.maxElementSize->height = aDesiredSize.height;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-PRIntn nsInlineFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_LEFT;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_RIGHT;
- }
- return skip;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-// Incremental reflow support
-
-NS_METHOD nsInlineFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nscoord maxAscent = 0;
- nscoord maxDescent = 0;
- nsIFrame* kid = mFirstChild;
- while (nsnull != kid) {
- // XXX Properly handle max element size...
- nsReflowMetrics kidMetrics(aMetrics.maxElementSize);
- kid->GetReflowMetrics(aPresContext, kidMetrics);
- if (kidMetrics.ascent > maxAscent) maxAscent = kidMetrics.ascent;
- if (kidMetrics.descent > maxDescent) maxDescent = kidMetrics.descent;
- kid->GetNextSibling(kid);
- }
-
- // XXX what about border & padding
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = maxAscent;
- aMetrics.descent = maxDescent;
-
- return NS_OK;
-}
-
-/**
- * Setup aState to the state it would have had we just reflowed our
- * children up to, but not including, aSkipChild. Return the index
- * of aSkipChild in our list of children.
- * If aSkipChild is nsnull then resets the state for appended content.
- */
-PRInt32 nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aSkipChild)
-{
- // Get ascent & descent info for all the children up to but not
- // including aSkipChild. Also compute the x coordinate for where
- // aSkipChild will be place after it is reflowed.
- PRInt32 i = 0;
- nsIFrame* kid = mFirstChild;
- nscoord x = aState.x;
- nscoord maxAscent = 0;
- nscoord maxDescent = 0;
- while ((nsnull != kid) && (kid != aSkipChild)) {
- nsReflowMetrics kidMetrics(nsnull);
- kid->GetReflowMetrics(aPresContext, kidMetrics);
- aState.ascents[i] = kidMetrics.ascent;
- if (kidMetrics.ascent > maxAscent) maxAscent = kidMetrics.ascent;
- if (kidMetrics.descent > maxDescent) maxDescent = kidMetrics.descent;
-
- // XXX Factor in left and right margins
- x += kidMetrics.width;
-
- kid->GetNextSibling(kid);
- i++;
- }
- aState.maxAscent = maxAscent;
- aState.maxDescent = maxDescent;
- aState.x = x;
- return i;
-}
-
-// XXX We need to return information about whether our next-in-flow is
-// dirty...
-nsReflowStatus
-nsInlineFrame::IncrementalReflowFrom(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex)
-{
- nsReflowStatus status = NS_FRAME_COMPLETE;
-
- // Just reflow all the mapped children starting with childFrame.
- // XXX This isn't the optimal thing to do...
- if (ReflowMappedChildrenFrom(aPresContext, aState, aChildFrame, aChildIndex)) {
- if (NextChildOffset() < mContent->ChildCount()) {
-#if XXX
- // Any space left?
- if (aState.availSize.width <= 0) {
- // No space left. Don't try to pull-up children
- status = NS_FRAME_NOT_COMPLETE;
- } else
-#endif
- {
- // Try and pull-up some children from a next-in-flow
- if (!PullUpChildren(aPresContext, aState)) {
- // We were not able to pull-up all the child frames from our
- // next-in-flow
- status = NS_FRAME_NOT_COMPLETE;
- }
- }
- }
- } else {
- // We were unable to reflow all our mapped frames
- status = NS_FRAME_NOT_COMPLETE;
- }
-
- return status;
-}
-
-nsReflowStatus
-nsInlineFrame::IncrementalReflowAfter(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex)
-{
- nsReflowStatus status = NS_FRAME_COMPLETE;
- nsIFrame* nextFrame;
-
- aChildFrame->GetNextSibling(nextFrame);
-
- // Just reflow all the remaining mapped children
- // XXX This isn't the optimal thing to do...
- if ((nsnull == nextFrame) ||
- ReflowMappedChildrenFrom(aPresContext, aState, nextFrame, aChildIndex + 1)) {
- if (NextChildOffset() < mContent->ChildCount()) {
-#if XXX
- // Any space left?
- if (aState.availSize.width <= 0) {
- // No space left. Don't try to pull-up children
- status = NS_FRAME_NOT_COMPLETE;
- } else
-#endif
- {
- // Try and pull-up some children from a next-in-flow
- if (!PullUpChildren(aPresContext, aState)) {
- // We were not able to pull-up all the child frames from our
- // next-in-flow
- status = NS_FRAME_NOT_COMPLETE;
- }
- }
- }
- } else {
- // We were unable to reflow all our mapped frames
- status = NS_FRAME_NOT_COMPLETE;
- }
-
- return status;
-}
-
-// In order to execute the vertical alignment code after incremental
-// reflow of the inline frame, we need to reposition any child frames
-// that were relatively positioned back to their computed x origin.
-// This should probably be done as a pre-alignment computation (and it
-// can be avoided if there are no relatively positioned children).
diff --git a/mozilla/layout/generic/nsLeafFrame.cpp b/mozilla/layout/generic/nsLeafFrame.cpp
index cb98d4125ea..601c890906d 100644
--- a/mozilla/layout/generic/nsLeafFrame.cpp
+++ b/mozilla/layout/generic/nsLeafFrame.cpp
@@ -60,6 +60,7 @@ NS_METHOD nsLeafFrame::Reflow(nsIPresContext* aPresContext,
// XXX add in code to check for width/height being set via css
// and if set use them instead of calling GetDesiredSize.
+
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
AddBordersAndPadding(aPresContext, aDesiredSize);
if (nsnull != aDesiredSize.maxElementSize) {
diff --git a/mozilla/layout/generic/nsLineLayout.cpp b/mozilla/layout/generic/nsLineLayout.cpp
deleted file mode 100644
index 1b651ec97b3..00000000000
--- a/mozilla/layout/generic/nsLineLayout.cpp
+++ /dev/null
@@ -1,1695 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsLineLayout.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsBlockFrame.h"
-#include "nsIContent.h"
-#include "nsIContentDelegate.h"
-#include "nsIPresContext.h"
-#include "nsISpaceManager.h"
-#include "nsIPtr.h"
-#include "nsAbsoluteFrame.h"
-#include "nsPlaceholderFrame.h"
-#include "nsCSSLayout.h"
-#include "nsCRT.h"
-#include "nsIReflowCommand.h"
-#include "nsIFontMetrics.h"
-#include "nsHTMLBase.h"
-#include "nsScrollFrame.h"
-
-#undef NOISY_REFLOW
-
-// XXX zap mAscentNum
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-nsLineData::nsLineData()
-{
- mNextLine = nsnull;
- mPrevLine = nsnull;
- mFirstChild = nsnull;
- mChildCount = 0;
- mFirstContentOffset = 0;
- mLastContentOffset = 0;
- mLastContentIsComplete = PR_TRUE;
- mIsBlock = PR_FALSE;
- mBounds.SetRect(0, 0, 0, 0);
- mFloaters = nsnull;
-}
-
-nsLineData::~nsLineData()
-{
- delete mFloaters;
-}
-
-void
-nsLineData::UnlinkLine()
-{
- nsLineData* prevLine = mPrevLine;
- nsLineData* nextLine = mNextLine;
- if (nsnull != nextLine) nextLine->mPrevLine = prevLine;
- if (nsnull != prevLine) prevLine->mNextLine = nextLine;
-}
-
-nsresult
-nsLineData::Verify(PRBool aFinalCheck) const
-{
- NS_ASSERTION(mNextLine != this, "bad line linkage");
- NS_ASSERTION(mPrevLine != this, "bad line linkage");
- if (nsnull != mPrevLine) {
- NS_ASSERTION(mPrevLine->mNextLine == this, "bad line linkage");
- }
- if (nsnull != mNextLine) {
- NS_ASSERTION(mNextLine->mPrevLine == this, "bad line linkage");
- }
-
- if (aFinalCheck) {
- NS_ASSERTION(0 != mChildCount, "empty line");
- NS_ASSERTION(nsnull != mFirstChild, "empty line");
-
- nsIFrame* nextLinesFirstChild = nsnull;
- if (nsnull != mNextLine) {
- nextLinesFirstChild = mNextLine->mFirstChild;
- }
-
- // Check that number of children are ok and that the index in parent
- // information agrees with the content offsets.
- PRInt32 offset = mFirstContentOffset;
- PRInt32 len = 0;
- nsIFrame* child = mFirstChild;
- while ((nsnull != child) && (child != nextLinesFirstChild)) {
- PRInt32 indexInParent;
- child->GetContentIndex(indexInParent);
- NS_ASSERTION(indexInParent == offset, "bad line offsets");
- len++;
- if (len != mChildCount) {
- offset++;
- }
- child->GetNextSibling(child);
- }
- NS_ASSERTION(offset == mLastContentOffset, "bad mLastContentOffset");
- NS_ASSERTION(len == mChildCount, "bad child count");
- }
-
- if (1 == mChildCount) {
- if (mIsBlock) {
- nsIFrame* child = mFirstChild;
- const nsStyleDisplay* display;
- child->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- NS_ASSERTION((NS_STYLE_DISPLAY_BLOCK == display->mDisplay) ||
- (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay),
- "bad mIsBlock state");
- }
- }
-
- // XXX verify content offsets and mLastContentIsComplete
- return NS_OK;
-}
-
-nsIFrame*
-nsLineData::GetLastChild()
-{
- nsIFrame* lastChild = mFirstChild;
- if (mChildCount > 1) {
- for (PRInt32 numKids = mChildCount - 1; --numKids >= 0; ) {
- nsIFrame* nextChild;
- lastChild->GetNextSibling(nextChild);
- lastChild = nextChild;
- }
- }
- return lastChild;
-}
-
-PRIntn
-nsLineData::GetLineNumber() const
-{
- PRIntn lineNumber = 0;
- nsLineData* prev = mPrevLine;
- while (nsnull != prev) {
- lineNumber++;
- prev = prev->mPrevLine;
- }
- return lineNumber;
-}
-
-void
-nsLineData::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the first/last content offset
- fprintf(out, "line %d [%d,%d,%c] ",
- GetLineNumber(),
- mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
-
- // Output the bounds rect
- out << mBounds;
-
- // Output the children, one line at a time
- if (nsnull != mFirstChild) {
- fputs("<\n", out);
- aIndent++;
-
- nsIFrame* child = mFirstChild;
- for (PRInt32 numKids = mChildCount; --numKids >= 0; ) {
- child->List(out, aIndent);
- child->GetNextSibling(child);
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- fputs("<>\n", out);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineLayout::nsLineLayout(nsBlockReflowState& aState)
- : mBlockReflowState(aState)
-{
- mBlock = aState.mBlock;
- mSpaceManager = aState.mSpaceManager;
- mBlock->GetContent(mBlockContent);
- mPresContext = aState.mPresContext;
- mUnconstrainedWidth = aState.mUnconstrainedWidth;
- mUnconstrainedHeight = aState.mUnconstrainedHeight;
- mMaxElementSizePointer = aState.mMaxElementSizePointer;
-
- mAscents = mAscentBuf;
- mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
-}
-
-nsLineLayout::~nsLineLayout()
-{
- NS_IF_RELEASE(mBlockContent);
- if (mAscents != mAscentBuf) {
- delete [] mAscents;
- }
-}
-
-nsresult
-nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- SetReflowSpace(aState.mCurrentBand.availSpace);
-
- mState.mSkipLeadingWhiteSpace = PR_TRUE;
- mState.mColumn = 0;
-
- mState.mKidFrame = nsnull;
- mState.mPrevKidFrame = nsnull;
- mState.mKidIndex = aLine->mFirstContentOffset;
- mState.mKidFrameNum = 0;
- mState.mMaxElementSize.width = 0;
- mState.mMaxElementSize.height = 0;
- mState.mMaxAscent = nsnull;
- mState.mMaxDescent = nsnull;
-
- mSavedState.mKidFrame = nsnull;
- mBreakFrame = nsnull;
- mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- mLine = aLine;
- mKidPrevInFlow = nsnull;
- mNewFrames = 0;
- mFramesReflowed = 0;
-
- mMarginApplied = PR_FALSE;
-
- mMustReflowMappedChildren = PR_FALSE;
- mY = aState.mY;
- mMaxHeight = aState.mAvailSize.height;
- mReflowDataChanged = PR_FALSE;
-
- mLineHeight = 0;
-
- mNoWrap = PR_FALSE;
- const nsStyleText* styleText;
- mBlock->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)styleText);
- switch (styleText->mWhiteSpace) {
- case NS_STYLE_WHITESPACE_PRE:
- case NS_STYLE_WHITESPACE_NOWRAP:
- mNoWrap = PR_TRUE;
- break;
- }
-
- return rv;
-}
-
-void
-nsLineLayout::SetReflowSpace(nsRect& aAvailableSpaceRect)
-{
- nscoord x0 = aAvailableSpaceRect.x;
- mLeftEdge = x0;
- mState.mX = x0;
- mRightEdge = x0 + aAvailableSpaceRect.width;
-
- mMaxWidth = mRightEdge - x0;
- mReflowDataChanged = PR_TRUE;
- mMustReflowMappedChildren = PR_TRUE;
-}
-
-nsresult
-nsLineLayout::SetAscent(nscoord aAscent)
-{
- PRInt32 kidFrameNum = mState.mKidFrameNum;
- if (kidFrameNum == mMaxAscents) {
- mMaxAscents *= 2;
- nscoord* newAscents = new nscoord[mMaxAscents];
- if (nsnull != newAscents) {
- nsCRT::memcpy(newAscents, mAscents, sizeof(nscoord) * kidFrameNum);
- if (mAscents != mAscentBuf) {
- delete [] mAscents;
- }
- mAscents = newAscents;
- } else {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- }
- mAscents[kidFrameNum] = aAscent;
- return NS_OK;
-}
-
-void
-nsLineLayout::AtSpace()
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::AtSpace: kidFrame=%p kidIndex=%d mX=%d",
- mState.mKidFrame, mState.mKidIndex, mState.mX));
- mBreakFrame = nsnull;
- mSavedState.mKidFrame = nsnull;
-}
-
-void
-nsLineLayout::AtWordStart(nsIFrame* aFrame, nscoord aX)
-{
- if (nsnull == mBreakFrame) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::AtWordStart: aFrame=%p kidFrame=%p[%d] aX=%d mX=%d",
- aFrame,
- mState.mKidFrame, mState.mKidIndex,
- aX, mState.mX));
-
- mSavedState = mState;
- mBreakFrame = aFrame;
- mBreakX = aX;
- }
- else if (mBreakFrame == aFrame) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::AtWordStart: update aX=%d", aX));
- NS_ASSERTION((mSavedState.mKidFrame == mState.mKidFrame) &&
- (mSavedState.mKidIndex == mState.mKidIndex) &&
- (mSavedState.mKidFrameNum == mState.mKidFrameNum),
- "bad break state");
- mBreakX = aX;
- }
-}
-
-PRBool
-nsLineLayout::CanBreak()
-{
- if (nsnull == mBreakFrame) {
- // There is no word to break at
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::CanBreak: no break frame"));
- return PR_FALSE;
- }
-
- if (mSavedState.mKidFrame == mLine->mFirstChild) {
- // The line's first frame contains the break position; we are not
- // allowed to break if the break would empty the line.
- if (0 == mBreakX) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::CanBreak: breakX=0"));
- return PR_FALSE;
- }
- }
-
- // Compute the break x coordinate in our coordinate system by adding
- // in the X coordinates of each of the frames between the break
- // frame and the containing block frame.
- nscoord breakX = mBreakX;
- nsIFrame* frame = mBreakFrame;
- for (;;) {
- nsRect r;
- frame->GetRect(r);
- breakX += r.x;
- nsIFrame* parent;
- frame->GetGeometricParent(parent);
- if (parent == mBlock) {
- break;
- }
- frame = parent;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::CanBreak: backup from=%p[%d]/%d to=%p[%d]/%d breakX=%d",
- mState.mKidFrame, mState.mKidIndex, mState.mKidFrameNum,
- mSavedState.mKidFrame, mSavedState.mKidIndex, mSavedState.mKidFrameNum,
- breakX));
-
- // Revert the line layout back to where it was when the break point
- // was found.
- mState = mSavedState;
-
- // Change the right edge to the breakX so that when we reflow the
- // child it will stop just before the break point.
- mRightEdge = breakX;
-
- // Forgot word break
- mSavedState.mKidFrame = nsnull;
- mBreakFrame = nsnull;
-
- return PR_TRUE;
-}
-
-/**
- * Attempt to avoid reflowing a child by seeing if it's been touched
- * since the last time it was reflowed.
- */
-nsresult
-nsLineLayout::ReflowMappedChild()
-{
- nsIFrame* kidFrame = mState.mKidFrame;
-
- if (mMustReflowMappedChildren || PR_TRUE) {
-/*
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: must reflow frame=%p[%d]",
- kidFrame, mKidIndex));
-*/
- return ReflowChild(nsnull, PR_FALSE);
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: attempt frame=%p[%d]",
- kidFrame, mState.mKidIndex));
-
- // If the child is a container then we need to reflow it if there is
- // a change in width. Note that if it's an empty container then it
- // doesn't really matter how much space we give it.
- if (mBlockReflowState.mDeltaWidth != 0) {
- nsIFrame* f;
- kidFrame->FirstChild(f);
- if (nsnull != f) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: has children"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-
- // If we need the max-element size and we are splittable then we
- // have to reflow to get it.
- nsSplittableType splits;
- kidFrame->IsSplittable(splits);
-#if 0
- if (nsnull != mMaxElementSizePointer) {
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: need max-element-size"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-#else
- // XXX For now, if the child is splittable we reflow it. The reason
- // is that the text whitespace compression needs to be consulted
- // here to properly handle reflow avoidance. To do that properly we
- // really need a first-rate protocol here (WillPlace?
- // CanAvoidReflow?) that gets the frame involved.
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: splittable hack"));
- return ReflowChild(nsnull, PR_FALSE);
- }
-#endif
-
- nsFrameState state;
- kidFrame->GetFrameState(state);
-
- // XXX a better term for this is "dirty" and once we add a dirty
- // bit that's what we'll do here.
-
- // XXX this check will cause pass2 of table reflow to reflow
- // everything; tables will be even faster if we have a dirty bit
- // instead (that way we can avoid reflowing non-splittables on
- // pass2)
- if (0 != (state & NS_FRAME_IN_REFLOW)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: frame is dirty"));
- return ReflowChild(nsnull, PR_FALSE);
- }
-
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- // XXX a next-in-flow propogated dirty-bit eliminates this code
-
- // The splittable frame has not yet been reflowed. This means
- // that, in theory, its state is well defined. However, if it has
- // a prev-in-flow and that frame has been touched then we need to
- // reflow this frame.
- nsIFrame* prevInFlow;
- kidFrame->GetPrevInFlow(prevInFlow);
- if (nsnull != prevInFlow) {
- nsFrameState prevState;
- prevInFlow->GetFrameState(prevState);
- if (0 != (prevState & NS_FRAME_IN_REFLOW)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: prev-in-flow frame is dirty"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-
- // If the child has a next-in-flow then never-mind, we need to
- // reflow it in case it has more/less space to reflow into.
- nsIFrame* nextInFlow;
- kidFrame->GetNextInFlow(nextInFlow);
- if (nsnull != nextInFlow) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: frame has next-in-flow"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-
- // Success! We have (so far) avoided reflowing the child. However,
- // we do need to place it and advance our position state. Get the
- // size of the child and its reflow metrics for placing.
- nsIStyleContextPtr kidSC;
- nsresult rv = kidFrame->GetStyleContext(mPresContext, kidSC.AssignRef());
- if (NS_OK != rv) {
- return rv;
- }
- const nsStyleDisplay* kidDisplay = (const nsStyleDisplay*)
- kidSC->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
- // XXX If it floats it needs to go through the normal path so that
- // PlaceFloater is invoked.
- return ReflowChild(nsnull, PR_FALSE);
- }
- const nsStyleSpacing* kidSpacing = (const nsStyleSpacing*)
- kidSC->GetStyleData(eStyleStruct_Spacing);
- PRBool isBlock = PR_FALSE;
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- if (kidFrame != mLine->mFirstChild) {
- // Block items must be at the start of a line, therefore we need
- // to break before the block item.
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: block requires break-before"));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- isBlock = PR_TRUE;
- break;
- }
-
- // Compute new total width of child using its current margin values
- // (they may have changed since the last time the child was reflowed)
- nsRect kidRect;
- kidFrame->GetRect(kidRect);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kidFrame, kidMargin);
- nscoord totalWidth;
- totalWidth = kidMargin.left + kidMargin.right + kidRect.width;
-
- // If the child intersects the area affected by the reflow then
- // we need to reflow it.
- nscoord x = mState.mX;
- if (x + kidMargin.left + kidRect.width > mRightEdge) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: failed edge test"));
- // XXX if !splittable then return NS_LINE_LAYOUT_BREAK_BEFORE
- return ReflowChild(nsnull, PR_FALSE);
- }
-
- // Make sure the child will fit. The child always fits if it's the
- // first child on the line.
- nscoord availWidth = mRightEdge - x;
- if (mUnconstrainedWidth ||
- (kidFrame == mLine->mFirstChild) ||
- (totalWidth <= availWidth)) {
- // By convention, mReflowResult is set during ResizeReflow,
- // IncrementalReflow AND GetReflowMetrics by those frames that are
- // line layout aware.
- mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
- nsReflowMetrics kidMetrics(nsnull);
- kidFrame->GetReflowMetrics(mPresContext, kidMetrics);
-
- nsSize maxElementSize;
- nsSize* kidMaxElementSize = nsnull;
- if (nsnull != mMaxElementSizePointer) {
- kidMaxElementSize = &maxElementSize;
- maxElementSize.width = kidRect.width;
- maxElementSize.height = kidRect.height;
- }
- kidRect.x = x + kidMargin.left;
- kidRect.y = mY;
-
- if (NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE == mReflowResult) {
- mState.mSkipLeadingWhiteSpace = PR_FALSE;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: fit size=%d,%d",
- kidRect.width, kidRect.height));
- mLine->mIsBlock = isBlock;
- return PlaceChild(kidRect, kidMetrics, kidMaxElementSize, kidMargin,
- NS_FRAME_COMPLETE);
- }
-
- // The child doesn't fit as is; if it's splittable then reflow it
- // otherwise return break-before status so that the non-splittable
- // child is pushed to the next line.
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: can't directly fit"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- return NS_LINE_LAYOUT_BREAK_BEFORE;
-}
-
-// Return values: <0 for error
-// 0 == NS_LINE_LAYOUT
-nsresult
-nsLineLayout::ReflowChild(nsIReflowCommand* aReflowCommand,
- PRBool aNewChild)
-{
- nsIFrame* kidFrame = mState.mKidFrame;
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: attempt frame=%p[%d] mX=%d availWidth=%d",
- kidFrame, mState.mKidIndex,
- mState.mX, mRightEdge - mState.mX));
-
- // Get kid frame's style context
- nsIStyleContextPtr kidSC;
- nsresult rv = kidFrame->GetStyleContext(mPresContext, kidSC.AssignRef());
- if (NS_OK != rv) {
- return rv;
- }
-
- // See if frame belongs in the line.
- // XXX absolute positioning
- // XXX floating frames
- // XXX break-before
- const nsStyleDisplay * kidDisplay = (const nsStyleDisplay*)
- kidSC->GetStyleData(eStyleStruct_Display);
- PRBool isBlock = PR_FALSE;
- PRBool isFirstChild = PRBool(kidFrame == mLine->mFirstChild);
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_NONE:
- // Make sure the frame remains zero sized.
- kidFrame->WillReflow(*mPresContext);
- kidFrame->SetRect(nsRect(mState.mX, mY, 0, 0));
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: display=none"));
- return NS_LINE_LAYOUT_COMPLETE;
-
- case NS_STYLE_DISPLAY_INLINE:
- break;
-
- default:
- isBlock = PR_TRUE;
- if (!isFirstChild) {
- // XXX Make sure child is dirty for next time
- kidFrame->WillReflow(*mPresContext);
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: block requires break-before"));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- break;
- }
-
- // Get the available size to reflow the child into
- PRBool didBreak = PR_FALSE;
- reflow_it_again_sam:
- nscoord availWidth = mRightEdge - mState.mX;
- nsSize kidAvailSize;
- kidAvailSize.width = availWidth;
- kidAvailSize.height = mMaxHeight;
- const nsStyleSpacing* kidSpacing = (const nsStyleSpacing*)
- kidSC->GetStyleData(eStyleStruct_Spacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kidFrame, kidMargin);
- if (!mUnconstrainedWidth) {
- if (mNoWrap) {
- // When our reflow is constrained and we are we are not supposed
- // to wrap make sure the child will fit regardless of how much
- // space is left.
- if (isBlock) {
- // Never give a block an infinite width
- kidAvailSize.width = mRightEdge - mLeftEdge;
- }
- else {
- kidAvailSize.width = NS_UNCONSTRAINEDSIZE;
- }
- }
- else {
- kidAvailSize.width -= kidMargin.left + kidMargin.right;
- if (!isFirstChild && (kidAvailSize.width <= 0)) {
- // No room.
- if (!didBreak && CanBreak()) {
- kidFrame = mState.mKidFrame;
- didBreak = PR_TRUE;
- mPendingBreak = NS_STYLE_CLEAR_NONE;
- goto reflow_it_again_sam;
- }
-
- // XXX Make sure child is dirty for next time
- kidFrame->WillReflow(*mPresContext);
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: !fit"));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- }
- }
-
- // Reflow the child
- mFramesReflowed++;
- nsRect kidRect;
- nsSize maxElementSize;
- nsSize* kidMaxElementSize = nsnull;
- nsReflowStatus kidReflowStatus;
- if (nsnull != mMaxElementSizePointer) {
- kidMaxElementSize = &maxElementSize;
- }
- nsReflowMetrics kidMetrics(kidMaxElementSize);
-
- // Get reflow reason set correctly. It's possible that we created a
- // child and then decided that we cannot reflow it (for example, a
- // block frame that isn't at the start of a line). In this case the
- // reason will be wrong so we need to check the frame state.
- nsReflowReason kidReason = eReflowReason_Resize;
- if (nsnull != aReflowCommand) {
- kidReason = eReflowReason_Incremental;
- }
- else if (aNewChild) {
- kidReason = eReflowReason_Initial;
- }
- else {
- nsFrameState state;
- kidFrame->GetFrameState(state);
- if (NS_FRAME_FIRST_REFLOW & state) {
- kidReason = eReflowReason_Initial;
- }
- }
-
- nsReflowState kidReflowState(kidFrame, *mBlockReflowState.reflowState,
- kidAvailSize, kidReason);
- kidReflowState.reflowCommand = aReflowCommand;
- mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
- nscoord dx = mState.mX + kidMargin.left;
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: reflowing frame into %d,%d",
- kidAvailSize.width, kidAvailSize.height));
- if (isBlock) {
- // Calculate top margin by collapsing with previous bottom margin
- nscoord negTopMargin;
- nscoord posTopMargin;
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kidFrame, kidMargin);
- if (kidMargin.top < 0) {
- negTopMargin = -kidMargin.top;
- posTopMargin = 0;
- } else {
- negTopMargin = 0;
- posTopMargin = kidMargin.top;
- }
-
- // XXX if (nav4_compatability)
- // Calculate the previous margin's positive and negative value.
- // If the current top margin is not defined by css then just use
- // what is cached in the block reflow state. Otherwise if the top
- // margin is defined by css then wipe out any synthetic margin.
- nscoord prevPos = mBlockReflowState.mPrevPosBottomMargin;
- nscoord prevNeg = mBlockReflowState.mPrevNegBottomMargin;
- if (eStyleUnit_Null != kidSpacing->mMargin.GetTopUnit()) {
- if (mBlockReflowState.mPrevMarginSynthetic) {
- prevPos = 0;
- prevNeg = 0;
- }
- }
- else {
- // When our top margin is not specified by css...act like
- // ebina's engine.
- if ((nsnull != mLine->mPrevLine) && !mLine->mPrevLine->mIsBlock) {
- // Supply a default top margin
- const nsStyleFont* styleFont;
- mBlock->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)styleFont);
- nsIFontMetrics* fm = mPresContext->GetMetricsFor(styleFont->mFont);
- mBlockReflowState.mPrevNegBottomMargin = 0;
- mBlockReflowState.mPrevPosBottomMargin = fm->GetHeight();
- mBlockReflowState.mPrevMarginSynthetic = PR_TRUE;
- NS_RELEASE(fm);
- }
- }
-
- nscoord maxPos = PR_MAX(prevPos, posTopMargin);
- nscoord maxNeg = PR_MAX(prevNeg, negTopMargin);
- nscoord topMargin = maxPos - maxNeg;
-
- // This is no longer a break point
- mSavedState.mKidFrame = nsnull;
- mBreakFrame = nsnull;
-
- mY += topMargin;
- mBlockReflowState.mY += topMargin;
- // XXX tell block what topMargin ended up being so that it can
- // undo it if it ends up pushing the line.
-
- NS_ASSERTION(0 == mPendingBreak, "whoops: uncleared break");
- mSpaceManager->Translate(dx, mY);
- kidFrame->WillReflow(*mPresContext);
- kidFrame->MoveTo(dx, mY);
- rv = mBlock->ReflowBlockChild(kidFrame, mPresContext,
- mSpaceManager, kidMetrics, kidReflowState,
- kidRect, kidReflowStatus);
- mSpaceManager->Translate(-dx, -mY);
-
- if ((0 == kidRect.width) && (0 == kidRect.height)) {
- // When a block child collapses into nothingness we don't apply
- // it's margins.
- mY -= topMargin;
- mBlockReflowState.mY -= topMargin;
- }
- else {
- // XXX if (nav4_compatability)
- // If the block frame we just reflowed has no bottom margin as
- // specified by css, then we supply our own.
- if (eStyleUnit_Null == kidSpacing->mMargin.GetBottomUnit()) {
- // ebina's engine uses the height of the font for the bottom margin.
- nsIStyleContext* blockSC;
- const nsStyleFont* styleFont;
- mBlock->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)styleFont);
- nsIFontMetrics* fm = mPresContext->GetMetricsFor(styleFont->mFont);
- mBlockReflowState.mPrevNegBottomMargin = 0;
- mBlockReflowState.mPrevPosBottomMargin = fm->GetHeight();
- mBlockReflowState.mPrevMarginSynthetic = PR_TRUE;
- NS_RELEASE(fm);
- }
- else {
- // Save away bottom margin information for later
- if (kidMargin.bottom < 0) {
- mBlockReflowState.mPrevNegBottomMargin = -kidMargin.bottom;
- mBlockReflowState.mPrevPosBottomMargin = 0;
- } else {
- mBlockReflowState.mPrevNegBottomMargin = 0;
- mBlockReflowState.mPrevPosBottomMargin = kidMargin.bottom;
- }
- mBlockReflowState.mPrevMarginSynthetic = PR_FALSE;
- }
- }
-
- kidRect.x = dx;
- kidRect.y = mY;
- kidMetrics.width = kidRect.width;
- kidMetrics.height = kidRect.height;
- kidMetrics.ascent = kidRect.height;
- kidMetrics.descent = 0;
- }
- else {
- // Apply bottom margin speculatively before reflowing the child
- nscoord bottomMargin = mBlockReflowState.mPrevPosBottomMargin -
- mBlockReflowState.mPrevNegBottomMargin;
- if (!mMarginApplied) {
- // Before we place the first inline child on this line apply
- // the previous block's bottom margin.
- mY += bottomMargin;
- mBlockReflowState.mY += bottomMargin;
- }
-
- NS_ASSERTION(0 == mPendingBreak, "whoops: uncleared break");
- kidFrame->WillReflow(*mPresContext);
- kidFrame->MoveTo(dx, mY);
- rv = mBlock->ReflowInlineChild(*this, kidFrame, kidMetrics,
- kidReflowState, kidReflowStatus);
-
- // See if speculative application of the margin should stick
- if (!mMarginApplied) {
- if (0 == kidMetrics.height) {
- // No, undo margin application when we get a zero height child.
- mY -= bottomMargin;
- mBlockReflowState.mY -= bottomMargin;
- }
- else {
- // Yes, keep the margin application.
- mMarginApplied = PR_TRUE;
- mBlockReflowState.mPrevPosBottomMargin = 0;
- mBlockReflowState.mPrevNegBottomMargin = 0;
- // XXX tell block what bottomMargin ended up being so that it can
- // undo it if it ends up pushing the line.
- }
- }
-
- kidRect.x = dx;
- kidRect.y = mY;
- kidRect.width = kidMetrics.width;
- kidRect.height = kidMetrics.height;
- }
- if (NS_OK != rv) return rv;
-
- // See if the child fit
- if (kidMetrics.width > kidAvailSize.width) {
- if (!isFirstChild) {
- if (!didBreak && CanBreak()) {
- kidFrame = mState.mKidFrame;
- didBreak = PR_TRUE;
- mPendingBreak = NS_STYLE_CLEAR_NONE;
- goto reflow_it_again_sam;
- }
- else {
- // We are out of room.
- // XXX mKidPrevInFlow
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: !fit size=%d,%d",
- kidRect.width, kidRect.height));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- }
- }
-
- // Non-aware children that take up space act like words; which means
- // that space immediately following them must not be skipped over.
- if (NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE == mReflowResult) {
- if ((kidRect.width != 0) && (kidRect.height != 0)) {
- mState.mSkipLeadingWhiteSpace = PR_FALSE;
- }
- }
-
- // Now place the child
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: fit size=%d,%d",
- kidRect.width, kidRect.height));
- mLine->mIsBlock = isBlock;
- return PlaceChild(kidRect, kidMetrics, kidMaxElementSize,
- kidMargin, kidReflowStatus);
-}
-
-nsresult
-nsLineLayout::PlaceChild(nsRect& kidRect,
- const nsReflowMetrics& kidMetrics,
- const nsSize* kidMaxElementSize,
- const nsMargin& kidMargin,
- nsReflowStatus kidReflowStatus)
-{
- nscoord horizontalMargins = 0;
-
- // Special case to position outside list bullets.
- // XXX RTL bullets
- PRBool isBullet = PR_FALSE;
- if (mBlockReflowState.mListPositionOutside) {
- PRBool isFirstChild = PRBool(mState.mKidFrame == mLine->mFirstChild);
- PRBool isFirstLine = PRBool(nsnull == mLine->mPrevLine);
- if (isFirstChild && isFirstLine) {
- nsIFrame* blockPrevInFlow;
- mBlock->GetPrevInFlow(blockPrevInFlow);
- PRBool isFirstInFlow = PRBool(nsnull == blockPrevInFlow);
- if (isFirstInFlow) {
- isBullet = PR_TRUE;
- // We are placing the first child of the block therefore this
- // is the bullet that is being reflowed. The bullet is placed
- // in the padding area of this block. Don't worry about
- // getting the Y coordinate of the bullet right (vertical
- // alignment will take care of that).
-
- // Compute gap between bullet and inner rect left edge
- const nsStyleFont* font;
- mBlock->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)font);
- nsIFontMetrics* fm = mPresContext->GetMetricsFor(font->mFont);
- nscoord kidAscent = fm->GetMaxAscent();
- nscoord dx = fm->GetHeight() / 2; // from old layout engine
- NS_RELEASE(fm);
-
- // XXX RTL bullets
- kidRect.x = mState.mX - kidRect.width - dx;
- mState.mKidFrame->SetRect(kidRect);
- }
- }
- }
- if (!isBullet) {
- // Place normal in-flow child
- mState.mKidFrame->SetRect(kidRect);
-
- // Advance
- // XXX RTL
- horizontalMargins = kidMargin.left + kidMargin.right;
- nscoord totalWidth = kidMetrics.width + horizontalMargins;
- mState.mX += totalWidth;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::PlaceChild: frame=%p[%d] {%d, %d, %d, %d}",
- mState.mKidFrame,
- mState.mKidIndex,
- kidRect.x, kidRect.y, kidRect.width, kidRect.height));
-
- if (nsnull != mMaxElementSizePointer) {
- // XXX I'm not certain that this is doing the right thing; rethink this
- nscoord elementWidth = kidMaxElementSize->width + horizontalMargins;
- if (elementWidth > mState.mMaxElementSize.width) {
- mState.mMaxElementSize.width = elementWidth;
- }
- if (kidMetrics.height > mState.mMaxElementSize.height) {
- mState.mMaxElementSize.height = kidMetrics.height;
- }
- }
- if (kidMetrics.ascent > mState.mMaxAscent) {
- mState.mMaxAscent = kidMetrics.ascent;
- }
- if (kidMetrics.descent > mState.mMaxDescent) {
- mState.mMaxDescent = kidMetrics.descent;
- }
- SetAscent(mLine->mIsBlock ? 0 : kidMetrics.ascent);
-
- // Set completion status
- nsresult rv = NS_LINE_LAYOUT_COMPLETE;
- mLine->mLastContentOffset = mState.mKidIndex;
- if (NS_FRAME_IS_COMPLETE(kidReflowStatus)) {
- mLine->mLastContentIsComplete = PR_TRUE;
- if (mLine->mIsBlock ||
- (NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER == mReflowResult) ||
- (NS_STYLE_CLEAR_NONE != mPendingBreak)) {
- rv = NS_LINE_LAYOUT_BREAK_AFTER;
- if (NS_STYLE_CLEAR_LINE == mPendingBreak) {
- mPendingBreak = NS_STYLE_CLEAR_NONE;
- }
- }
- mKidPrevInFlow = nsnull;
- }
- else {
- mLine->mLastContentIsComplete = PR_FALSE;
- rv = NS_LINE_LAYOUT_NOT_COMPLETE;
- mKidPrevInFlow = mState.mKidFrame;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::PlaceChild: rv=%d", rv));
- return rv;
-}
-
-nsresult
-nsLineLayout::IncrementalReflowFromChild(nsIReflowCommand* aReflowCommand,
- nsIFrame* aChildFrame)
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
-
- mLine->mBounds.x = mState.mX;
- mLine->mBounds.y = mY;
- mState.mKidFrame = mLine->mFirstChild;
- mState.mKidFrameNum = 0;
- while (mState.mKidFrameNum < mLine->mChildCount) {
- nsresult childReflowStatus;
- if (mState.mKidFrame == aChildFrame) {
- childReflowStatus = ReflowChild(aReflowCommand, PR_FALSE);
- } else {
- childReflowStatus = ReflowMappedChild();
- }
-
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
-
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
-
-done:
- // Perform alignment operations
- AlignChildren();
-
- // Set final bounds of the line
- mLine->mBounds.height = mLineHeight;
- mLine->mBounds.width = mState.mX - mLine->mBounds.x;
-
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from ReflowMapped");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::SplitLine(PRInt32 aChildReflowStatus)
-{
- PRInt32 pushCount = mLine->mChildCount - mState.mKidFrameNum;
- nsresult rv = NS_LINE_LAYOUT_COMPLETE;
-
- if (NS_LINE_LAYOUT_NOT_COMPLETE == aChildReflowStatus) {
- // When a line is not complete it indicates that the last child on
- // the line reflowed and took some space but wasn't given enough
- // space to complete. Sometimes when this happens we will need to
- // create a next-in-flow for the child.
- nsIFrame* nextInFlow;
- mState.mPrevKidFrame->GetNextInFlow(nextInFlow);
- if (nsnull == nextInFlow) {
- // Create a continuation frame for the child frame and insert it
- // into our lines child list.
- nsIFrame* nextFrame;
- mState.mPrevKidFrame->GetNextSibling(nextFrame);
- nsIStyleContext* kidSC;
- mState.mPrevKidFrame->GetStyleContext(mPresContext, kidSC);
- mState.mPrevKidFrame->CreateContinuingFrame(mPresContext, mBlock, kidSC,
- nextInFlow);
- NS_RELEASE(kidSC);
- if (nsnull == nextInFlow) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- mState.mPrevKidFrame->SetNextSibling(nextInFlow);
- nextInFlow->SetNextSibling(nextFrame);
- mNewFrames++;
-
- // Add new child to our line
- mLine->mChildCount++;
-
- // Set mKidFrame to the new next-in-flow so that we will
- // push it when we push children. Increment the number of
- // remaining kids now that there is one more.
- mState.mKidFrame = nextInFlow;
- pushCount++;
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::SplitLine: created next in flow %p",
- nextInFlow));
- }
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::SplitLine: pushing %d frames",
- pushCount));
-
- if (0 != pushCount) {
- NS_ASSERTION(nsnull != mState.mKidFrame, "whoops");
- nsLineData* from = mLine;
- nsLineData* to = mLine->mNextLine;
- if (nsnull != to) {
- // Only push into the next line if it's empty; otherwise we can
- // end up pushing a frame which is continued into the same frame
- // as it's continuation. This causes all sorts of side effects
- // so we don't allow it.
- if (to->mChildCount != 0) {
- nsLineData* insertedLine = new nsLineData();
- from->mNextLine = insertedLine;
- to->mPrevLine = insertedLine;
- insertedLine->mPrevLine = from;
- insertedLine->mNextLine = to;
- to = insertedLine;
- to->mLastContentOffset = from->mLastContentOffset;
- to->mLastContentIsComplete = from->mLastContentIsComplete;
- }
- } else {
- to = new nsLineData();
- to->mPrevLine = from;
- from->mNextLine = to;
- }
- if (nsnull == to) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- PRInt32 kidIndexInParent;
- mState.mKidFrame->GetContentIndex(kidIndexInParent);
- to->mFirstChild = mState.mKidFrame;
- to->mChildCount += pushCount;
- to->mFirstContentOffset = kidIndexInParent;
-
- // The to-line is going to be reflowed therefore it's last content
- // offset and completion status don't matter. In fact, it's expensive
- // to compute them so don't bother.
-#ifdef NS_DEBUG
- to->mLastContentOffset = -1;
- to->mLastContentIsComplete = PRPackedBool(0x255);
-#endif
-
- from->mChildCount -= pushCount;
- NS_ASSERTION(0 != from->mChildCount, "bad push");
-#ifdef NS_DEBUG
- if (nsIFrame::GetVerifyTreeEnable()) {
- from->Verify();
- }
-#endif
-#ifdef NOISY_REFLOW
- printf("After push, from-line (%d):\n", pushCount);
- from->List(stdout, 1);
- printf("After push, to-line:\n");
- to->List(stdout, 1);
-#endif
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("nsLineLayout::SplitLine: returning %d",
- aChildReflowStatus));
- return aChildReflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::ReflowMapped()
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
-
- mState.mKidFrame = mLine->mFirstChild;
- mState.mKidFrameNum = 0;
- while (mState.mKidFrameNum < mLine->mChildCount) {
- nsresult childReflowStatus = ReflowMappedChild();
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
-
-done:
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from ReflowMapped");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-static PRBool
-IsBlock(const nsStyleDisplay* aDisplay)
-{
- switch (aDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- return PR_TRUE;
- }
- return PR_FALSE;
-}
-
-// XXX fix this code to look at the available width and if it's too
-// small for the next child then skip the pullup (and return
-// BREAK_AFTER status).
-
-nsresult
-nsLineLayout::PullUpChildren()
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
- nsIFrame* prevKidFrame = mState.mPrevKidFrame;
-
- nsBlockFrame* currentBlock = mBlock;
- nsLineData* line = mLine->mNextLine;
- while (nsnull != currentBlock) {
-
- // Pull children from the next line
- while (nsnull != line) {
- // Get first child from next line
- mState.mKidFrame = line->mFirstChild;
- if (nsnull == mState.mKidFrame) {
- NS_ASSERTION(0 == line->mChildCount, "bad line list");
- nsLineData* nextLine = line->mNextLine;
- nsLineData* prevLine = line->mPrevLine;
- if (nsnull != prevLine) prevLine->mNextLine = nextLine;
- if (nsnull != nextLine) nextLine->mPrevLine = prevLine;
- delete line;/* XXX free-list in block-reflow-state? */
- line = nextLine;
- continue;
- }
-
- // XXX Avoid the pullup work if the child cannot already fit
- // (e.g. it's not splittable and can't fit)
-
- // XXX change this to use the next-line's mIsBlock when possible
- // (make sure push code set it's properly for this to work: only
- // from reflow-unmapped)
-
- // If the child is a block element then if this is not the first
- // line in the block or if it's the first line and it's not the
- // first child in the line then we cannot pull-up the child.
- nsresult rv;
- const nsStyleDisplay* kidDisplay;
- rv = mState.mKidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- if (IsBlock(kidDisplay)) {
- if ((nsnull != mLine->mPrevLine) || (0 != mLine->mChildCount)) {
- goto done;
- }
- }
-
- // Make pulled child part of this line
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("nsLineLayout::PullUpChildren: trying to pull frame=%p",
- mState.mKidFrame));
- mLine->mChildCount++;
- if (0 == --line->mChildCount) {
- // Remove empty lines from the list
- nsLineData* nextLine = line->mNextLine;
- nsLineData* prevLine = line->mPrevLine;
- if (nsnull != prevLine) prevLine->mNextLine = nextLine;
- if (nsnull != nextLine) nextLine->mPrevLine = prevLine;
- delete line;/* XXX free-list in block-reflow-state? */
- line = nextLine;
- }
- else {
- // Repair the first content offset of the line. The first
- // child of the line's index-in-parent should be the line's
- // new first content offset.
- mState.mKidFrame->GetNextSibling(line->mFirstChild);
- PRInt32 indexInParent;
- line->mFirstChild->GetContentIndex(indexInParent);
- line->mFirstContentOffset = indexInParent;
-#ifdef NS_DEBUG
- if (nsIFrame::GetVerifyTreeEnable()) {
- line->Verify();
- }
-#endif
- }
-
- // Try to reflow it like any other mapped child
- nsresult childReflowStatus = ReflowMappedChild();
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidIndex++;
- mState.mKidFrameNum++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidIndex++;
- mState.mKidFrameNum++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
-
- // Grab the block's next in flow
- nsIFrame* nextInFlow;
- currentBlock->GetNextInFlow(nextInFlow);
- currentBlock = (nsBlockFrame*)nextInFlow;
- if (nsnull != currentBlock) {
- line = currentBlock->GetFirstLine();
- }
- }
-
-done:
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from PullUpChildren");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::CreateFrameFor(nsIContent* aKid)
-{
- nsIStyleContextPtr kidSC =
- mPresContext->ResolveStyleContextFor(aKid, mBlock); // XXX bad API
- if (nsnull == kidSC) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- const nsStylePosition* kidPosition = (const nsStylePosition*)
- kidSC->GetStyleData(eStyleStruct_Position);
- const nsStyleDisplay* kidDisplay = (const nsStyleDisplay*)
- kidSC->GetStyleData(eStyleStruct_Display);
-
- // Check whether it wants to floated or absolutely positioned
- PRBool isBlock = PR_FALSE;
- nsIFrame* kidFrame;
- nsresult rv;
- if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) {
- rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- }
- else if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
- rv = nsPlaceholderFrame::NewFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- }
- else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) ||
- (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) {
- rv = NS_NewScrollFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- }
- else if (nsnull == mKidPrevInFlow) {
- // Create initial frame for the child
- nsIContentDelegate* kidDel;
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_NONE:
- rv = nsFrame::NewFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- break;
-
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- isBlock = PR_TRUE;
- // FALL THROUGH
- default:
- kidDel = aKid->GetDelegate(mPresContext);
- rv = kidDel->CreateFrame(mPresContext, aKid, mBlock, kidSC, kidFrame);
- NS_RELEASE(kidDel);
- break;
- }
- } else {
- // Since kid has a prev-in-flow, use that to create the next
- // frame.
- rv = mKidPrevInFlow->CreateContinuingFrame(mPresContext, mBlock, kidSC,
- kidFrame);
- NS_ASSERTION(0 == mLine->mChildCount, "bad continuation");
- }
- if (NS_OK != rv) {
- return rv;
- }
- if (NS_OK == rv) {
- // Wrap the frame in a view if necessary
- rv = nsHTMLBase::CreateViewForFrame(mPresContext, kidFrame, kidSC,
- PR_FALSE);
- if (NS_OK != rv) {
- return rv;
- }
- }
-
- mState.mKidFrame = kidFrame;
- mNewFrames++;
-
- if (isBlock && (0 != mLine->mChildCount)) {
- // When we are not at the start of a line we need to break
- // before a block element.
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
-
- return rv;
-}
-
-nsresult
-nsLineLayout::ReflowUnmapped()
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
- for (;;) {
- nsIContentPtr kid = mBlockContent->ChildAt(mState.mKidIndex);
- if (kid.IsNull()) {
- break;
- }
-
- // Create a frame for the new content
- nsresult rv = CreateFrameFor(kid);
- if (rv < 0) {
- reflowStatus = rv;
- goto done;
- }
-
- // Add frame to our list
- if (nsnull != mState.mPrevKidFrame) {
- mState.mPrevKidFrame->SetNextSibling(mState.mKidFrame);
- }
- if (0 == mLine->mChildCount) {
- mLine->mFirstChild = mState.mKidFrame;
- mBlock->SetFirstChild(mState.mKidFrame);
- }
- mLine->mChildCount++;
-
- nsresult childReflowStatus;
- if (rv == NS_LINE_LAYOUT_BREAK_BEFORE) {
- // If we break before a frame is even supposed to layout then we
- // need to split the line.
- childReflowStatus = rv;
-
- // XXX Mark new frame dirty so it gets reflow later on
- mState.mKidFrame->WillReflow(*mPresContext);
- goto split_line;
- }
-
- // Reflow new child frame
- childReflowStatus = ReflowChild(nsnull, PR_TRUE);
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- mState.mKidIndex++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- mState.mKidIndex++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
- NS_ASSERTION(nsnull == mLine->mNextLine, "bad line list");
-
-done:
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from ReflowUnmapped");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::ReflowLine()
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("enter nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
- mLine->mChildCount,
- mLine->mBounds.x, mLine->mBounds.y,
- mLine->mBounds.width, mLine->mBounds.height));
-
- nsresult rv = NS_LINE_LAYOUT_COMPLETE;
-
- mLine->mBounds.x = mState.mX;
- mLine->mBounds.y = mY;
- mOldChildCount = mLine->mChildCount;
-
- // Reflow the mapped frames
- if (0 != mLine->mChildCount) {
- rv = ReflowMapped();
- if (rv < 0) return rv;
- }
-
- // Pull-up any frames from the next line
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- if (nsnull != mLine->mNextLine) {
- rv = PullUpChildren();
- if (rv < 0) return rv;
- }
-
- // Try reflowing any unmapped children
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- if (nsnull == mLine->mNextLine) {
- rv = ReflowUnmapped();
- if (rv < 0) return rv;
- }
- }
- }
-
- // Perform alignment operations
- AlignChildren();
-
- // Set final bounds of the line
- mLine->mBounds.height = mLineHeight;
- mLine->mBounds.width = mState.mX - mLine->mBounds.x;
-
-#ifdef NS_DEBUG
- if (nsIFrame::GetVerifyTreeEnable()) {
- mLine->Verify();
- }
-#endif
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("exit nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
- mLine->mChildCount,
- mLine->mBounds.x, mLine->mBounds.y,
- mLine->mBounds.width, mLine->mBounds.height));
- return rv;
-}
-
-void
-nsLineLayout::AlignChildren()
-{
- NS_PRECONDITION(mLine->mChildCount == mState.mKidFrameNum, "bad line reflow");
-
- // Block lines don't require (or allow!) alignment
- if (mLine->mIsBlock) {
- mLineHeight = mState.mMaxAscent + mState.mMaxDescent;
- }
- else {
- // Avoid alignment when we didn't actually reflow any frames and we
- // also didn't change the number of frames we had (which means the
- // pullup code didn't pull anything up). When this happens it means
- // that nothing changed which means that we can avoid the alignment
- // work.
- if ((0 == mFramesReflowed) && (mOldChildCount == mLine->mChildCount)) {
- mLineHeight = mLine->mBounds.height;
- }
- }
-
- nsIStyleContextPtr blockSC;
- mBlock->GetStyleContext(mPresContext, blockSC.AssignRef());
- const nsStyleFont* blockFont = (const nsStyleFont*)
- blockSC->GetStyleData(eStyleStruct_Font);
- const nsStyleText* blockText = (const nsStyleText*)
- blockSC->GetStyleData(eStyleStruct_Text);
- const nsStyleDisplay* blockDisplay = (const nsStyleDisplay*)
- blockSC->GetStyleData(eStyleStruct_Display);
-
- // First vertically align the children on the line; this will
- // compute the actual line height for us.
- if (!mLine->mIsBlock) {
- mLineHeight =
- nsCSSLayout::VerticallyAlignChildren(mPresContext, mBlock, blockFont,
- mY,
- mLine->mFirstChild,
- mLine->mChildCount,
- mAscents, mState.mMaxAscent);
- }
-
- // Now horizontally place the children
- nsCSSLayout::HorizontallyPlaceChildren(mPresContext, mBlock,
- blockText->mTextAlign,
- blockDisplay->mDirection,
- mLine->mFirstChild,
- mLine->mChildCount,
- mState.mX - mLeftEdge,
- mMaxWidth);
-
- // Last, apply relative positioning
- nsCSSLayout::RelativePositionChildren(mPresContext, mBlock,
- mLine->mFirstChild,
- mLine->mChildCount);
-}
diff --git a/mozilla/layout/generic/nsLineLayout.h b/mozilla/layout/generic/nsLineLayout.h
deleted file mode 100644
index 34bc57051e2..00000000000
--- a/mozilla/layout/generic/nsLineLayout.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#ifndef nsLineLayout_h___
-#define nsLineLayout_h___
-
-#include "nsIFrame.h"
-#include "nsCoord.h"
-#include "nsSize.h"
-#include "nsVoidArray.h"
-
-class nsIPresContext;
-class nsISpaceManager;
-class nsBlockFrame;
-struct nsBlockReflowState;
-struct nsLineLayout;
-
-/* d76e29b0-ff56-11d1-89e7-006008911b81 */
-#define NS_IINLINE_FRAME_IID \
-{0xd76e29b0, 0xff56, 0x11d1, {0x89, 0xe7, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
-
-/**
- * Interface to "inline frames". Inline frames are those that are aware
- * of html line layout.
- *
- * Note that this interface does not expose AddRef/Release (like all frame
- * interfaces)
- */
-class nsIInlineFrame : private nsISupports {
-public:
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0;
-
- NS_IMETHOD ReflowInline(nsLineLayout& aLineLayout,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus) = 0;
-};
-
-//----------------------------------------------------------------------
-
-/**
- * Persistent per-line data
- */
-struct nsLineData {
- nsLineData();
- ~nsLineData();
-
- nsIFrame* GetLastChild();
- nsresult Verify(PRBool aFinalCheck = PR_TRUE) const;
- void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
- void UnlinkLine();
- PRIntn GetLineNumber() const;
-
- nsLineData* mNextLine;
- nsLineData* mPrevLine;
- nsIFrame* mFirstChild;
- PRInt32 mChildCount;
- PRInt32 mFirstContentOffset;
- PRInt32 mLastContentOffset;
- nsRect mBounds;
- PRPackedBool mLastContentIsComplete;
- PRPackedBool mIsBlock;
- nsVoidArray* mFloaters; // placeholder frames for below current line floaters
-};
-
-//----------------------------------------------------------------------
-
-/**
- * Transient state used during line reflow.
- */
-
-// State used during line layout that may need to be rewound because
-// of an inconvenient word break.
-struct nsLineLayoutState {
- // The next x coordinate to place the child frame
- nscoord mX;
-
- // This is true if the next frame to reflow should skip over leading
- // whitespace.
- PRBool mSkipLeadingWhiteSpace;
-
- // The column number when pre-formatting (for tab spacing)
- PRInt32 mColumn;
-
- // The child frame being considered for reflow
- nsIFrame* mKidFrame;
-
- // The previous child frame just reflowed
- nsIFrame* mPrevKidFrame;
-
- // The child frame's content index-in-parent
- PRInt32 mKidIndex;
-
- // The child frame number within this line
- PRInt32 mKidFrameNum;
-
- // Current line values values
- nsSize mMaxElementSize;
- nscoord mMaxAscent;
- nscoord mMaxDescent;
-};
-
-struct nsLineLayout {
- nsLineLayout(nsBlockReflowState& aState);
- ~nsLineLayout();
-
- nsresult Initialize(nsBlockReflowState& aState, nsLineData* aLine);
-
- void SetReflowSpace(nsRect& aAvailableSpaceRect);
-
- nsresult ReflowLine();
-
- nsresult IncrementalReflowFromChild(nsIReflowCommand* aReflowCommand,
- nsIFrame* aChildFrame);
-
- void AtSpace();
-
- void AtWordStart(nsIFrame* aFrame, nscoord aX);
-
- PRBool SkipLeadingWhiteSpace() {
- return mState.mSkipLeadingWhiteSpace;
- }
-
- void SetSkipLeadingWhiteSpace(PRBool aSkip) {
- mState.mSkipLeadingWhiteSpace = aSkip;
- }
-
- PRIntn GetColumn() {
- return mState.mColumn;
- }
-
- void SetColumn(PRIntn aNewColumn) {
- mState.mColumn = aNewColumn;
- }
-
- // A value set by line-layout cognizant frames. Frames that are not
- // aware of line layout leave the value unchanged and can thus be
- // detected by the line-layout algorithm.
- PRInt32 mReflowResult;
-
- // The presentation context
- nsIPresContext* mPresContext;
-
- // The block behind the line
- nsBlockFrame* mBlock;
- nsBlockReflowState& mBlockReflowState;
- nsISpaceManager* mSpaceManager;
- nsIContent* mBlockContent;
- PRBool mNoWrap;
-
- // The line we are reflowing
- nsLineData* mLine;
- nsIFrame* mKidPrevInFlow;
-
- // Whenever the line layout creates a frame this slot is incremented
- PRIntn mNewFrames;
- PRIntn mFramesReflowed;
- PRIntn mOldChildCount;
-
- nsLineLayoutState mState;
- nsLineLayoutState mSavedState;
-
- // The current breakable point in the line. If a line-break is
- // requested then this is where the line will break at.
- nsIFrame* mBreakFrame;
- nscoord mBreakX;
- PRUint8 mPendingBreak;
-
- // XXX ick
- // This is set by the block code when it updates the available
- // reflow area when a floater is placed.
- PRBool mReflowDataChanged;
- PRPackedBool mMustReflowMappedChildren;
-
- PRPackedBool mUnconstrainedWidth;
- PRPackedBool mUnconstrainedHeight;
- PRPackedBool mMarginApplied;
-
- nscoord mY;
- nscoord mLineHeight;
- nscoord mMaxWidth;
- nscoord mMaxHeight;
- nsSize* mMaxElementSizePointer;
- nscoord mLeftEdge;
- nscoord mRightEdge;
-
- nscoord* mAscents;
- nscoord mAscentBuf[20];
- nscoord mMaxAscents;
-
-protected:
- nsresult SetAscent(nscoord aAscent);
-
- nsresult ReflowMappedChild();
-
- nsresult ReflowChild(nsIReflowCommand* aReflowCommand, PRBool aNewChild);
-
- nsresult PlaceChild(nsRect& kidRect,
- const nsReflowMetrics& kidMetrics,
- const nsSize* kidMaxElementSize,
- const nsMargin& kidMargin,
- nsReflowStatus kidReflowStatus);
-
- nsresult ReflowMapped();
-
- nsresult SplitLine(PRInt32 aChildReflowStatus);
-
- nsresult PushChildren();
-
- nsresult CreateNextInFlow(nsIFrame* aFrame);
-
- nsresult PullUpChildren();
-
- nsresult CreateFrameFor(nsIContent* aKid);
-
- nsresult ReflowUnmapped();
-
- void AlignChildren();
-
- PRBool CanBreak();
-};
-
-// Value's for nsLineLayout.mReflowResult
-#define NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE 0
-#define NS_LINE_LAYOUT_REFLOW_RESULT_AWARE 1
-#define NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER 2
-
-// Return value's from nsLineLayout reflow methods
-#define NS_LINE_LAYOUT_COMPLETE 0
-#define NS_LINE_LAYOUT_NOT_COMPLETE 1
-#define NS_LINE_LAYOUT_BREAK_BEFORE 2
-#define NS_LINE_LAYOUT_BREAK_AFTER 3
-
-#endif /* nsLineLayout_h___ */
diff --git a/mozilla/layout/generic/nsPlaceholderFrame.cpp b/mozilla/layout/generic/nsPlaceholderFrame.cpp
index 5ce07ccbb92..d9c74c4c9ea 100644
--- a/mozilla/layout/generic/nsPlaceholderFrame.cpp
+++ b/mozilla/layout/generic/nsPlaceholderFrame.cpp
@@ -23,8 +23,7 @@
#include "nsIStyleContext.h"
#include "nsCSSLayout.h"
#include "nsIView.h"
-
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
+#include "nsHTMLIIDs.h"
nsresult
nsPlaceholderFrame::NewFrame(nsIFrame** aInstancePtrResult,
@@ -112,7 +111,7 @@ nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext,
}
// Notify our containing block that there's a new floater
- container->AddFloater(aPresContext, mAnchoredItem, this);
+ container->AddFloater(aPresContext, aReflowState, mAnchoredItem, this);
} else {
// XXX This causes anchored-items sizes to get fixed up; this is
@@ -125,7 +124,8 @@ nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext,
mAnchoredItem->WillReflow(*aPresContext);
mAnchoredItem->Reflow(aPresContext, desiredSize, reflowState, aStatus);
mAnchoredItem->SizeTo(desiredSize.width, desiredSize.height);
- container->PlaceFloater(aPresContext, mAnchoredItem, this);
+
+//XXXdeprecated container->PlaceFloater(aPresContext, mAnchoredItem, this);
mAnchoredItem->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
}
diff --git a/mozilla/layout/html/base/src/Makefile b/mozilla/layout/html/base/src/Makefile
index 54c1765b1bd..33deda896ec 100644
--- a/mozilla/layout/html/base/src/Makefile
+++ b/mozilla/layout/html/base/src/Makefile
@@ -23,7 +23,6 @@ LIBRARY_NAME = raptorhtmlbase_s
CPPSRCS = \
nsAbsoluteFrame.cpp \
nsBRPart.cpp \
- nsBlockFrame.cpp \
nsBodyFrame.cpp \
nsBodyPart.cpp \
nsGlobalVariables.cpp \
@@ -41,7 +40,6 @@ CPPSRCS = \
nsHTMLTagContent.cpp \
nsHTMLTags.cpp \
nsImageMap.cpp \
- nsInlineFrame.cpp \
nsLeafFrame.cpp \
nsPageFrame.cpp \
nsPlaceholderFrame.cpp \
diff --git a/mozilla/layout/html/base/src/deadnsInlineFrame.h b/mozilla/layout/html/base/src/deadnsInlineFrame.h
deleted file mode 100644
index 8e5eae4f1ea..00000000000
--- a/mozilla/layout/html/base/src/deadnsInlineFrame.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#ifndef nsInlineFrame_h___
-#define nsInlineFrame_h___
-
-#include "nsHTMLContainerFrame.h"
-
-class nsInlineState;
-
-// Inline container class. Does not support being used as a pseudo frame
-class nsInlineFrame : public nsHTMLContainerFrame {
-public:
- static nsresult NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent);
-
- NS_IMETHOD Reflow(nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
-
- NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics);
-
-protected:
- nsInlineFrame(nsIContent* aContent, nsIFrame* aParent);
-
- virtual ~nsInlineFrame();
-
- virtual PRIntn GetSkipSides() const;
-
- void InitializeState(nsIPresContext* aPresContext,
- const nsReflowState& aReflowState,
- nsInlineState& aState);
-
- PRBool DidFitChild(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- nsReflowMetrics& aChildMetrics);
-
- PRBool CanFitChild(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame);
-
- void ComputeFinalSize(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsReflowMetrics& aSize);
-
- PRBool ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex);
-
- PRBool PullUpChildren(nsIPresContext* aPresContext,
- nsInlineState& aState);
-
- nsReflowStatus ReflowUnmappedChildren(nsIPresContext* aPresContext,
- nsInlineState& aState);
-
- void PlaceChild(nsIFrame* aChild,
- PRInt32 aIndex, // in the child frame list
- nsInlineState& aState,
- const nsReflowMetrics& aChildSize,
- const nsSize* aChildMaxElementSize);
-
- PRInt32 RecoverState(nsIPresContext* aCX,
- nsInlineState& aState,
- nsIFrame* aSkipChild);
-
- nsReflowStatus IncrementalReflowFrom(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex);
-
- nsReflowStatus IncrementalReflowAfter(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex);
-
- nsReflowStatus ReflowChild(nsInlineState& aState,
- nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState);
-};
-
-#endif /* nsInlineFrame_h___ */
diff --git a/mozilla/layout/html/base/src/makefile.win b/mozilla/layout/html/base/src/makefile.win
index cc6e08f962f..f218fa0f614 100644
--- a/mozilla/layout/html/base/src/makefile.win
+++ b/mozilla/layout/html/base/src/makefile.win
@@ -23,15 +23,14 @@ REQUIRES=xpcom raptor js
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= \
- nsAbsoluteFrame.cpp \
+ nsAbsoluteFrame.cpp \
nsBRPart.cpp \
- nsBlockFrame.cpp \
nsBodyFrame.cpp \
nsBodyPart.cpp \
nsGlobalVariables.cpp \
nsHRPart.cpp \
nsHTMLAtoms.cpp \
- nsHTMLBase.cpp \
+ nsHTMLBase.cpp \
nsHTMLBullet.cpp \
nsHTMLContainer.cpp \
nsHTMLContainerFrame.cpp \
@@ -39,12 +38,10 @@ CPPSRCS= \
nsHTMLHead.cpp \
nsHTMLIIDs.cpp \
nsHTMLImage.cpp \
- nsHTMLReflowCommand.cpp \
+ nsHTMLReflowCommand.cpp \
nsHTMLTagContent.cpp \
nsImageMap.cpp \
- nsInlineFrame.cpp \
nsLeafFrame.cpp \
- nsLineLayout.cpp \
nsPageFrame.cpp \
nsPlaceholderFrame.cpp \
nsRootPart.cpp \
@@ -57,9 +54,8 @@ CPPSRCS= \
$(NULL)
CPP_OBJS= \
- .\$(OBJDIR)\nsAbsoluteFrame.obj \
+ .\$(OBJDIR)\nsAbsoluteFrame.obj \
.\$(OBJDIR)\nsBRPart.obj \
- .\$(OBJDIR)\nsBlockFrame.obj \
.\$(OBJDIR)\nsBodyFrame.obj \
.\$(OBJDIR)\nsBodyPart.obj \
.\$(OBJDIR)\nsGlobalVariables.obj \
@@ -73,13 +69,11 @@ CPP_OBJS= \
.\$(OBJDIR)\nsHTMLHead.obj \
.\$(OBJDIR)\nsHTMLIIDs.obj \
.\$(OBJDIR)\nsHTMLImage.obj \
- .\$(OBJDIR)\nsHTMLReflowCommand.obj \
+ .\$(OBJDIR)\nsHTMLReflowCommand.obj \
.\$(OBJDIR)\nsHTMLTagContent.obj \
.\$(OBJDIR)\nsHTMLTags.obj \
.\$(OBJDIR)\nsImageMap.obj \
- .\$(OBJDIR)\nsInlineFrame.obj \
.\$(OBJDIR)\nsLeafFrame.obj \
- .\$(OBJDIR)\nsLineLayout.obj \
.\$(OBJDIR)\nsPageFrame.obj \
.\$(OBJDIR)\nsPlaceholderFrame.obj \
.\$(OBJDIR)\nsRootPart.obj \
@@ -93,8 +87,9 @@ CPP_OBJS= \
EXPORTS=nsGlobalVariables.h
-LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
- -I..\..\style\src -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \
+LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
+ -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \
+ -I..\..\style\src -I..\..\..\css\layout\src \
-I..\..\..\base\src
LCFLAGS = \
diff --git a/mozilla/layout/html/base/src/nsBRPart.cpp b/mozilla/layout/html/base/src/nsBRPart.cpp
index b24263bebbc..58703a3a109 100644
--- a/mozilla/layout/html/base/src/nsBRPart.cpp
+++ b/mozilla/layout/html/base/src/nsBRPart.cpp
@@ -20,34 +20,31 @@
#include "nsHTMLTagContent.h"
#include "nsHTMLIIDs.h"
#include "nsIPresContext.h"
-#include "nsBlockFrame.h"
+#include "nsIInlineReflow.h"
+#include "nsCSSLineLayout.h"
#include "nsStyleConsts.h"
#include "nsHTMLAtoms.h"
#include "nsIStyleContext.h"
#include "nsIFontMetrics.h"
#include "nsIRenderingContext.h"
-class BRFrame : public nsFrame, public nsIInlineFrame {
+class BRFrame : public nsFrame, public nsIInlineReflow {
public:
BRFrame(nsIContent* aContent, nsIFrame* aParentFrame);
// nsISupports
- NS_IMETHOD_(nsrefcnt) AddRef(void);
- NS_IMETHOD_(nsrefcnt) Release(void);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
// nsIFrame
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
- NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics);
- // nsIInlineFrame
- NS_IMETHOD ReflowInline(nsLineLayout& aLineLayout,
+ // nsIInlineReflow
+ NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout);
+ NS_IMETHOD InlineReflow(nsCSSLineLayout& aLineLayout,
nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
+ const nsReflowState& aReflowState);
protected:
virtual ~BRFrame();
@@ -63,20 +60,6 @@ BRFrame::~BRFrame()
{
}
-nsrefcnt
-BRFrame::AddRef(void)
-{
- NS_ERROR("not supported");
- return 0;
-}
-
-nsrefcnt
-BRFrame::Release(void)
-{
- NS_ERROR("not supported");
- return 0;
-}
-
NS_IMETHODIMP
BRFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
{
@@ -84,8 +67,8 @@ BRFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
- if (aIID.Equals(kIInlineFrameIID)) {
- *aInstancePtrResult = (void*) ((nsIInlineFrame*)this);
+ if (aIID.Equals(kIInlineReflowIID)) {
+ *aInstancePtrResult = (void*) ((nsIInlineReflow*)this);
return NS_OK;
}
return nsFrame::QueryInterface(aIID, aInstancePtrResult);
@@ -106,9 +89,17 @@ BRFrame::Paint(nsIPresContext& aPresContext,
return NS_OK;
}
-NS_METHOD
-BRFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
+NS_IMETHODIMP
+BRFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
+{
+ aLineLayout.EndTextRun();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BRFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState)
{
if (nsnull != aMetrics.maxElementSize) {
aMetrics.maxElementSize->width = 0;
@@ -116,9 +107,9 @@ BRFrame::GetReflowMetrics(nsIPresContext* aPresContext,
}
// We have no width, but we're the height of the default font
- const nsStyleFont* font =
- (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
- nsIFontMetrics* fm = aPresContext->GetMetricsFor(font->mFont);
+ const nsStyleFont* font = (const nsStyleFont*)
+ mStyleContext->GetStyleData(eStyleStruct_Font);
+ nsIFontMetrics* fm = aLineLayout.mPresContext->GetMetricsFor(font->mFont);
aMetrics.width = 0;
if (nsIFrame::GetShowFrameBorders()) {
@@ -132,45 +123,16 @@ BRFrame::GetReflowMetrics(nsIPresContext* aPresContext,
aMetrics.descent = fm->GetMaxDescent();
NS_RELEASE(fm);
- // Get cached state for containing block frame
- nsBlockReflowState* state =
- nsBlockFrame::FindBlockReflowState(aPresContext, this);
- if (nsnull != state) {
- nsLineLayout* lineLayoutState = state->mCurrentLine;
- if (nsnull != lineLayoutState) {
- lineLayoutState->mReflowResult =
- NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER;
- const nsStyleDisplay* display = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- lineLayoutState->mPendingBreak = display->mBreakType;
- if (NS_STYLE_CLEAR_NONE == lineLayoutState->mPendingBreak) {
- lineLayoutState->mPendingBreak = NS_STYLE_CLEAR_LINE;
- }
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-BRFrame::ReflowInline(nsLineLayout& aLineLayout,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- GetReflowMetrics(aLineLayout.mPresContext, aDesiredSize);
- aStatus = NS_FRAME_COMPLETE;
-
- aLineLayout.mReflowResult =
- NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER;
+ // Return our inline reflow status
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
- aLineLayout.mPendingBreak = display->mBreakType;
- if (NS_STYLE_CLEAR_NONE == aLineLayout.mPendingBreak) {
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_LINE;
+ PRUint32 breakType = display->mBreakType;
+ if (NS_STYLE_CLEAR_NONE == breakType) {
+ breakType = NS_STYLE_CLEAR_LINE;
}
- return NS_OK;
+ return NS_INLINE_REFLOW_BREAK_AFTER |
+ NS_INLINE_REFLOW_MAKE_BREAK_TYPE(breakType);
}
//----------------------------------------------------------------------
diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp
deleted file mode 100644
index bf4fc11255c..00000000000
--- a/mozilla/layout/html/base/src/nsBlockFrame.cpp
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsBlockFrame.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIHTMLContent.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIAnchoredItems.h"
-#include "nsIReflowCommand.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIPtr.h"
-#include "nsHTMLAtoms.h"
-#include "nsHTMLIIDs.h"
-#include "nsHTMLValue.h"
-#include "nsCSSLayout.h"
-#include "nsIView.h"
-
-// XXX what do we do with catastrophic errors (rv < 0)? What is the
-// state of the reflow world after such an error?
-
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-//----------------------------------------------------------------------
-
-void nsBlockBandData::ComputeAvailSpaceRect()
-{
- nsBandTrapezoid* trapezoid = data;
-
- if (count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < count; i++) {
- nsBandTrapezoid* trapezoid = &data[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &data[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availSpace);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availSpace);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availSpace.x = availSpace.XMost();
- }
- availSpace.width = 0;
- }
-}
-
-//----------------------------------------------------------------------
-
-nsBlockReflowState::nsBlockReflowState()
-{
-}
-
-nsBlockReflowState::~nsBlockReflowState()
-{
-}
-
-nsresult
-nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock)
-{
- nsresult rv = NS_OK;
-
- mPresContext = aPresContext;
- mBlock = aBlock;
- mSpaceManager = aSpaceManager;
- mBlockIsPseudo = aBlock->IsPseudoFrame();
- mListPositionOutside = PR_FALSE;
- mCurrentLine = nsnull;
- mPrevKidFrame = nsnull;
- reflowState = &aReflowState;
-
- mX = 0;
- mY = 0;
- mStyleSizeFlags = 0;
- mAvailSize = reflowState->maxSize;
- mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE);
- mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE);
- mMaxElementSizePointer = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
- }
- mKidXMost = 0;
-
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = 0;
- mPrevMarginSynthetic = PR_FALSE;
-
- mNextListOrdinal = -1;
-
- return rv;
-}
-
-// Recover the block reflow state to what it should be if aLine is about
-// to be reflowed. aLine should not be nsnull
-nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
-{
- NS_PRECONDITION(nsnull != aLine, "null parameter");
- nsLineData* prevLine = aLine->mPrevLine;
-
- if (nsnull != prevLine) {
- // Compute the running y-offset, and the available height
- mY = prevLine->mBounds.YMost();
- if (!mUnconstrainedHeight) {
- mAvailSize.height -= mY;
- }
-
- // Compute the kid x-most
- for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
- nscoord xmost = l->mBounds.XMost();
- if (xmost > mKidXMost) {
- mKidXMost = xmost;
- }
- }
-
- // If the previous line is a block, then factor in its bottom margin
- if (prevLine->mIsBlock) {
- const nsStyleSpacing* kidSpacing;
- nsIFrame* kid = prevLine->mFirstChild;
-
- kid->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)kidSpacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kid, kidMargin);
- if (kidMargin.bottom < 0) {
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = -kidMargin.bottom;
- } else {
- mPrevPosBottomMargin = kidMargin.bottom;
- mPrevNegBottomMargin = 0;
- }
- }
- }
-
- return NS_OK;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsBlockFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsBlockFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsBlockFrame::~nsBlockFrame()
-{
- DestroyLines();
- delete mRunInFloaters;
-}
-
-void nsBlockFrame::DestroyLines()
-{
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- mLines = nsnull;
-}
-
-NS_METHOD
-nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
-{
- NS_PRECONDITION(0 != aInstancePtr, "null ptr");
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
- if (aIID.Equals(kBlockFrameCID)) {
- *aInstancePtr = (void*) (this);
- return NS_OK;
- }
- else if (aIID.Equals(kIRunaroundIID)) {
- *aInstancePtr = (void*) ((nsIRunaround*) this);
- return NS_OK;
- }
- else if (aIID.Equals(kIFloaterContainerIID)) {
- *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
- return NS_OK;
- }
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_METHOD
-nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
-{
- aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame)
-{
- nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
- if (nsnull == cf) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
- aContinuingFrame = cf;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::ListTag(FILE* out) const
-{
- if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
- fprintf(out, "*block<");
- nsIAtom* atom = mContent->GetTag();
- if (nsnull != atom) {
- nsAutoString tmp;
- atom->ToString(tmp);
- fputs(tmp, out);
- }
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, ">(%d)@%p", contentIndex, this);
- } else {
- nsHTMLContainerFrame::ListTag(out);
- }
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- NS_RELEASE(view);
- }
-
- // Output the first/last content offset
- fprintf(out, "[%d,%d,%c] ", mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
-
- // Output the children, one line at a time
- if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- aIndent++;
-
- nsLineData* line = mLines;
- while (nsnull != line) {
- line->List(out, aIndent);
- line = line->mNextLine;
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
-
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- nsresult rv = nsHTMLContainerFrame::VerifyTree();
- if (NS_OK != rv) {
- return rv;
- }
- rv = VerifyLines(PR_TRUE);
- return rv;
-#else
- return NS_OK;
-#endif
-}
-
-#ifdef NS_DEBUG
-nsresult
-nsBlockFrame::VerifyLines(PRBool aFinalCheck) const
-{
- nsresult rv = NS_OK;
-
- // Make sure that the list of children agrees with our child count.
- // If this is not the case then the child list and the line list are
- // not properly arranged.
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(mChildCount == len, "bad child list");
-
- // Verify that our lines are correctly setup
- PRInt32 offset = mFirstContentOffset;
- PRInt32 lineChildCount = 0;
- nsLineData* line = mLines;
- nsLineData* prevLine = nsnull;
- while (nsnull != line) {
- if (aFinalCheck) {
- NS_ASSERTION(((offset == line->mFirstContentOffset) &&
- (line->mFirstContentOffset <= line->mLastContentOffset)),
- "bad line mFirstContentOffset");
- NS_ASSERTION(line->mLastContentOffset <= mLastContentOffset,
- "bad line mLastContentOffset");
- offset = line->mLastContentOffset;
- if (line->mLastContentIsComplete) {
- offset++;
- }
- }
- lineChildCount += line->mChildCount;
- rv = line->Verify(aFinalCheck);
- if (NS_OK != rv) {
- return rv;
- }
- prevLine = line;
- line = line->mNextLine;
- }
- if (aFinalCheck && (nsnull != prevLine)) {
- NS_ASSERTION(prevLine->mLastContentOffset == mLastContentOffset,
- "bad mLastContentOffset");
- NS_ASSERTION(prevLine->mLastContentIsComplete == mLastContentIsComplete,
- "bad mLastContentIsComplete");
- }
- NS_ASSERTION(lineChildCount == mChildCount, "bad line counts");
-
- return rv;
-}
-#endif
-
-//----------------------------------------------------------------------
-
-// Remove a next-in-flow from from this block's list of lines
-
-// XXX problems here:
-// 1. we always have to start from the first line: slow!
-// 2. we can avoid this when the child is not the last child in a line
-
-void
-nsBlockFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
- // When a reflow indicates completion it's possible that
- // next-in-flows were just removed. We have to remove them from any
- // nsLineData's that follow the current line.
- nsLineData* line = mLines;
- while (nsnull != line) {
- if (line->mFirstChild == aNextInFlow) {
- // Remove child from line.
- if (0 == --line->mChildCount) {
- line->mFirstChild = nsnull;
- }
- else {
- // Fixup the line
- nsIFrame* nextKid;
- aNextInFlow->GetNextSibling(nextKid);
- line->mFirstChild = nextKid;
- nextKid->GetContentIndex(line->mFirstContentOffset);
- }
- break;
- }
- line = line->mNextLine;
- }
-}
-
-nsresult
-nsBlockFrame::ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(aLineLayout, aDesiredSize, aReflowState, aStatus);
- }
- else {
- aKidFrame->Reflow(aLineLayout.mPresContext, aDesiredSize, aReflowState,
- aStatus);
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
- nsIRunaround* reflowRunaround;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- // Get the band for this y-offset and see whether there are any floaters
- // that have changed the left/right edges.
- //
- // XXX In order to do this efficiently we should move all this code to
- // nsBlockFrame since it already has band data, and it's probably the only
- // one who calls this routine anyway
- nsBandData bandData;
- nsBandTrapezoid trapezoids[12];
- nsBandTrapezoid* trapezoid = trapezoids;
- nsRect availBand;
-
- bandData.trapezoids = trapezoids;
- bandData.size = 12;
- aSpaceManager->GetBandData(0, aReflowState.maxSize, bandData);
-
- if (bandData.count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < bandData.count; i++) {
- nsBandTrapezoid* trapezoid = &trapezoids[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &trapezoids[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availBand);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availBand);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availBand.x = availBand.XMost();
- }
- availBand.width = 0;
- }
-
- // Does the child frame support interface nsIRunaround?
- if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
- (void**)&reflowRunaround)) {
- // Yes, the child frame wants to interact directly with the space
- // manager.
- reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState,
- aDesiredRect, aStatus);
- } else {
- // No, use interface nsIFrame instead.
- if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
- if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) {
- // There are left/right floaters.
- aReflowState.maxSize.width = availBand.width;
- }
- }
-
- // XXX FIX ME
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-
- // Return the desired rect
- aDesiredRect.x = availBand.x;
- aDesiredRect.y = 0;
- aDesiredRect.width = aDesiredSize.width;
- aDesiredRect.height = aDesiredSize.height;
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
-
- return NS_OK;
-}
-
-nsLineData*
-nsBlockFrame::CreateLineForOverflowList(nsIFrame* aOverflowList)
-{
- nsLineData* newLine = new nsLineData();
- if (nsnull != newLine) {
- nsIFrame* kid = aOverflowList;
- newLine->mFirstChild = kid;
- kid->GetContentIndex(newLine->mFirstContentOffset);
- newLine->mLastContentOffset = -1;
- newLine->mLastContentIsComplete = PRPackedBool(0x255);
- PRInt32 kids = 0;
- while (nsnull != kid) {
- kids++;
- kid->GetNextSibling(kid);
- }
- newLine->mChildCount = kids;
- }
- return newLine;
-}
-
-void
-nsBlockFrame::DrainOverflowList()
-{
- nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
- if (nsnull != prevBlock) {
- nsIFrame* overflowList = prevBlock->mOverflowList;
- if (nsnull != overflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- NS_ASSERTION(nsnull == mLines, "bad overflow list");
-
- // Create a line to hold the entire overflow list
- nsLineData* newLine = CreateLineForOverflowList(overflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(overflowList);
- prevBlock->mOverflowList = nsnull;
-
- // The new line is the first line
- mLines = newLine;
- }
- }
-
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild,
- "overflow list but no mapped children");
-
- // Create a line to hold the overflow list
- nsLineData* newLine = CreateLineForOverflowList(mOverflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
-
- // The new line is appended after our other lines
- nsLineData* prevLine = nsnull;
- nsLineData* line = mLines;
- while (nsnull != line) {
- prevLine = line;
- line = line->mNextLine;
- }
- if (nsnull == prevLine) {
- mLines = newLine;
- }
- else {
- prevLine->mNextLine = newLine;
- newLine->mPrevLine = prevLine;
- }
- }
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_FALSE);
- }
-#endif
-}
-
-void
-nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint8 aBreakType)
-{
- for (;;) {
- if (aState.mCurrentBand.count <= 1) {
- // No floaters in this band therefore nothing to clear
- break;
- }
-
- // Find the Y coordinate to clear to
- nscoord clearYMost = aState.mY;
- nsRect tmp;
- PRInt32 i;
- for (i = 0; i < aState.mCurrentBand.count; i++) {
- const nsStyleDisplay* display;
- nsBandTrapezoid* trapezoid = &aState.mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 fn, numFrames = trapezoid->frames->Count();
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
-
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- }
-
- if (clearYMost == aState.mY) {
- // Nothing to clear
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::ClearFloaters: mY=%d clearYMost=%d\n",
- aState.mY, clearYMost));
-
- aState.mY = clearYMost + 1;
-
- // Get a new band
- GetAvailableSpace(aState, aState.mY);
- }
-}
-
-nsresult
-nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine)
-{
- // Before we place the line, make sure that it will fit in it's new
- // location. It always fits if the height isn't constrained or it's
- // the first line.
- if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
- if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
- // The line will not fit
- return PushLines(aState, aLine);
- }
- }
-
- // When the line is finally placed then we know that the child
- // frames have a stable location. This means that we can DidReflow
- // them marking them done. Note that when we are paginated this
- // optimization cannot be done because this may be a nested block
- // that will be pushed to a new page by the containing block and the
- // nested block can't know that during its reflow.
- // XXX and actually, this only always works for the block which is a
- // child of the body.
- if (!aState.mPresContext->IsPaginated()) {
- nsIAtom* tag = mContent->GetTag();
- if (nsHTMLAtoms::body == tag) {
- nsIFrame* child = aLine->mFirstChild;
- for (PRInt32 i = aLine->mChildCount; --i >= 0; ) {
- nsFrameState state;
- child->GetFrameState(state);
- if (NS_FRAME_IN_REFLOW & state) {
- child->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
- }
- child->GetNextSibling(child);
- }
-
- // Paint this portion of ourselves
- if (!aLine->mBounds.IsEmpty()) {
- Invalidate(aLine->mBounds);
- }
- }
- NS_IF_RELEASE(tag);
- }
-
- // Consume space and advance running values
- aState.mY += aLine->mBounds.height;
- if (nsnull != aState.mMaxElementSizePointer) {
- nsSize* maxSize = aState.mMaxElementSizePointer;
- if (aLineLayout.mState.mMaxElementSize.width > maxSize->width) {
- maxSize->width = aLineLayout.mState.mMaxElementSize.width;
- }
- if (aLineLayout.mState.mMaxElementSize.height > maxSize->height) {
- maxSize->height = aLineLayout.mState.mMaxElementSize.height;
- }
- }
- nscoord xmost = aLine->mBounds.XMost();
- if (xmost > aState.mKidXMost) {
- aState.mKidXMost = xmost;
- }
-
- // Process any pending break operations
- switch (aLineLayout.mPendingBreak) {
- default:
- break;
- case NS_STYLE_CLEAR_LEFT:
- case NS_STYLE_CLEAR_RIGHT:
- case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
- ClearFloaters(aState, aLineLayout.mPendingBreak);
- break;
- }
- // XXX for now clear the pending break; this is where support for
- // page breaks or column breaks could be partially handled.
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- // Any below current line floaters to place?
- // XXX We really want to know whether this is the initial reflow (reflow
- // unmapped) or a subsequent reflow in which case we only need to offset
- // the existing floaters...
- if (aState.mPendingFloaters.Count() > 0) {
- if (nsnull == aLine->mFloaters) {
- aLine->mFloaters = new nsVoidArray;
- }
- aLine->mFloaters->operator=(aState.mPendingFloaters);
- aState.mPendingFloaters.Clear();
- }
-
- if (nsnull != aLine->mFloaters) {
- PlaceBelowCurrentLineFloaters(aState, aLine->mFloaters, aState.mY);
- // XXX Factor in the height of the floaters as well when considering
- // whether the line fits.
- // The default policy is that if there isn't room for the floaters then
- // both the line and the floaters are pushed to the next-in-flow...
- }
-
- if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
- // The current y coordinate is now past our available space
- // rectangle. Get a new band of space.
- GetAvailableSpace(aState, aState.mY);
- }
-
- return NS_LINE_LAYOUT_COMPLETE;
-}
-
-// aY has borderpadding.top already factored in
-nsresult
-nsBlockFrame::GetAvailableSpace(nsBlockReflowState& aState, nscoord aY)
-{
- nsresult rv = NS_OK;
-
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Fill in band data for the specific Y coordinate
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->GetBandData(aY, aState.mAvailSize, aState.mCurrentBand);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
- aState.mCurrentBand.ComputeAvailSpaceRect();
-
- aState.mCurrentBand.availSpace.MoveBy(aState.mBorderPadding.left,
- aState.mY);
-
- return rv;
-}
-
-// Give aLine and any successive lines to the block's next-in-flow; if
-// we don't have a next-in-flow then push all the children onto our
-// overflow list.
-nsresult
-nsBlockFrame::PushLines(nsBlockReflowState& aState, nsLineData* aLine)
-{
- PRInt32 i;
-
- // Split our child-list in two; revert our last content offset and
- // completion status to the previous line.
- nsLineData* prevLine = aLine->mPrevLine;
- NS_PRECONDITION(nsnull != prevLine, "pushing first line");
- nsIFrame* prevKidFrame = prevLine->mFirstChild;
- for (i = prevLine->mChildCount - 1; --i >= 0; ) {
- prevKidFrame->GetNextSibling(prevKidFrame);
- }
-#ifdef NS_DEBUG
- nsIFrame* nextFrame;
- prevKidFrame->GetNextSibling(nextFrame);
- NS_ASSERTION(nextFrame == aLine->mFirstChild, "bad line list");
-#endif
- prevKidFrame->SetNextSibling(nsnull);
- prevLine->mNextLine = nsnull;
- mLastContentOffset = prevLine->mLastContentOffset;
- mLastContentIsComplete = prevLine->mLastContentIsComplete;
-
- // Push children to our next-in-flow if we have, or to our overflow list
- nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow;
- PRInt32 pushCount = 0;
- if (nsnull == nextInFlow) {
- // Place children on the overflow list
- mOverflowList = aLine->mFirstChild;
-
- // Destroy the lines
- nsLineData* line = aLine;
- while (nsnull != line) {
- pushCount += line->mChildCount;
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- }
- else {
- aLine->mPrevLine = nsnull;
-
- // Pass on the children to our next-in-flow
- nsLineData* line = aLine;
- prevLine = line;
- nsIFrame* lastKid = aLine->mFirstChild;
- nsIFrame* kid = lastKid;
- while (nsnull != line) {
- i = line->mChildCount;
- pushCount += i;
- NS_ASSERTION(kid == line->mFirstChild, "bad line list");
- while (--i >= 0) {
- kid->SetGeometricParent(nextInFlow);
- nsIFrame* contentParent;
- kid->GetContentParent(contentParent);
- if (this == contentParent) {
- kid->SetContentParent(nextInFlow);
- }
- lastKid = kid;
- kid->GetNextSibling(kid);
- }
- prevLine = line;
- line = line->mNextLine;
- }
-
- // Join the two line lists
- nsLineData* nextInFlowLine = nextInFlow->mLines;
- if (nsnull != nextInFlowLine) {
- lastKid->SetNextSibling(nextInFlowLine->mFirstChild);
- nextInFlowLine->mPrevLine = prevLine;
- }
- nsIFrame* firstKid = aLine->mFirstChild;
- prevLine->mNextLine = nextInFlowLine;
- nextInFlow->mLines = aLine;
- nextInFlow->mFirstChild = firstKid;
- nextInFlow->mChildCount += pushCount;
- firstKid->GetContentIndex(nextInFlow->mFirstContentOffset);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- nextInFlow->VerifyLines(PR_FALSE);
- }
-#endif
- }
- mChildCount -= pushCount;
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return NS_LINE_LAYOUT_NOT_COMPLETE;
-}
-
-nsresult
-nsBlockFrame::ReflowMapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // See if we have any run-in floaters to place
- if (nsnull != mRunInFloaters) {
- PlaceBelowCurrentLineFloaters(aState, mRunInFloaters, aState.mY);
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- nsLineData* line = mLines;
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != line) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);/* XXX move out of loop */
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-// XXX This is a short-term hack. It assumes that the caller has already recovered
-// the state, and that some space has been retrieved from the space manager...
-nsresult
-nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != aLine) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, aLine);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, aLine);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = aLine->mLastContentOffset;
- mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
- aLine = aLine->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // If we have no children and we have a prev-in-flow then we need to
- // pick up where it left off. If we have children, e.g. we're being
- // resized, then our content offset will have already been set
- // correctly.
- nsIFrame* kidPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsBlockFrame* prev = (nsBlockFrame*) mPrevInFlow;
- mFirstContentOffset = prev->NextChildOffset();// XXX Is this necessary?
- if (PR_FALSE == prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
-
- // Get to the last line where the new content may be added
- nsLineData* line = nsnull;
- nsLineData* prevLine = nsnull;
- if (nsnull != mLines) {
- line = mLines;
- while (nsnull != line->mNextLine) {
- line = line->mNextLine;
- }
- prevLine = line->mPrevLine;
-
- // If the last line is not complete then kidPrevInFlow should be
- // set to the last-line's last child.
- if (!line->mLastContentIsComplete) {
- kidPrevInFlow = line->GetLastChild();
- }
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- // Now reflow the new content until we are out of new content or out
- // of vertical space.
- PRInt32 kidIndex = NextChildOffset();
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- PRInt32 contentChildCount = mContent->ChildCount();
- while (kidIndex < contentChildCount) {
- if (nsnull == line) {
- if (!MoreToReflow(aState)) {
- break;
- }
- line = new nsLineData();
- if (nsnull == line) {
- rv = NS_ERROR_OUT_OF_MEMORY;
- goto done;
- }
- line->mFirstContentOffset = kidIndex;
- }
-
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Add line to the block; do this before placing the line in case
- // PushLines is needed.
- if (nsnull == prevLine) {
- // For the first line, initialize mFirstContentOffset
- mFirstContentOffset = line->mFirstContentOffset;
- mFirstChild = line->mFirstChild;
- mLines = line;
- }
- else {
- prevLine->mNextLine = line;
- line->mPrevLine = prevLine;
- }
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
- kidIndex = lineLayout.mState.mKidIndex;
- kidPrevInFlow = lineLayout.mKidPrevInFlow;
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- prevLine = line;
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
- if (aState.mBlockIsPseudo) {
- PropagateContentOffsets();
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState)
-{
- nsresult rv;
- rv = aState.Initialize(aPresContext, aSpaceManager,
- aReflowState, aMaxElementSize, this);
-
- // Apply border and padding adjustments for regular frames only
- if (!aState.mBlockIsPseudo) {
- const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStylePosition* myPosition = (const nsStylePosition*)
- mStyleContext->GetStyleData(eStyleStruct_Position);
-
- mySpacing->CalcBorderPaddingFor(this, aState.mBorderPadding);
- aState.mY = aState.mBorderPadding.top;
- aState.mX = aState.mBorderPadding.left;
-
- if (aState.mUnconstrainedWidth) {
- // If our width is unconstrained don't bother futzing with the
- // available width/height because they don't matter - we are
- // going to get reflowed again.
- aState.mDeltaWidth = NS_UNCONSTRAINEDSIZE;
- }
- else {
- // When we are constrained we need to apply the width/height
- // style properties. When we have a width/height it applies to
- // the content width/height of our box. The content width/height
- // doesn't include the border+padding so we have to add that in
- // instead of subtracting it out of our maxsize.
- nscoord lr =
- aState.mBorderPadding.left + aState.mBorderPadding.right;
-
- // Get and apply the stylistic size. Note: do not limit the
- // height until we are done reflowing.
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
- aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aState.mAvailSize.width = aState.mStyleSize.width + lr;
- }
- else {
- aState.mAvailSize.width -= lr;
- }
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
- }
- else {
- aState.mBorderPadding.SizeTo(0, 0, 0, 0);
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
-
- // Setup initial list ordinal value
- nsIAtom* tag = mContent->GetTag();
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- nsHTMLValue value;
- if (eContentAttr_HasValue ==
- ((nsIHTMLContent*)mContent)->GetAttribute(nsHTMLAtoms::start, value)) {
- if (eHTMLUnit_Integer == value.GetUnit()) {
- aState.mNextListOrdinal = value.GetIntValue();
- }
- }
- }
- NS_RELEASE(tag);
-
- // Setup list flags in block reflow state if this block is a list
- // item.
- const nsStyleDisplay* myDisplay = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_DISPLAY_LIST_ITEM == myDisplay->mDisplay) {
- const nsStyleList* myList = (const nsStyleList*)
- mStyleContext->GetStyleData(eStyleStruct_List);
- if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == myList->mListStylePosition) {
- aState.mListPositionOutside = PR_TRUE;
- }
- }
-
- return rv;
-}
-
-PRBool
-nsBlockFrame::MoreToReflow(nsBlockReflowState& aState)
-{
- PRBool rv = PR_FALSE;
- if (NextChildOffset() < mContent->ChildCount()) {
- rv = PR_TRUE;
- }
- return rv;
-}
-
-nsBlockReflowState*
-nsBlockFrame::FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame)
-{
- nsBlockReflowState* state = nsnull;
- if (nsnull != aFrame) {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
- while (nsnull != parent) {
- nsBlockFrame* block;
- nsresult rv = parent->QueryInterface(kBlockFrameCID, (void**) &block);
- if (NS_OK == rv) {
- nsIPresShell* shell = aPresContext->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(block);
- NS_RELEASE(shell);
- break;
- }
- parent->GetGeometricParent(parent);
- }
- }
- return state;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer)
-{
- return nsHTMLContainerFrame::ContentAppended(aShell, aPresContext, aContainer);
-}
-
-NS_METHOD
-nsBlockFrame::ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- return nsHTMLContainerFrame::ContentInserted(aShell, aPresContext, aContainer,
- aChild, aIndexInParent);
-}
-
-NS_METHOD
-nsBlockFrame::ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-NS_METHOD
-nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-// XXX if there is nothing special going on here, then remove this
-// implementation and let nsFrame do it.
-NS_METHOD
-nsBlockFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nsresult rv = NS_OK;
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = mRect.height;
- aMetrics.descent = 0;
- return rv;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PreReflowCheck();
- }
-#endif
-
- nsBlockReflowState state;
- nsresult rv = NS_OK;
-
- if (eReflowReason_Initial == aReflowState.reason) {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 == (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
- else {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 != (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- }
-
- aStatus = NS_FRAME_COMPLETE;
- rv = InitializeState(aPresContext, aSpaceManager, aReflowState,
- aDesiredSize.maxElementSize, state);
-
- NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d",
- aReflowState.reason, state.mDeltaWidth));
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- nsIPresShell* shell = state.mPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Is the reflow command target at us?
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
- if (this == target) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- if (nsIReflowCommand::FrameAppended == type) {
- nsLineData* lastLine = LastLine();
-
- // Restore the state
- if (nsnull != lastLine) {
- state.RecoverState(lastLine);
- }
-
- // Reflow unmapped children
- PRInt32 kidIndex = NextChildOffset();
- PRInt32 contentChildCount = mContent->ChildCount();
- if (kidIndex == contentChildCount) {
- // There is nothing to do here
- if (nsnull != lastLine) {
- state.mY = lastLine->mBounds.YMost();
- }
- }
- else {
- rv = ReflowUnmapped(state);
- }
- } else {
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- }
- } else {
- // The command is passing through us. Get the next frame in the
- // reflow chain
- nsIFrame* nextFrame;
- aReflowState.reflowCommand->GetNext(nextFrame);
-
- // Restore our state as if nextFrame is the next frame to reflow
- nsLineData* line = FindLine(nextFrame);
- state.RecoverState(line);
-
- // Get some available space to start reflowing with
- GetAvailableSpace(state, state.mY);
-
- // Reflow the affected line
- nsLineLayout lineLayout(state);
-
- state.mCurrentLine = &lineLayout;
- lineLayout.Initialize(state, line);
-
- // Have the line handle the incremental reflow
- nsRect oldBounds = line->mBounds;
- rv = lineLayout.IncrementalReflowFromChild(aReflowState.reflowCommand,
- nextFrame);
-
- // Now place the line. It's possible it won't fit
- rv = PlaceLine(state, lineLayout, line);
- // XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- state.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
-
- // Now figure out what to do with the frames that follow
- rv = IncrementalReflowAfter(state, line, rv, oldBounds);
- }
- }
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- } else {
- nsresult rv = NS_OK;
- nsIPresShell* shell = aPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Check for an overflow list
- DrainOverflowList();
-
- if (nsnull != mLines) {
- rv = ReflowMapped(state);
- }
-
- if (NS_OK == rv) {
- if ((nsnull != mLines) && (state.mAvailSize.height <= 0)) {
- // We are out of space
- }
- if (MoreToReflow(state)) {
- rv = ReflowUnmapped(state);
- }
- }
-
-#ifdef NS_DEBUG
- if (0 != mContent->ChildCount()) {
- NS_ASSERTION(nsnull != mLines, "reflowed zero children");
- }
-#endif
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsBlockFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredRect.width, aDesiredRect.height));
- return rv;
-}
-
-nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
-{
- // Find the line that contains the aFrame
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsIFrame* child = line->mFirstChild;
- for (PRInt32 count = line->mChildCount; count > 0; count--) {
- if (child == aFrame) {
- return line;
- }
-
- child->GetNextSibling(child);
- }
-
- // Move to the next line
- line = line->mNextLine;
- }
-
- return nsnull;
-}
-
-nsLineData* nsBlockFrame::LastLine()
-{
- nsLineData* lastLine = mLines;
-
- // Get the last line
- if (nsnull != lastLine) {
- while (nsnull != lastLine->mNextLine) {
- lastLine = lastLine->mNextLine;
- }
- }
-
- return lastLine;
-}
-
-nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds)
-{
- // Now just reflow all the lines that follow...
- // XXX Obviously this needs to be more efficient
- return ReflowMappedFrom(aState, aLine->mNextLine);
-}
-
-void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect)
-{
- aDesiredRect.x = 0;
- aDesiredRect.y = 0;
-
- // Special check for zero sized content: If our content is zero
- // sized then we collapse into nothingness.
- if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
- (0 == aState.mY - aState.mBorderPadding.top)) {
- aDesiredRect.width = 0;
- aDesiredRect.height = 0;
- }
- else {
- aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
- if (!aState.mUnconstrainedWidth) {
- // Make sure we're at least as wide as the max size we were given
- nscoord maxWidth = aState.mAvailSize.width + aState.mBorderPadding.left +
- aState.mBorderPadding.right;
- if (aDesiredRect.width < maxWidth) {
- aDesiredRect.width = maxWidth;
- }
- }
- aState.mY += aState.mBorderPadding.bottom;
- nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
- aState.mPrevNegBottomMargin;
- if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
- // It's possible that we don't have room for the last bottom
- // margin (the last bottom margin is the margin following a block
- // element that we contain; it isn't applied immediately because
- // of the margin collapsing logic). This can happen when we are
- // reflowed in a limited amount of space because we don't know in
- // advance what the last bottom margin will be.
- nscoord maxY = aMaxSize.height;
- if (aState.mY + lastBottomMargin > maxY) {
- lastBottomMargin = maxY - aState.mY;
- if (lastBottomMargin < 0) {
- lastBottomMargin = 0;
- }
- }
- }
- aState.mY += lastBottomMargin;
- aDesiredRect.height = aState.mY;
-
- if (!aState.mBlockIsPseudo) {
- // Clamp the desired rect height when style height applies
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredRect.height = aState.mBorderPadding.top +
- aState.mStyleSize.height + aState.mBorderPadding.bottom;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-
-void nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame)
-{
- // Compute the available space for the floater. Use the default
- // 'auto' width and height values
- nsSize kidAvailSize(0, NS_UNCONSTRAINEDSIZE);
- nsSize styleSize;
- PRIntn styleSizeFlags = nsCSSLayout::GetStyleSize(aPresContext, *aState.reflowState,
- styleSize);
-
- // XXX The width and height are for the content area only. Add in space for
- // border and padding
- if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
- kidAvailSize.width = styleSize.width;
- }
- if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
- kidAvailSize.height = styleSize.height;
- }
-
- // Resize reflow the anchored item into the available space
- // XXX Check for complete?
- nsReflowMetrics desiredSize(nsnull);
- nsReflowState reflowState(aFloaterFrame, *aState.reflowState, kidAvailSize,
- eReflowReason_Initial);
- nsReflowStatus status;
-
- aFloaterFrame->WillReflow(*aPresContext);
- aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status);
- aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
-
- aFloaterFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
-}
-
-PRBool
-nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
-
- if (nsnull != state) {
- // Get the frame associated with the space manager, and get its
- // nsIAnchoredItems interface
- nsIFrame* frame = state->mSpaceManager->GetFrame();
- nsIAnchoredItems* anchoredItems = nsnull;
-
- frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
- NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
- if (nsnull != anchoredItems) {
- anchoredItems->AddAnchoredItem(aFloater,
- nsIAnchoredItems::anHTMLFloater,
- this);
-
- // Reflow the floater
- ReflowFloater(aPresContext, *state, aFloater);
-
- // Determine whether we place it at the top or we place it below the
- // current line
- if (IsLeftMostChild(aPlaceholder)) {
- if (nsnull == mRunInFloaters) {
- mRunInFloaters = new nsVoidArray;
- }
- mRunInFloaters->AppendElement(aPlaceholder);
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- } else {
- // Add the placeholder to our to-do list
- state->mPendingFloaters.AppendElement(aPlaceholder);
- }
- return PR_TRUE;
- }
- }
-
- return PR_FALSE;
-}
-
-// XXX Deprecated
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
-#if 0
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
- if (nsnull != state) {
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- }
-#endif
-}
-
-PRBool
-nsBlockFrame::IsLeftMostChild(nsIFrame* aFrame)
-{
- do {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
-
- // See if there are any non-zero sized child frames that precede
- // aFrame in the child list
- nsIFrame* child;
- parent->FirstChild(child);
- while ((nsnull != child) && (aFrame != child)) {
- nsSize size;
-
- // Is the child zero-sized?
- child->GetSize(size);
- if ((size.width > 0) || (size.height > 0)) {
- // We found a non-zero sized child frame that precedes aFrame
- return PR_FALSE;
- }
- child->GetNextSibling(child);
- }
-
- // aFrame is the left-most non-zero sized frame in its geometric parent.
- // Walk up one level and check that its parent is left-most as well
- aFrame = parent;
- } while (aFrame != this);
- return PR_TRUE;
-}
-
-// Used when placing run-in floaters (floaters displayed at the top of the
-// block as supposed to below the current line)
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState)
-{
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Get the type of floater
- const nsStyleDisplay* floaterDisplay;
- aFloater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay);
-
- // Commit some space in the space manager, and adjust our current
- // band of available space.
- nsRect region;
- aFloater->GetRect(region);
- region.y = aState.mY;
- if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
- region.x = aState.mX;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats,
- "bad float type");
- region.x = aState.mCurrentBand.availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->AddRectRegion(aFloater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- aFloater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Update the band of available space to reflect space taken up by
- // the floater
- GetAvailableSpace(aState, aState.mY);
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-// XXX It's unclear what coordinate space aY is in. Is it relative to the
-// upper-left origin of the containing block, or relative to aState.mY?
-void
-nsBlockFrame::PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY)
-{
- NS_PRECONDITION(aFloaterList->Count() > 0, "no floaters");
-
- nsISpaceManager* sm = aState.mSpaceManager;
- nsBlockBandData* bd = &aState.mCurrentBand;
-
- // XXX Factor this code with PlaceFloater()...
- PRInt32 numFloaters = aFloaterList->Count();
- for (PRInt32 i = 0; i < numFloaters; i++) {
- nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)aFloaterList->ElementAt(i);
- nsIFrame* floater = placeholderFrame->GetAnchoredItem();
- nsRect region;
-
- // Get the band of available space
- // XXX This is inefficient to do this inside the loop...
- GetAvailableSpace(aState, aY);
-
- // Get the type of floater
- const nsStyleDisplay* sd;
- floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)sd);
-
- floater->GetRect(region);
- // XXX GetAvailableSpace() is translating availSpace by aState.mY...
- region.y = bd->availSpace.y - aState.mY;
- if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
- region.x = bd->availSpace.x;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
- region.x = bd->availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- // XXX Temporary incremental hack
- sm->RemoveRegion(floater);
- sm->AddRectRegion(floater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- floater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
- }
-
- // Pass on updated available space to the current line
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- GetAvailableSpace(aState, aY);
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineData*
-nsBlockFrame::GetFirstLine()
-{
- return mLines;
-}
-
-PRIntn
-nsBlockFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_TOP;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_BOTTOM;
- }
- return skip;
-}
diff --git a/mozilla/layout/html/base/src/nsBlockFrame.h b/mozilla/layout/html/base/src/nsBlockFrame.h
deleted file mode 100644
index 77b3e0ee8ff..00000000000
--- a/mozilla/layout/html/base/src/nsBlockFrame.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#ifndef nsBlockFrame_h___
-#define nsBlockFrame_h___
-
-#include "nsHTMLContainerFrame.h"
-#include "nsIFloaterContainer.h"
-#include "nsIRunaround.h"
-#include "nsISpaceManager.h"
-#include "nsLineLayout.h"
-#include "nsVoidArray.h"
-
-struct nsMargin;
-struct nsStyleDisplay;
-struct nsStyleFont;
-struct nsStyleText;
-class nsBlockFrame;
-struct nsBandData;
-
-struct nsBlockBandData : public nsBandData {
- // Trapezoids used during band processing
- nsBandTrapezoid data[12];
-
- // Bounding rect of available space between any left and right floaters
- nsRect availSpace;
-
- nsBlockBandData() {
- size = 12;
- trapezoids = data;
- }
-
- /**
- * Computes the bounding rect of the available space, i.e. space
- * between any left and right floaters Uses the current trapezoid
- * data, see nsISpaceManager::GetBandData(). Also updates member
- * data "availSpace".
- */
- void ComputeAvailSpaceRect();
-};
-
-struct nsBlockReflowState {
- nsBlockReflowState();
- ~nsBlockReflowState();
-
- nsresult Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock);
-
- nsresult RecoverState(nsLineData* aLine);
-
- nsIPresContext* mPresContext;
-
- nsBlockFrame* mBlock;
- PRBool mBlockIsPseudo;
-
- // Current line being reflowed
- nsLineLayout* mCurrentLine;
-
- // Previous line's last child frame
- nsIFrame* mPrevKidFrame;
-
- // Layout position information
- nscoord mX;
- nscoord mY;
- nsSize mAvailSize;
- nsSize mStyleSize;
- PRIntn mStyleSizeFlags;
- PRPackedBool mUnconstrainedWidth;
- PRPackedBool mUnconstrainedHeight;
- nsSize* mMaxElementSizePointer;
- nscoord mKidXMost;
- const nsReflowState* reflowState;
-
- // Change in width since last reflow
- nscoord mDeltaWidth;
-
- // Bottom margin information from the previous line (only when
- // the previous line contains a block element)
- nscoord mPrevNegBottomMargin;
- nscoord mPrevPosBottomMargin;
- PRBool mPrevMarginSynthetic;
-
- // Block frame border+padding information
- nsMargin mBorderPadding;
-
- // Space manager and current band information
- nsISpaceManager* mSpaceManager;
- nsBlockBandData mCurrentBand;
-
- // Array of floaters to place below current line
- nsVoidArray mPendingFloaters;
-
- // The next list ordinal for counting list bullets
- PRInt32 mNextListOrdinal;
- PRBool mListPositionOutside;
-};
-
-//----------------------------------------------------------------------
-
-/* 94e8e410-de21-11d1-89bf-006008911b81 */
-#define NS_BLOCKFRAME_CID \
- {0x94e8e410, 0xde21, 0x11d1, {0x89, 0xbf, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
-
-/**
- * Block Reflow
- *
- * The block frame reflow machinery performs "2D" layout. Inline
- * elements are flowed into logical lines (left to right or right to
- * left) and the lines are stacked vertically. nsLineLayout is used
- * for this part of the process. Block elements are flowed directly by
- * the block reflow logic after flushing out any preceeding line.
- *
- * During reflow, the block frame will make available to child frames
- * it's reflow state using the presentation shell's cached data
- * mechanism.
- *
- *
Reflowing Mapped Content
- * Pullup
- * Reflowing Unmapped Content
- * Content Insertion Handling
- * Content Deletion Handling
- * Style Change Handling
- *
- * Assertions
- * mLastContentIsComplete always reflects the state of the last
- * child frame on our chlid list.
- */
-
-// XXX we don't use nsContainerFrame mOverFlowList!!! wasted memory
-
-class nsBlockFrame : public nsHTMLContainerFrame,
- public nsIRunaround,
- public nsIFloaterContainer
-{
-public:
- /**
- * Create a new block frame that maps the given piece of content.
- */
- static nsresult NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent);
-
- // nsISupports
- NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
-
- // nsIFrame
- NS_IMETHOD ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer);
- NS_IMETHOD ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent);
- NS_IMETHOD ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent);
- NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent);
- NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics);
- NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
- NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame);
- NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
- NS_IMETHOD ListTag(FILE* out) const;
- NS_IMETHOD VerifyTree() const;
-
- // nsIRunaround
- NS_IMETHOD Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus);
-
- // nsIFloaterContainer
- virtual PRBool AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder);
- virtual void PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder);
-
- // nsBlockFrame
- nsresult ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
-
- nsresult ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus);
-
- static nsBlockReflowState* FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame);
-
-protected:
- nsBlockFrame(nsIContent* aContent, nsIFrame* aParent);
-
- virtual ~nsBlockFrame();
-
- virtual PRIntn GetSkipSides() const;
-
- virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow);
-
- nsresult InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState);
-
- void ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect);
-
- nsLineData* LastLine();
- nsLineData* FindLine(nsIFrame* aFrame);
-
- nsresult IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds);
-
- void DestroyLines();
-
- void DrainOverflowList();
-
- nsLineData* CreateLineForOverflowList(nsIFrame* aOverflowList);
-
-#ifdef NS_DEBUG
- nsresult VerifyLines(PRBool aFinalCheck) const;
-#endif
-
- void ClearFloaters(nsBlockReflowState& aState,
- PRUint8 aBreakType);
-
- nsresult PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine);
-
- PRBool IsLeftMostChild(nsIFrame* aFrame);
-
- void PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState);
- void PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY);
-
- nsresult GetAvailableSpace(nsBlockReflowState& aState, nscoord aY);
-
- PRBool MoreToReflow(nsBlockReflowState& aState);
-
- nsresult PushLines(nsBlockReflowState& aState,
- nsLineData* aLine);
-
- nsresult ReflowMapped(nsBlockReflowState& aState);
- nsresult ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine);
-
- nsresult ReflowUnmapped(nsBlockReflowState& aState);
-
- nsLineData* GetFirstLine();
-
- void ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame);
-
- void SetFirstChild(nsIFrame* aFirstChild) {
- if (nsnull == mFirstChild) {
- mFirstChild = aFirstChild;
- }
- }
-
- nsLineData* mLines;
- nsVoidArray* mRunInFloaters; // placeholder frames for floaters to display
- // at the top line
-
- friend struct nsLineLayout;
-};
-
-#endif /* nsBlockFrame_h___ */
diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp
deleted file mode 100644
index bf4fc11255c..00000000000
--- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsBlockFrame.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIHTMLContent.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIAnchoredItems.h"
-#include "nsIReflowCommand.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIPtr.h"
-#include "nsHTMLAtoms.h"
-#include "nsHTMLIIDs.h"
-#include "nsHTMLValue.h"
-#include "nsCSSLayout.h"
-#include "nsIView.h"
-
-// XXX what do we do with catastrophic errors (rv < 0)? What is the
-// state of the reflow world after such an error?
-
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-//----------------------------------------------------------------------
-
-void nsBlockBandData::ComputeAvailSpaceRect()
-{
- nsBandTrapezoid* trapezoid = data;
-
- if (count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < count; i++) {
- nsBandTrapezoid* trapezoid = &data[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &data[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availSpace);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availSpace);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availSpace.x = availSpace.XMost();
- }
- availSpace.width = 0;
- }
-}
-
-//----------------------------------------------------------------------
-
-nsBlockReflowState::nsBlockReflowState()
-{
-}
-
-nsBlockReflowState::~nsBlockReflowState()
-{
-}
-
-nsresult
-nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock)
-{
- nsresult rv = NS_OK;
-
- mPresContext = aPresContext;
- mBlock = aBlock;
- mSpaceManager = aSpaceManager;
- mBlockIsPseudo = aBlock->IsPseudoFrame();
- mListPositionOutside = PR_FALSE;
- mCurrentLine = nsnull;
- mPrevKidFrame = nsnull;
- reflowState = &aReflowState;
-
- mX = 0;
- mY = 0;
- mStyleSizeFlags = 0;
- mAvailSize = reflowState->maxSize;
- mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE);
- mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE);
- mMaxElementSizePointer = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
- }
- mKidXMost = 0;
-
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = 0;
- mPrevMarginSynthetic = PR_FALSE;
-
- mNextListOrdinal = -1;
-
- return rv;
-}
-
-// Recover the block reflow state to what it should be if aLine is about
-// to be reflowed. aLine should not be nsnull
-nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
-{
- NS_PRECONDITION(nsnull != aLine, "null parameter");
- nsLineData* prevLine = aLine->mPrevLine;
-
- if (nsnull != prevLine) {
- // Compute the running y-offset, and the available height
- mY = prevLine->mBounds.YMost();
- if (!mUnconstrainedHeight) {
- mAvailSize.height -= mY;
- }
-
- // Compute the kid x-most
- for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
- nscoord xmost = l->mBounds.XMost();
- if (xmost > mKidXMost) {
- mKidXMost = xmost;
- }
- }
-
- // If the previous line is a block, then factor in its bottom margin
- if (prevLine->mIsBlock) {
- const nsStyleSpacing* kidSpacing;
- nsIFrame* kid = prevLine->mFirstChild;
-
- kid->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)kidSpacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kid, kidMargin);
- if (kidMargin.bottom < 0) {
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = -kidMargin.bottom;
- } else {
- mPrevPosBottomMargin = kidMargin.bottom;
- mPrevNegBottomMargin = 0;
- }
- }
- }
-
- return NS_OK;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsBlockFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsBlockFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsBlockFrame::~nsBlockFrame()
-{
- DestroyLines();
- delete mRunInFloaters;
-}
-
-void nsBlockFrame::DestroyLines()
-{
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- mLines = nsnull;
-}
-
-NS_METHOD
-nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
-{
- NS_PRECONDITION(0 != aInstancePtr, "null ptr");
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
- if (aIID.Equals(kBlockFrameCID)) {
- *aInstancePtr = (void*) (this);
- return NS_OK;
- }
- else if (aIID.Equals(kIRunaroundIID)) {
- *aInstancePtr = (void*) ((nsIRunaround*) this);
- return NS_OK;
- }
- else if (aIID.Equals(kIFloaterContainerIID)) {
- *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
- return NS_OK;
- }
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_METHOD
-nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
-{
- aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame)
-{
- nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
- if (nsnull == cf) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
- aContinuingFrame = cf;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::ListTag(FILE* out) const
-{
- if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
- fprintf(out, "*block<");
- nsIAtom* atom = mContent->GetTag();
- if (nsnull != atom) {
- nsAutoString tmp;
- atom->ToString(tmp);
- fputs(tmp, out);
- }
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, ">(%d)@%p", contentIndex, this);
- } else {
- nsHTMLContainerFrame::ListTag(out);
- }
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- NS_RELEASE(view);
- }
-
- // Output the first/last content offset
- fprintf(out, "[%d,%d,%c] ", mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
-
- // Output the children, one line at a time
- if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- aIndent++;
-
- nsLineData* line = mLines;
- while (nsnull != line) {
- line->List(out, aIndent);
- line = line->mNextLine;
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
-
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- nsresult rv = nsHTMLContainerFrame::VerifyTree();
- if (NS_OK != rv) {
- return rv;
- }
- rv = VerifyLines(PR_TRUE);
- return rv;
-#else
- return NS_OK;
-#endif
-}
-
-#ifdef NS_DEBUG
-nsresult
-nsBlockFrame::VerifyLines(PRBool aFinalCheck) const
-{
- nsresult rv = NS_OK;
-
- // Make sure that the list of children agrees with our child count.
- // If this is not the case then the child list and the line list are
- // not properly arranged.
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(mChildCount == len, "bad child list");
-
- // Verify that our lines are correctly setup
- PRInt32 offset = mFirstContentOffset;
- PRInt32 lineChildCount = 0;
- nsLineData* line = mLines;
- nsLineData* prevLine = nsnull;
- while (nsnull != line) {
- if (aFinalCheck) {
- NS_ASSERTION(((offset == line->mFirstContentOffset) &&
- (line->mFirstContentOffset <= line->mLastContentOffset)),
- "bad line mFirstContentOffset");
- NS_ASSERTION(line->mLastContentOffset <= mLastContentOffset,
- "bad line mLastContentOffset");
- offset = line->mLastContentOffset;
- if (line->mLastContentIsComplete) {
- offset++;
- }
- }
- lineChildCount += line->mChildCount;
- rv = line->Verify(aFinalCheck);
- if (NS_OK != rv) {
- return rv;
- }
- prevLine = line;
- line = line->mNextLine;
- }
- if (aFinalCheck && (nsnull != prevLine)) {
- NS_ASSERTION(prevLine->mLastContentOffset == mLastContentOffset,
- "bad mLastContentOffset");
- NS_ASSERTION(prevLine->mLastContentIsComplete == mLastContentIsComplete,
- "bad mLastContentIsComplete");
- }
- NS_ASSERTION(lineChildCount == mChildCount, "bad line counts");
-
- return rv;
-}
-#endif
-
-//----------------------------------------------------------------------
-
-// Remove a next-in-flow from from this block's list of lines
-
-// XXX problems here:
-// 1. we always have to start from the first line: slow!
-// 2. we can avoid this when the child is not the last child in a line
-
-void
-nsBlockFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
- // When a reflow indicates completion it's possible that
- // next-in-flows were just removed. We have to remove them from any
- // nsLineData's that follow the current line.
- nsLineData* line = mLines;
- while (nsnull != line) {
- if (line->mFirstChild == aNextInFlow) {
- // Remove child from line.
- if (0 == --line->mChildCount) {
- line->mFirstChild = nsnull;
- }
- else {
- // Fixup the line
- nsIFrame* nextKid;
- aNextInFlow->GetNextSibling(nextKid);
- line->mFirstChild = nextKid;
- nextKid->GetContentIndex(line->mFirstContentOffset);
- }
- break;
- }
- line = line->mNextLine;
- }
-}
-
-nsresult
-nsBlockFrame::ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(aLineLayout, aDesiredSize, aReflowState, aStatus);
- }
- else {
- aKidFrame->Reflow(aLineLayout.mPresContext, aDesiredSize, aReflowState,
- aStatus);
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
- nsIRunaround* reflowRunaround;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- // Get the band for this y-offset and see whether there are any floaters
- // that have changed the left/right edges.
- //
- // XXX In order to do this efficiently we should move all this code to
- // nsBlockFrame since it already has band data, and it's probably the only
- // one who calls this routine anyway
- nsBandData bandData;
- nsBandTrapezoid trapezoids[12];
- nsBandTrapezoid* trapezoid = trapezoids;
- nsRect availBand;
-
- bandData.trapezoids = trapezoids;
- bandData.size = 12;
- aSpaceManager->GetBandData(0, aReflowState.maxSize, bandData);
-
- if (bandData.count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < bandData.count; i++) {
- nsBandTrapezoid* trapezoid = &trapezoids[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &trapezoids[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availBand);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availBand);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availBand.x = availBand.XMost();
- }
- availBand.width = 0;
- }
-
- // Does the child frame support interface nsIRunaround?
- if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
- (void**)&reflowRunaround)) {
- // Yes, the child frame wants to interact directly with the space
- // manager.
- reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState,
- aDesiredRect, aStatus);
- } else {
- // No, use interface nsIFrame instead.
- if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
- if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) {
- // There are left/right floaters.
- aReflowState.maxSize.width = availBand.width;
- }
- }
-
- // XXX FIX ME
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-
- // Return the desired rect
- aDesiredRect.x = availBand.x;
- aDesiredRect.y = 0;
- aDesiredRect.width = aDesiredSize.width;
- aDesiredRect.height = aDesiredSize.height;
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
-
- return NS_OK;
-}
-
-nsLineData*
-nsBlockFrame::CreateLineForOverflowList(nsIFrame* aOverflowList)
-{
- nsLineData* newLine = new nsLineData();
- if (nsnull != newLine) {
- nsIFrame* kid = aOverflowList;
- newLine->mFirstChild = kid;
- kid->GetContentIndex(newLine->mFirstContentOffset);
- newLine->mLastContentOffset = -1;
- newLine->mLastContentIsComplete = PRPackedBool(0x255);
- PRInt32 kids = 0;
- while (nsnull != kid) {
- kids++;
- kid->GetNextSibling(kid);
- }
- newLine->mChildCount = kids;
- }
- return newLine;
-}
-
-void
-nsBlockFrame::DrainOverflowList()
-{
- nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
- if (nsnull != prevBlock) {
- nsIFrame* overflowList = prevBlock->mOverflowList;
- if (nsnull != overflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- NS_ASSERTION(nsnull == mLines, "bad overflow list");
-
- // Create a line to hold the entire overflow list
- nsLineData* newLine = CreateLineForOverflowList(overflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(overflowList);
- prevBlock->mOverflowList = nsnull;
-
- // The new line is the first line
- mLines = newLine;
- }
- }
-
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild,
- "overflow list but no mapped children");
-
- // Create a line to hold the overflow list
- nsLineData* newLine = CreateLineForOverflowList(mOverflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
-
- // The new line is appended after our other lines
- nsLineData* prevLine = nsnull;
- nsLineData* line = mLines;
- while (nsnull != line) {
- prevLine = line;
- line = line->mNextLine;
- }
- if (nsnull == prevLine) {
- mLines = newLine;
- }
- else {
- prevLine->mNextLine = newLine;
- newLine->mPrevLine = prevLine;
- }
- }
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_FALSE);
- }
-#endif
-}
-
-void
-nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint8 aBreakType)
-{
- for (;;) {
- if (aState.mCurrentBand.count <= 1) {
- // No floaters in this band therefore nothing to clear
- break;
- }
-
- // Find the Y coordinate to clear to
- nscoord clearYMost = aState.mY;
- nsRect tmp;
- PRInt32 i;
- for (i = 0; i < aState.mCurrentBand.count; i++) {
- const nsStyleDisplay* display;
- nsBandTrapezoid* trapezoid = &aState.mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 fn, numFrames = trapezoid->frames->Count();
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
-
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- }
-
- if (clearYMost == aState.mY) {
- // Nothing to clear
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::ClearFloaters: mY=%d clearYMost=%d\n",
- aState.mY, clearYMost));
-
- aState.mY = clearYMost + 1;
-
- // Get a new band
- GetAvailableSpace(aState, aState.mY);
- }
-}
-
-nsresult
-nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine)
-{
- // Before we place the line, make sure that it will fit in it's new
- // location. It always fits if the height isn't constrained or it's
- // the first line.
- if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
- if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
- // The line will not fit
- return PushLines(aState, aLine);
- }
- }
-
- // When the line is finally placed then we know that the child
- // frames have a stable location. This means that we can DidReflow
- // them marking them done. Note that when we are paginated this
- // optimization cannot be done because this may be a nested block
- // that will be pushed to a new page by the containing block and the
- // nested block can't know that during its reflow.
- // XXX and actually, this only always works for the block which is a
- // child of the body.
- if (!aState.mPresContext->IsPaginated()) {
- nsIAtom* tag = mContent->GetTag();
- if (nsHTMLAtoms::body == tag) {
- nsIFrame* child = aLine->mFirstChild;
- for (PRInt32 i = aLine->mChildCount; --i >= 0; ) {
- nsFrameState state;
- child->GetFrameState(state);
- if (NS_FRAME_IN_REFLOW & state) {
- child->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
- }
- child->GetNextSibling(child);
- }
-
- // Paint this portion of ourselves
- if (!aLine->mBounds.IsEmpty()) {
- Invalidate(aLine->mBounds);
- }
- }
- NS_IF_RELEASE(tag);
- }
-
- // Consume space and advance running values
- aState.mY += aLine->mBounds.height;
- if (nsnull != aState.mMaxElementSizePointer) {
- nsSize* maxSize = aState.mMaxElementSizePointer;
- if (aLineLayout.mState.mMaxElementSize.width > maxSize->width) {
- maxSize->width = aLineLayout.mState.mMaxElementSize.width;
- }
- if (aLineLayout.mState.mMaxElementSize.height > maxSize->height) {
- maxSize->height = aLineLayout.mState.mMaxElementSize.height;
- }
- }
- nscoord xmost = aLine->mBounds.XMost();
- if (xmost > aState.mKidXMost) {
- aState.mKidXMost = xmost;
- }
-
- // Process any pending break operations
- switch (aLineLayout.mPendingBreak) {
- default:
- break;
- case NS_STYLE_CLEAR_LEFT:
- case NS_STYLE_CLEAR_RIGHT:
- case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
- ClearFloaters(aState, aLineLayout.mPendingBreak);
- break;
- }
- // XXX for now clear the pending break; this is where support for
- // page breaks or column breaks could be partially handled.
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- // Any below current line floaters to place?
- // XXX We really want to know whether this is the initial reflow (reflow
- // unmapped) or a subsequent reflow in which case we only need to offset
- // the existing floaters...
- if (aState.mPendingFloaters.Count() > 0) {
- if (nsnull == aLine->mFloaters) {
- aLine->mFloaters = new nsVoidArray;
- }
- aLine->mFloaters->operator=(aState.mPendingFloaters);
- aState.mPendingFloaters.Clear();
- }
-
- if (nsnull != aLine->mFloaters) {
- PlaceBelowCurrentLineFloaters(aState, aLine->mFloaters, aState.mY);
- // XXX Factor in the height of the floaters as well when considering
- // whether the line fits.
- // The default policy is that if there isn't room for the floaters then
- // both the line and the floaters are pushed to the next-in-flow...
- }
-
- if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
- // The current y coordinate is now past our available space
- // rectangle. Get a new band of space.
- GetAvailableSpace(aState, aState.mY);
- }
-
- return NS_LINE_LAYOUT_COMPLETE;
-}
-
-// aY has borderpadding.top already factored in
-nsresult
-nsBlockFrame::GetAvailableSpace(nsBlockReflowState& aState, nscoord aY)
-{
- nsresult rv = NS_OK;
-
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Fill in band data for the specific Y coordinate
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->GetBandData(aY, aState.mAvailSize, aState.mCurrentBand);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
- aState.mCurrentBand.ComputeAvailSpaceRect();
-
- aState.mCurrentBand.availSpace.MoveBy(aState.mBorderPadding.left,
- aState.mY);
-
- return rv;
-}
-
-// Give aLine and any successive lines to the block's next-in-flow; if
-// we don't have a next-in-flow then push all the children onto our
-// overflow list.
-nsresult
-nsBlockFrame::PushLines(nsBlockReflowState& aState, nsLineData* aLine)
-{
- PRInt32 i;
-
- // Split our child-list in two; revert our last content offset and
- // completion status to the previous line.
- nsLineData* prevLine = aLine->mPrevLine;
- NS_PRECONDITION(nsnull != prevLine, "pushing first line");
- nsIFrame* prevKidFrame = prevLine->mFirstChild;
- for (i = prevLine->mChildCount - 1; --i >= 0; ) {
- prevKidFrame->GetNextSibling(prevKidFrame);
- }
-#ifdef NS_DEBUG
- nsIFrame* nextFrame;
- prevKidFrame->GetNextSibling(nextFrame);
- NS_ASSERTION(nextFrame == aLine->mFirstChild, "bad line list");
-#endif
- prevKidFrame->SetNextSibling(nsnull);
- prevLine->mNextLine = nsnull;
- mLastContentOffset = prevLine->mLastContentOffset;
- mLastContentIsComplete = prevLine->mLastContentIsComplete;
-
- // Push children to our next-in-flow if we have, or to our overflow list
- nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow;
- PRInt32 pushCount = 0;
- if (nsnull == nextInFlow) {
- // Place children on the overflow list
- mOverflowList = aLine->mFirstChild;
-
- // Destroy the lines
- nsLineData* line = aLine;
- while (nsnull != line) {
- pushCount += line->mChildCount;
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- }
- else {
- aLine->mPrevLine = nsnull;
-
- // Pass on the children to our next-in-flow
- nsLineData* line = aLine;
- prevLine = line;
- nsIFrame* lastKid = aLine->mFirstChild;
- nsIFrame* kid = lastKid;
- while (nsnull != line) {
- i = line->mChildCount;
- pushCount += i;
- NS_ASSERTION(kid == line->mFirstChild, "bad line list");
- while (--i >= 0) {
- kid->SetGeometricParent(nextInFlow);
- nsIFrame* contentParent;
- kid->GetContentParent(contentParent);
- if (this == contentParent) {
- kid->SetContentParent(nextInFlow);
- }
- lastKid = kid;
- kid->GetNextSibling(kid);
- }
- prevLine = line;
- line = line->mNextLine;
- }
-
- // Join the two line lists
- nsLineData* nextInFlowLine = nextInFlow->mLines;
- if (nsnull != nextInFlowLine) {
- lastKid->SetNextSibling(nextInFlowLine->mFirstChild);
- nextInFlowLine->mPrevLine = prevLine;
- }
- nsIFrame* firstKid = aLine->mFirstChild;
- prevLine->mNextLine = nextInFlowLine;
- nextInFlow->mLines = aLine;
- nextInFlow->mFirstChild = firstKid;
- nextInFlow->mChildCount += pushCount;
- firstKid->GetContentIndex(nextInFlow->mFirstContentOffset);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- nextInFlow->VerifyLines(PR_FALSE);
- }
-#endif
- }
- mChildCount -= pushCount;
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return NS_LINE_LAYOUT_NOT_COMPLETE;
-}
-
-nsresult
-nsBlockFrame::ReflowMapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // See if we have any run-in floaters to place
- if (nsnull != mRunInFloaters) {
- PlaceBelowCurrentLineFloaters(aState, mRunInFloaters, aState.mY);
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- nsLineData* line = mLines;
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != line) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);/* XXX move out of loop */
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-// XXX This is a short-term hack. It assumes that the caller has already recovered
-// the state, and that some space has been retrieved from the space manager...
-nsresult
-nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != aLine) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, aLine);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, aLine);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = aLine->mLastContentOffset;
- mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
- aLine = aLine->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // If we have no children and we have a prev-in-flow then we need to
- // pick up where it left off. If we have children, e.g. we're being
- // resized, then our content offset will have already been set
- // correctly.
- nsIFrame* kidPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsBlockFrame* prev = (nsBlockFrame*) mPrevInFlow;
- mFirstContentOffset = prev->NextChildOffset();// XXX Is this necessary?
- if (PR_FALSE == prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
-
- // Get to the last line where the new content may be added
- nsLineData* line = nsnull;
- nsLineData* prevLine = nsnull;
- if (nsnull != mLines) {
- line = mLines;
- while (nsnull != line->mNextLine) {
- line = line->mNextLine;
- }
- prevLine = line->mPrevLine;
-
- // If the last line is not complete then kidPrevInFlow should be
- // set to the last-line's last child.
- if (!line->mLastContentIsComplete) {
- kidPrevInFlow = line->GetLastChild();
- }
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- // Now reflow the new content until we are out of new content or out
- // of vertical space.
- PRInt32 kidIndex = NextChildOffset();
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- PRInt32 contentChildCount = mContent->ChildCount();
- while (kidIndex < contentChildCount) {
- if (nsnull == line) {
- if (!MoreToReflow(aState)) {
- break;
- }
- line = new nsLineData();
- if (nsnull == line) {
- rv = NS_ERROR_OUT_OF_MEMORY;
- goto done;
- }
- line->mFirstContentOffset = kidIndex;
- }
-
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Add line to the block; do this before placing the line in case
- // PushLines is needed.
- if (nsnull == prevLine) {
- // For the first line, initialize mFirstContentOffset
- mFirstContentOffset = line->mFirstContentOffset;
- mFirstChild = line->mFirstChild;
- mLines = line;
- }
- else {
- prevLine->mNextLine = line;
- line->mPrevLine = prevLine;
- }
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
- kidIndex = lineLayout.mState.mKidIndex;
- kidPrevInFlow = lineLayout.mKidPrevInFlow;
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- prevLine = line;
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
- if (aState.mBlockIsPseudo) {
- PropagateContentOffsets();
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState)
-{
- nsresult rv;
- rv = aState.Initialize(aPresContext, aSpaceManager,
- aReflowState, aMaxElementSize, this);
-
- // Apply border and padding adjustments for regular frames only
- if (!aState.mBlockIsPseudo) {
- const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStylePosition* myPosition = (const nsStylePosition*)
- mStyleContext->GetStyleData(eStyleStruct_Position);
-
- mySpacing->CalcBorderPaddingFor(this, aState.mBorderPadding);
- aState.mY = aState.mBorderPadding.top;
- aState.mX = aState.mBorderPadding.left;
-
- if (aState.mUnconstrainedWidth) {
- // If our width is unconstrained don't bother futzing with the
- // available width/height because they don't matter - we are
- // going to get reflowed again.
- aState.mDeltaWidth = NS_UNCONSTRAINEDSIZE;
- }
- else {
- // When we are constrained we need to apply the width/height
- // style properties. When we have a width/height it applies to
- // the content width/height of our box. The content width/height
- // doesn't include the border+padding so we have to add that in
- // instead of subtracting it out of our maxsize.
- nscoord lr =
- aState.mBorderPadding.left + aState.mBorderPadding.right;
-
- // Get and apply the stylistic size. Note: do not limit the
- // height until we are done reflowing.
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
- aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aState.mAvailSize.width = aState.mStyleSize.width + lr;
- }
- else {
- aState.mAvailSize.width -= lr;
- }
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
- }
- else {
- aState.mBorderPadding.SizeTo(0, 0, 0, 0);
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
-
- // Setup initial list ordinal value
- nsIAtom* tag = mContent->GetTag();
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- nsHTMLValue value;
- if (eContentAttr_HasValue ==
- ((nsIHTMLContent*)mContent)->GetAttribute(nsHTMLAtoms::start, value)) {
- if (eHTMLUnit_Integer == value.GetUnit()) {
- aState.mNextListOrdinal = value.GetIntValue();
- }
- }
- }
- NS_RELEASE(tag);
-
- // Setup list flags in block reflow state if this block is a list
- // item.
- const nsStyleDisplay* myDisplay = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_DISPLAY_LIST_ITEM == myDisplay->mDisplay) {
- const nsStyleList* myList = (const nsStyleList*)
- mStyleContext->GetStyleData(eStyleStruct_List);
- if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == myList->mListStylePosition) {
- aState.mListPositionOutside = PR_TRUE;
- }
- }
-
- return rv;
-}
-
-PRBool
-nsBlockFrame::MoreToReflow(nsBlockReflowState& aState)
-{
- PRBool rv = PR_FALSE;
- if (NextChildOffset() < mContent->ChildCount()) {
- rv = PR_TRUE;
- }
- return rv;
-}
-
-nsBlockReflowState*
-nsBlockFrame::FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame)
-{
- nsBlockReflowState* state = nsnull;
- if (nsnull != aFrame) {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
- while (nsnull != parent) {
- nsBlockFrame* block;
- nsresult rv = parent->QueryInterface(kBlockFrameCID, (void**) &block);
- if (NS_OK == rv) {
- nsIPresShell* shell = aPresContext->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(block);
- NS_RELEASE(shell);
- break;
- }
- parent->GetGeometricParent(parent);
- }
- }
- return state;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer)
-{
- return nsHTMLContainerFrame::ContentAppended(aShell, aPresContext, aContainer);
-}
-
-NS_METHOD
-nsBlockFrame::ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- return nsHTMLContainerFrame::ContentInserted(aShell, aPresContext, aContainer,
- aChild, aIndexInParent);
-}
-
-NS_METHOD
-nsBlockFrame::ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-NS_METHOD
-nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-// XXX if there is nothing special going on here, then remove this
-// implementation and let nsFrame do it.
-NS_METHOD
-nsBlockFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nsresult rv = NS_OK;
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = mRect.height;
- aMetrics.descent = 0;
- return rv;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PreReflowCheck();
- }
-#endif
-
- nsBlockReflowState state;
- nsresult rv = NS_OK;
-
- if (eReflowReason_Initial == aReflowState.reason) {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 == (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
- else {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 != (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- }
-
- aStatus = NS_FRAME_COMPLETE;
- rv = InitializeState(aPresContext, aSpaceManager, aReflowState,
- aDesiredSize.maxElementSize, state);
-
- NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d",
- aReflowState.reason, state.mDeltaWidth));
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- nsIPresShell* shell = state.mPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Is the reflow command target at us?
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
- if (this == target) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- if (nsIReflowCommand::FrameAppended == type) {
- nsLineData* lastLine = LastLine();
-
- // Restore the state
- if (nsnull != lastLine) {
- state.RecoverState(lastLine);
- }
-
- // Reflow unmapped children
- PRInt32 kidIndex = NextChildOffset();
- PRInt32 contentChildCount = mContent->ChildCount();
- if (kidIndex == contentChildCount) {
- // There is nothing to do here
- if (nsnull != lastLine) {
- state.mY = lastLine->mBounds.YMost();
- }
- }
- else {
- rv = ReflowUnmapped(state);
- }
- } else {
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- }
- } else {
- // The command is passing through us. Get the next frame in the
- // reflow chain
- nsIFrame* nextFrame;
- aReflowState.reflowCommand->GetNext(nextFrame);
-
- // Restore our state as if nextFrame is the next frame to reflow
- nsLineData* line = FindLine(nextFrame);
- state.RecoverState(line);
-
- // Get some available space to start reflowing with
- GetAvailableSpace(state, state.mY);
-
- // Reflow the affected line
- nsLineLayout lineLayout(state);
-
- state.mCurrentLine = &lineLayout;
- lineLayout.Initialize(state, line);
-
- // Have the line handle the incremental reflow
- nsRect oldBounds = line->mBounds;
- rv = lineLayout.IncrementalReflowFromChild(aReflowState.reflowCommand,
- nextFrame);
-
- // Now place the line. It's possible it won't fit
- rv = PlaceLine(state, lineLayout, line);
- // XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- state.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
-
- // Now figure out what to do with the frames that follow
- rv = IncrementalReflowAfter(state, line, rv, oldBounds);
- }
- }
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- } else {
- nsresult rv = NS_OK;
- nsIPresShell* shell = aPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Check for an overflow list
- DrainOverflowList();
-
- if (nsnull != mLines) {
- rv = ReflowMapped(state);
- }
-
- if (NS_OK == rv) {
- if ((nsnull != mLines) && (state.mAvailSize.height <= 0)) {
- // We are out of space
- }
- if (MoreToReflow(state)) {
- rv = ReflowUnmapped(state);
- }
- }
-
-#ifdef NS_DEBUG
- if (0 != mContent->ChildCount()) {
- NS_ASSERTION(nsnull != mLines, "reflowed zero children");
- }
-#endif
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsBlockFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredRect.width, aDesiredRect.height));
- return rv;
-}
-
-nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
-{
- // Find the line that contains the aFrame
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsIFrame* child = line->mFirstChild;
- for (PRInt32 count = line->mChildCount; count > 0; count--) {
- if (child == aFrame) {
- return line;
- }
-
- child->GetNextSibling(child);
- }
-
- // Move to the next line
- line = line->mNextLine;
- }
-
- return nsnull;
-}
-
-nsLineData* nsBlockFrame::LastLine()
-{
- nsLineData* lastLine = mLines;
-
- // Get the last line
- if (nsnull != lastLine) {
- while (nsnull != lastLine->mNextLine) {
- lastLine = lastLine->mNextLine;
- }
- }
-
- return lastLine;
-}
-
-nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds)
-{
- // Now just reflow all the lines that follow...
- // XXX Obviously this needs to be more efficient
- return ReflowMappedFrom(aState, aLine->mNextLine);
-}
-
-void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect)
-{
- aDesiredRect.x = 0;
- aDesiredRect.y = 0;
-
- // Special check for zero sized content: If our content is zero
- // sized then we collapse into nothingness.
- if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
- (0 == aState.mY - aState.mBorderPadding.top)) {
- aDesiredRect.width = 0;
- aDesiredRect.height = 0;
- }
- else {
- aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
- if (!aState.mUnconstrainedWidth) {
- // Make sure we're at least as wide as the max size we were given
- nscoord maxWidth = aState.mAvailSize.width + aState.mBorderPadding.left +
- aState.mBorderPadding.right;
- if (aDesiredRect.width < maxWidth) {
- aDesiredRect.width = maxWidth;
- }
- }
- aState.mY += aState.mBorderPadding.bottom;
- nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
- aState.mPrevNegBottomMargin;
- if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
- // It's possible that we don't have room for the last bottom
- // margin (the last bottom margin is the margin following a block
- // element that we contain; it isn't applied immediately because
- // of the margin collapsing logic). This can happen when we are
- // reflowed in a limited amount of space because we don't know in
- // advance what the last bottom margin will be.
- nscoord maxY = aMaxSize.height;
- if (aState.mY + lastBottomMargin > maxY) {
- lastBottomMargin = maxY - aState.mY;
- if (lastBottomMargin < 0) {
- lastBottomMargin = 0;
- }
- }
- }
- aState.mY += lastBottomMargin;
- aDesiredRect.height = aState.mY;
-
- if (!aState.mBlockIsPseudo) {
- // Clamp the desired rect height when style height applies
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredRect.height = aState.mBorderPadding.top +
- aState.mStyleSize.height + aState.mBorderPadding.bottom;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-
-void nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame)
-{
- // Compute the available space for the floater. Use the default
- // 'auto' width and height values
- nsSize kidAvailSize(0, NS_UNCONSTRAINEDSIZE);
- nsSize styleSize;
- PRIntn styleSizeFlags = nsCSSLayout::GetStyleSize(aPresContext, *aState.reflowState,
- styleSize);
-
- // XXX The width and height are for the content area only. Add in space for
- // border and padding
- if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
- kidAvailSize.width = styleSize.width;
- }
- if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
- kidAvailSize.height = styleSize.height;
- }
-
- // Resize reflow the anchored item into the available space
- // XXX Check for complete?
- nsReflowMetrics desiredSize(nsnull);
- nsReflowState reflowState(aFloaterFrame, *aState.reflowState, kidAvailSize,
- eReflowReason_Initial);
- nsReflowStatus status;
-
- aFloaterFrame->WillReflow(*aPresContext);
- aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status);
- aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
-
- aFloaterFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
-}
-
-PRBool
-nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
-
- if (nsnull != state) {
- // Get the frame associated with the space manager, and get its
- // nsIAnchoredItems interface
- nsIFrame* frame = state->mSpaceManager->GetFrame();
- nsIAnchoredItems* anchoredItems = nsnull;
-
- frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
- NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
- if (nsnull != anchoredItems) {
- anchoredItems->AddAnchoredItem(aFloater,
- nsIAnchoredItems::anHTMLFloater,
- this);
-
- // Reflow the floater
- ReflowFloater(aPresContext, *state, aFloater);
-
- // Determine whether we place it at the top or we place it below the
- // current line
- if (IsLeftMostChild(aPlaceholder)) {
- if (nsnull == mRunInFloaters) {
- mRunInFloaters = new nsVoidArray;
- }
- mRunInFloaters->AppendElement(aPlaceholder);
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- } else {
- // Add the placeholder to our to-do list
- state->mPendingFloaters.AppendElement(aPlaceholder);
- }
- return PR_TRUE;
- }
- }
-
- return PR_FALSE;
-}
-
-// XXX Deprecated
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
-#if 0
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
- if (nsnull != state) {
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- }
-#endif
-}
-
-PRBool
-nsBlockFrame::IsLeftMostChild(nsIFrame* aFrame)
-{
- do {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
-
- // See if there are any non-zero sized child frames that precede
- // aFrame in the child list
- nsIFrame* child;
- parent->FirstChild(child);
- while ((nsnull != child) && (aFrame != child)) {
- nsSize size;
-
- // Is the child zero-sized?
- child->GetSize(size);
- if ((size.width > 0) || (size.height > 0)) {
- // We found a non-zero sized child frame that precedes aFrame
- return PR_FALSE;
- }
- child->GetNextSibling(child);
- }
-
- // aFrame is the left-most non-zero sized frame in its geometric parent.
- // Walk up one level and check that its parent is left-most as well
- aFrame = parent;
- } while (aFrame != this);
- return PR_TRUE;
-}
-
-// Used when placing run-in floaters (floaters displayed at the top of the
-// block as supposed to below the current line)
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState)
-{
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Get the type of floater
- const nsStyleDisplay* floaterDisplay;
- aFloater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay);
-
- // Commit some space in the space manager, and adjust our current
- // band of available space.
- nsRect region;
- aFloater->GetRect(region);
- region.y = aState.mY;
- if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
- region.x = aState.mX;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats,
- "bad float type");
- region.x = aState.mCurrentBand.availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->AddRectRegion(aFloater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- aFloater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Update the band of available space to reflect space taken up by
- // the floater
- GetAvailableSpace(aState, aState.mY);
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-// XXX It's unclear what coordinate space aY is in. Is it relative to the
-// upper-left origin of the containing block, or relative to aState.mY?
-void
-nsBlockFrame::PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY)
-{
- NS_PRECONDITION(aFloaterList->Count() > 0, "no floaters");
-
- nsISpaceManager* sm = aState.mSpaceManager;
- nsBlockBandData* bd = &aState.mCurrentBand;
-
- // XXX Factor this code with PlaceFloater()...
- PRInt32 numFloaters = aFloaterList->Count();
- for (PRInt32 i = 0; i < numFloaters; i++) {
- nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)aFloaterList->ElementAt(i);
- nsIFrame* floater = placeholderFrame->GetAnchoredItem();
- nsRect region;
-
- // Get the band of available space
- // XXX This is inefficient to do this inside the loop...
- GetAvailableSpace(aState, aY);
-
- // Get the type of floater
- const nsStyleDisplay* sd;
- floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)sd);
-
- floater->GetRect(region);
- // XXX GetAvailableSpace() is translating availSpace by aState.mY...
- region.y = bd->availSpace.y - aState.mY;
- if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
- region.x = bd->availSpace.x;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
- region.x = bd->availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- // XXX Temporary incremental hack
- sm->RemoveRegion(floater);
- sm->AddRectRegion(floater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- floater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
- }
-
- // Pass on updated available space to the current line
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- GetAvailableSpace(aState, aY);
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineData*
-nsBlockFrame::GetFirstLine()
-{
- return mLines;
-}
-
-PRIntn
-nsBlockFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_TOP;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_BOTTOM;
- }
- return skip;
-}
diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h
deleted file mode 100644
index bf4fc11255c..00000000000
--- a/mozilla/layout/html/base/src/nsBlockReflowState.h
+++ /dev/null
@@ -1,1961 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsBlockFrame.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIHTMLContent.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsIAnchoredItems.h"
-#include "nsIReflowCommand.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIPtr.h"
-#include "nsHTMLAtoms.h"
-#include "nsHTMLIIDs.h"
-#include "nsHTMLValue.h"
-#include "nsCSSLayout.h"
-#include "nsIView.h"
-
-// XXX what do we do with catastrophic errors (rv < 0)? What is the
-// state of the reflow world after such an error?
-
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-//----------------------------------------------------------------------
-
-void nsBlockBandData::ComputeAvailSpaceRect()
-{
- nsBandTrapezoid* trapezoid = data;
-
- if (count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < count; i++) {
- nsBandTrapezoid* trapezoid = &data[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &data[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availSpace);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availSpace);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availSpace.x = availSpace.XMost();
- }
- availSpace.width = 0;
- }
-}
-
-//----------------------------------------------------------------------
-
-nsBlockReflowState::nsBlockReflowState()
-{
-}
-
-nsBlockReflowState::~nsBlockReflowState()
-{
-}
-
-nsresult
-nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockFrame* aBlock)
-{
- nsresult rv = NS_OK;
-
- mPresContext = aPresContext;
- mBlock = aBlock;
- mSpaceManager = aSpaceManager;
- mBlockIsPseudo = aBlock->IsPseudoFrame();
- mListPositionOutside = PR_FALSE;
- mCurrentLine = nsnull;
- mPrevKidFrame = nsnull;
- reflowState = &aReflowState;
-
- mX = 0;
- mY = 0;
- mStyleSizeFlags = 0;
- mAvailSize = reflowState->maxSize;
- mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE);
- mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE);
- mMaxElementSizePointer = aMaxElementSize;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
- }
- mKidXMost = 0;
-
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = 0;
- mPrevMarginSynthetic = PR_FALSE;
-
- mNextListOrdinal = -1;
-
- return rv;
-}
-
-// Recover the block reflow state to what it should be if aLine is about
-// to be reflowed. aLine should not be nsnull
-nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
-{
- NS_PRECONDITION(nsnull != aLine, "null parameter");
- nsLineData* prevLine = aLine->mPrevLine;
-
- if (nsnull != prevLine) {
- // Compute the running y-offset, and the available height
- mY = prevLine->mBounds.YMost();
- if (!mUnconstrainedHeight) {
- mAvailSize.height -= mY;
- }
-
- // Compute the kid x-most
- for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
- nscoord xmost = l->mBounds.XMost();
- if (xmost > mKidXMost) {
- mKidXMost = xmost;
- }
- }
-
- // If the previous line is a block, then factor in its bottom margin
- if (prevLine->mIsBlock) {
- const nsStyleSpacing* kidSpacing;
- nsIFrame* kid = prevLine->mFirstChild;
-
- kid->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)kidSpacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kid, kidMargin);
- if (kidMargin.bottom < 0) {
- mPrevPosBottomMargin = 0;
- mPrevNegBottomMargin = -kidMargin.bottom;
- } else {
- mPrevPosBottomMargin = kidMargin.bottom;
- mPrevNegBottomMargin = 0;
- }
- }
- }
-
- return NS_OK;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsBlockFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsBlockFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsBlockFrame::nsBlockFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
-}
-
-nsBlockFrame::~nsBlockFrame()
-{
- DestroyLines();
- delete mRunInFloaters;
-}
-
-void nsBlockFrame::DestroyLines()
-{
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- mLines = nsnull;
-}
-
-NS_METHOD
-nsBlockFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
-{
- NS_PRECONDITION(0 != aInstancePtr, "null ptr");
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
- if (aIID.Equals(kBlockFrameCID)) {
- *aInstancePtr = (void*) (this);
- return NS_OK;
- }
- else if (aIID.Equals(kIRunaroundIID)) {
- *aInstancePtr = (void*) ((nsIRunaround*) this);
- return NS_OK;
- }
- else if (aIID.Equals(kIFloaterContainerIID)) {
- *aInstancePtr = (void*) ((nsIFloaterContainer*) this);
- return NS_OK;
- }
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_METHOD
-nsBlockFrame::IsSplittable(nsSplittableType& aIsSplittable) const
-{
- aIsSplittable = NS_FRAME_SPLITTABLE_NON_RECTANGULAR;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::CreateContinuingFrame(nsIPresContext* aCX,
- nsIFrame* aParent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aContinuingFrame)
-{
- nsBlockFrame* cf = new nsBlockFrame(mContent, aParent);
- if (nsnull == cf) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- PrepareContinuingFrame(aCX, aParent, aStyleContext, cf);
- aContinuingFrame = cf;
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::ListTag(FILE* out) const
-{
- if ((nsnull != mGeometricParent) && IsPseudoFrame()) {
- fprintf(out, "*block<");
- nsIAtom* atom = mContent->GetTag();
- if (nsnull != atom) {
- nsAutoString tmp;
- atom->ToString(tmp);
- fputs(tmp, out);
- }
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, ">(%d)@%p", contentIndex, this);
- } else {
- nsHTMLContainerFrame::ListTag(out);
- }
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the tag
- ListTag(out);
- nsIView* view;
- GetView(view);
- if (nsnull != view) {
- fprintf(out, " [view=%p]", view);
- NS_RELEASE(view);
- }
-
- // Output the first/last content offset
- fprintf(out, "[%d,%d,%c] ", mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
- if (nsnull != mPrevInFlow) {
- fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
- }
- if (nsnull != mNextInFlow) {
- fprintf(out, "next-in-flow=%p ", mNextInFlow);
- }
-
- // Output the rect
- out << mRect;
-
- // Output the children, one line at a time
- if (nsnull != mLines) {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<\n", out);
- aIndent++;
-
- nsLineData* line = mLines;
- while (nsnull != line) {
- line->List(out, aIndent);
- line = line->mNextLine;
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- if (0 != mState) {
- fprintf(out, " [state=%08x]", mState);
- }
- fputs("<>\n", out);
- }
-
- return NS_OK;
-}
-
-NS_METHOD
-nsBlockFrame::VerifyTree() const
-{
-#ifdef NS_DEBUG
- NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
- nsresult rv = nsHTMLContainerFrame::VerifyTree();
- if (NS_OK != rv) {
- return rv;
- }
- rv = VerifyLines(PR_TRUE);
- return rv;
-#else
- return NS_OK;
-#endif
-}
-
-#ifdef NS_DEBUG
-nsresult
-nsBlockFrame::VerifyLines(PRBool aFinalCheck) const
-{
- nsresult rv = NS_OK;
-
- // Make sure that the list of children agrees with our child count.
- // If this is not the case then the child list and the line list are
- // not properly arranged.
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(mChildCount == len, "bad child list");
-
- // Verify that our lines are correctly setup
- PRInt32 offset = mFirstContentOffset;
- PRInt32 lineChildCount = 0;
- nsLineData* line = mLines;
- nsLineData* prevLine = nsnull;
- while (nsnull != line) {
- if (aFinalCheck) {
- NS_ASSERTION(((offset == line->mFirstContentOffset) &&
- (line->mFirstContentOffset <= line->mLastContentOffset)),
- "bad line mFirstContentOffset");
- NS_ASSERTION(line->mLastContentOffset <= mLastContentOffset,
- "bad line mLastContentOffset");
- offset = line->mLastContentOffset;
- if (line->mLastContentIsComplete) {
- offset++;
- }
- }
- lineChildCount += line->mChildCount;
- rv = line->Verify(aFinalCheck);
- if (NS_OK != rv) {
- return rv;
- }
- prevLine = line;
- line = line->mNextLine;
- }
- if (aFinalCheck && (nsnull != prevLine)) {
- NS_ASSERTION(prevLine->mLastContentOffset == mLastContentOffset,
- "bad mLastContentOffset");
- NS_ASSERTION(prevLine->mLastContentIsComplete == mLastContentIsComplete,
- "bad mLastContentIsComplete");
- }
- NS_ASSERTION(lineChildCount == mChildCount, "bad line counts");
-
- return rv;
-}
-#endif
-
-//----------------------------------------------------------------------
-
-// Remove a next-in-flow from from this block's list of lines
-
-// XXX problems here:
-// 1. we always have to start from the first line: slow!
-// 2. we can avoid this when the child is not the last child in a line
-
-void
-nsBlockFrame::WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow)
-{
- // When a reflow indicates completion it's possible that
- // next-in-flows were just removed. We have to remove them from any
- // nsLineData's that follow the current line.
- nsLineData* line = mLines;
- while (nsnull != line) {
- if (line->mFirstChild == aNextInFlow) {
- // Remove child from line.
- if (0 == --line->mChildCount) {
- line->mFirstChild = nsnull;
- }
- else {
- // Fixup the line
- nsIFrame* nextKid;
- aNextInFlow->GetNextSibling(nextKid);
- line->mFirstChild = nextKid;
- nextKid->GetContentIndex(line->mFirstContentOffset);
- }
- break;
- }
- line = line->mNextLine;
- }
-}
-
-nsresult
-nsBlockFrame::ReflowInlineChild(nsLineLayout& aLineLayout,
- nsIFrame* aKidFrame,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(aLineLayout, aDesiredSize, aReflowState, aStatus);
- }
- else {
- aKidFrame->Reflow(aLineLayout.mPresContext, aDesiredSize, aReflowState,
- aStatus);
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
- nsIRunaround* reflowRunaround;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
-
- // Get the band for this y-offset and see whether there are any floaters
- // that have changed the left/right edges.
- //
- // XXX In order to do this efficiently we should move all this code to
- // nsBlockFrame since it already has band data, and it's probably the only
- // one who calls this routine anyway
- nsBandData bandData;
- nsBandTrapezoid trapezoids[12];
- nsBandTrapezoid* trapezoid = trapezoids;
- nsRect availBand;
-
- bandData.trapezoids = trapezoids;
- bandData.size = 12;
- aSpaceManager->GetBandData(0, aReflowState.maxSize, bandData);
-
- if (bandData.count > 1) {
- // If there's more than one trapezoid that means there are floaters
- PRInt32 i;
-
- // Stop when we get to space occupied by a right floater, or when we've
- // looked at every trapezoid and none are right floaters
- for (i = 0; i < bandData.count; i++) {
- nsBandTrapezoid* trapezoid = &trapezoids[i];
-
- if (trapezoid->state != nsBandTrapezoid::Available) {
- const nsStyleDisplay* display;
-
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 numFrames = trapezoid->frames->Count();
-
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (PRInt32 i = 0; i < numFrames; i++) {
- nsIFrame* f = (nsIFrame*)trapezoid->frames->ElementAt(i);
-
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- goto foundRightFloater;
- }
- }
-
- } else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
- break;
- }
- }
- }
- }
- foundRightFloater:
-
- if (i > 0) {
- trapezoid = &trapezoids[i - 1];
- }
- }
-
- if (nsBandTrapezoid::Available == trapezoid->state) {
- // The trapezoid is available
- trapezoid->GetRect(availBand);
- } else {
- const nsStyleDisplay* display;
-
- // The trapezoid is occupied. That means there's no available space
- trapezoid->GetRect(availBand);
-
- // XXX Handle the case of multiple frames
- trapezoid->frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
- availBand.x = availBand.XMost();
- }
- availBand.width = 0;
- }
-
- // Does the child frame support interface nsIRunaround?
- if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
- (void**)&reflowRunaround)) {
- // Yes, the child frame wants to interact directly with the space
- // manager.
- reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState,
- aDesiredRect, aStatus);
- } else {
- // No, use interface nsIFrame instead.
- if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
- if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) {
- // There are left/right floaters.
- aReflowState.maxSize.width = availBand.width;
- }
- }
-
- // XXX FIX ME
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-
- // Return the desired rect
- aDesiredRect.x = availBand.x;
- aDesiredRect.y = 0;
- aDesiredRect.width = aDesiredSize.width;
- aDesiredRect.height = aDesiredSize.height;
- }
-
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
-
- return NS_OK;
-}
-
-nsLineData*
-nsBlockFrame::CreateLineForOverflowList(nsIFrame* aOverflowList)
-{
- nsLineData* newLine = new nsLineData();
- if (nsnull != newLine) {
- nsIFrame* kid = aOverflowList;
- newLine->mFirstChild = kid;
- kid->GetContentIndex(newLine->mFirstContentOffset);
- newLine->mLastContentOffset = -1;
- newLine->mLastContentIsComplete = PRPackedBool(0x255);
- PRInt32 kids = 0;
- while (nsnull != kid) {
- kids++;
- kid->GetNextSibling(kid);
- }
- newLine->mChildCount = kids;
- }
- return newLine;
-}
-
-void
-nsBlockFrame::DrainOverflowList()
-{
- nsBlockFrame* prevBlock = (nsBlockFrame*) mPrevInFlow;
- if (nsnull != prevBlock) {
- nsIFrame* overflowList = prevBlock->mOverflowList;
- if (nsnull != overflowList) {
- NS_ASSERTION(nsnull == mFirstChild, "bad overflow list");
- NS_ASSERTION(nsnull == mLines, "bad overflow list");
-
- // Create a line to hold the entire overflow list
- nsLineData* newLine = CreateLineForOverflowList(overflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(overflowList);
- prevBlock->mOverflowList = nsnull;
-
- // The new line is the first line
- mLines = newLine;
- }
- }
-
- if (nsnull != mOverflowList) {
- NS_ASSERTION(nsnull != mFirstChild,
- "overflow list but no mapped children");
-
- // Create a line to hold the overflow list
- nsLineData* newLine = CreateLineForOverflowList(mOverflowList);
-
- // Place the children on our child list; this also reassigns
- // their geometric parent and updates our mChildCount.
- AppendChildren(mOverflowList, PR_FALSE);
- mOverflowList = nsnull;
-
- // The new line is appended after our other lines
- nsLineData* prevLine = nsnull;
- nsLineData* line = mLines;
- while (nsnull != line) {
- prevLine = line;
- line = line->mNextLine;
- }
- if (nsnull == prevLine) {
- mLines = newLine;
- }
- else {
- prevLine->mNextLine = newLine;
- newLine->mPrevLine = prevLine;
- }
- }
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_FALSE);
- }
-#endif
-}
-
-void
-nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint8 aBreakType)
-{
- for (;;) {
- if (aState.mCurrentBand.count <= 1) {
- // No floaters in this band therefore nothing to clear
- break;
- }
-
- // Find the Y coordinate to clear to
- nscoord clearYMost = aState.mY;
- nsRect tmp;
- PRInt32 i;
- for (i = 0; i < aState.mCurrentBand.count; i++) {
- const nsStyleDisplay* display;
- nsBandTrapezoid* trapezoid = &aState.mCurrentBand.data[i];
- if (trapezoid->state != nsBandTrapezoid::Available) {
- if (nsBandTrapezoid::OccupiedMultiple == trapezoid->state) {
- PRInt32 fn, numFrames = trapezoid->frames->Count();
- NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
- for (fn = 0; fn < numFrames; fn++) {
- nsIFrame* f = (nsIFrame*) trapezoid->frames->ElementAt(fn);
- f->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
-
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- else {
- trapezoid->frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&)display);
- switch (display->mFloats) {
- case NS_STYLE_FLOAT_LEFT:
- if ((NS_STYLE_CLEAR_LEFT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- case NS_STYLE_FLOAT_RIGHT:
- if ((NS_STYLE_CLEAR_RIGHT == aBreakType) ||
- (NS_STYLE_CLEAR_LEFT_AND_RIGHT == aBreakType)) {
- trapezoid->GetRect(tmp);
- nscoord ym = tmp.YMost();
- if (ym > clearYMost) {
- clearYMost = ym;
- }
- }
- break;
- }
- }
- }
- }
-
- if (clearYMost == aState.mY) {
- // Nothing to clear
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::ClearFloaters: mY=%d clearYMost=%d\n",
- aState.mY, clearYMost));
-
- aState.mY = clearYMost + 1;
-
- // Get a new band
- GetAvailableSpace(aState, aState.mY);
- }
-}
-
-nsresult
-nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
- nsLineLayout& aLineLayout,
- nsLineData* aLine)
-{
- // Before we place the line, make sure that it will fit in it's new
- // location. It always fits if the height isn't constrained or it's
- // the first line.
- if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
- if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
- // The line will not fit
- return PushLines(aState, aLine);
- }
- }
-
- // When the line is finally placed then we know that the child
- // frames have a stable location. This means that we can DidReflow
- // them marking them done. Note that when we are paginated this
- // optimization cannot be done because this may be a nested block
- // that will be pushed to a new page by the containing block and the
- // nested block can't know that during its reflow.
- // XXX and actually, this only always works for the block which is a
- // child of the body.
- if (!aState.mPresContext->IsPaginated()) {
- nsIAtom* tag = mContent->GetTag();
- if (nsHTMLAtoms::body == tag) {
- nsIFrame* child = aLine->mFirstChild;
- for (PRInt32 i = aLine->mChildCount; --i >= 0; ) {
- nsFrameState state;
- child->GetFrameState(state);
- if (NS_FRAME_IN_REFLOW & state) {
- child->DidReflow(*aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
- }
- child->GetNextSibling(child);
- }
-
- // Paint this portion of ourselves
- if (!aLine->mBounds.IsEmpty()) {
- Invalidate(aLine->mBounds);
- }
- }
- NS_IF_RELEASE(tag);
- }
-
- // Consume space and advance running values
- aState.mY += aLine->mBounds.height;
- if (nsnull != aState.mMaxElementSizePointer) {
- nsSize* maxSize = aState.mMaxElementSizePointer;
- if (aLineLayout.mState.mMaxElementSize.width > maxSize->width) {
- maxSize->width = aLineLayout.mState.mMaxElementSize.width;
- }
- if (aLineLayout.mState.mMaxElementSize.height > maxSize->height) {
- maxSize->height = aLineLayout.mState.mMaxElementSize.height;
- }
- }
- nscoord xmost = aLine->mBounds.XMost();
- if (xmost > aState.mKidXMost) {
- aState.mKidXMost = xmost;
- }
-
- // Process any pending break operations
- switch (aLineLayout.mPendingBreak) {
- default:
- break;
- case NS_STYLE_CLEAR_LEFT:
- case NS_STYLE_CLEAR_RIGHT:
- case NS_STYLE_CLEAR_LEFT_AND_RIGHT:
- ClearFloaters(aState, aLineLayout.mPendingBreak);
- break;
- }
- // XXX for now clear the pending break; this is where support for
- // page breaks or column breaks could be partially handled.
- aLineLayout.mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- // Any below current line floaters to place?
- // XXX We really want to know whether this is the initial reflow (reflow
- // unmapped) or a subsequent reflow in which case we only need to offset
- // the existing floaters...
- if (aState.mPendingFloaters.Count() > 0) {
- if (nsnull == aLine->mFloaters) {
- aLine->mFloaters = new nsVoidArray;
- }
- aLine->mFloaters->operator=(aState.mPendingFloaters);
- aState.mPendingFloaters.Clear();
- }
-
- if (nsnull != aLine->mFloaters) {
- PlaceBelowCurrentLineFloaters(aState, aLine->mFloaters, aState.mY);
- // XXX Factor in the height of the floaters as well when considering
- // whether the line fits.
- // The default policy is that if there isn't room for the floaters then
- // both the line and the floaters are pushed to the next-in-flow...
- }
-
- if (aState.mY >= aState.mCurrentBand.availSpace.YMost()) {
- // The current y coordinate is now past our available space
- // rectangle. Get a new band of space.
- GetAvailableSpace(aState, aState.mY);
- }
-
- return NS_LINE_LAYOUT_COMPLETE;
-}
-
-// aY has borderpadding.top already factored in
-nsresult
-nsBlockFrame::GetAvailableSpace(nsBlockReflowState& aState, nscoord aY)
-{
- nsresult rv = NS_OK;
-
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Fill in band data for the specific Y coordinate
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->GetBandData(aY, aState.mAvailSize, aState.mCurrentBand);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Compute the bounding rect of the available space, i.e. space
- // between any left and right floaters
- aState.mCurrentBand.ComputeAvailSpaceRect();
-
- aState.mCurrentBand.availSpace.MoveBy(aState.mBorderPadding.left,
- aState.mY);
-
- return rv;
-}
-
-// Give aLine and any successive lines to the block's next-in-flow; if
-// we don't have a next-in-flow then push all the children onto our
-// overflow list.
-nsresult
-nsBlockFrame::PushLines(nsBlockReflowState& aState, nsLineData* aLine)
-{
- PRInt32 i;
-
- // Split our child-list in two; revert our last content offset and
- // completion status to the previous line.
- nsLineData* prevLine = aLine->mPrevLine;
- NS_PRECONDITION(nsnull != prevLine, "pushing first line");
- nsIFrame* prevKidFrame = prevLine->mFirstChild;
- for (i = prevLine->mChildCount - 1; --i >= 0; ) {
- prevKidFrame->GetNextSibling(prevKidFrame);
- }
-#ifdef NS_DEBUG
- nsIFrame* nextFrame;
- prevKidFrame->GetNextSibling(nextFrame);
- NS_ASSERTION(nextFrame == aLine->mFirstChild, "bad line list");
-#endif
- prevKidFrame->SetNextSibling(nsnull);
- prevLine->mNextLine = nsnull;
- mLastContentOffset = prevLine->mLastContentOffset;
- mLastContentIsComplete = prevLine->mLastContentIsComplete;
-
- // Push children to our next-in-flow if we have, or to our overflow list
- nsBlockFrame* nextInFlow = (nsBlockFrame*) mNextInFlow;
- PRInt32 pushCount = 0;
- if (nsnull == nextInFlow) {
- // Place children on the overflow list
- mOverflowList = aLine->mFirstChild;
-
- // Destroy the lines
- nsLineData* line = aLine;
- while (nsnull != line) {
- pushCount += line->mChildCount;
- nsLineData* next = line->mNextLine;
- delete line;
- line = next;
- }
- }
- else {
- aLine->mPrevLine = nsnull;
-
- // Pass on the children to our next-in-flow
- nsLineData* line = aLine;
- prevLine = line;
- nsIFrame* lastKid = aLine->mFirstChild;
- nsIFrame* kid = lastKid;
- while (nsnull != line) {
- i = line->mChildCount;
- pushCount += i;
- NS_ASSERTION(kid == line->mFirstChild, "bad line list");
- while (--i >= 0) {
- kid->SetGeometricParent(nextInFlow);
- nsIFrame* contentParent;
- kid->GetContentParent(contentParent);
- if (this == contentParent) {
- kid->SetContentParent(nextInFlow);
- }
- lastKid = kid;
- kid->GetNextSibling(kid);
- }
- prevLine = line;
- line = line->mNextLine;
- }
-
- // Join the two line lists
- nsLineData* nextInFlowLine = nextInFlow->mLines;
- if (nsnull != nextInFlowLine) {
- lastKid->SetNextSibling(nextInFlowLine->mFirstChild);
- nextInFlowLine->mPrevLine = prevLine;
- }
- nsIFrame* firstKid = aLine->mFirstChild;
- prevLine->mNextLine = nextInFlowLine;
- nextInFlow->mLines = aLine;
- nextInFlow->mFirstChild = firstKid;
- nextInFlow->mChildCount += pushCount;
- firstKid->GetContentIndex(nextInFlow->mFirstContentOffset);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- nextInFlow->VerifyLines(PR_FALSE);
- }
-#endif
- }
- mChildCount -= pushCount;
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return NS_LINE_LAYOUT_NOT_COMPLETE;
-}
-
-nsresult
-nsBlockFrame::ReflowMapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // See if we have any run-in floaters to place
- if (nsnull != mRunInFloaters) {
- PlaceBelowCurrentLineFloaters(aState, mRunInFloaters, aState.mY);
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- nsLineData* line = mLines;
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != line) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);/* XXX move out of loop */
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-// XXX This is a short-term hack. It assumes that the caller has already recovered
-// the state, and that some space has been retrieved from the space manager...
-nsresult
-nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- while (nsnull != aLine) {
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, aLine);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, aLine);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
-
- mLastContentOffset = aLine->mLastContentOffset;
- mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
- aLine = aLine->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
-{
- nsresult rv = NS_OK;
-
- // If we have no children and we have a prev-in-flow then we need to
- // pick up where it left off. If we have children, e.g. we're being
- // resized, then our content offset will have already been set
- // correctly.
- nsIFrame* kidPrevInFlow = nsnull;
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsBlockFrame* prev = (nsBlockFrame*) mPrevInFlow;
- mFirstContentOffset = prev->NextChildOffset();// XXX Is this necessary?
- if (PR_FALSE == prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
-
- // Get to the last line where the new content may be added
- nsLineData* line = nsnull;
- nsLineData* prevLine = nsnull;
- if (nsnull != mLines) {
- line = mLines;
- while (nsnull != line->mNextLine) {
- line = line->mNextLine;
- }
- prevLine = line->mPrevLine;
-
- // If the last line is not complete then kidPrevInFlow should be
- // set to the last-line's last child.
- if (!line->mLastContentIsComplete) {
- kidPrevInFlow = line->GetLastChild();
- }
- }
-
- // Get some space to start reflowing with
- GetAvailableSpace(aState, aState.mY);
-
- // Now reflow the new content until we are out of new content or out
- // of vertical space.
- PRInt32 kidIndex = NextChildOffset();
- nsLineLayout lineLayout(aState);
- aState.mCurrentLine = &lineLayout;
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- PRInt32 contentChildCount = mContent->ChildCount();
- while (kidIndex < contentChildCount) {
- if (nsnull == line) {
- if (!MoreToReflow(aState)) {
- break;
- }
- line = new nsLineData();
- if (nsnull == line) {
- rv = NS_ERROR_OUT_OF_MEMORY;
- goto done;
- }
- line->mFirstContentOffset = kidIndex;
- }
-
- // Initialize the line layout for this line
- rv = lineLayout.Initialize(aState, line);
- if (NS_OK != rv) {
- goto done;
- }
- lineLayout.mKidPrevInFlow = kidPrevInFlow;
- lineLayout.mState.mPrevKidFrame = aState.mPrevKidFrame;
-
- // Reflow the line
- nsresult lineReflowStatus = lineLayout.ReflowLine();
- if (PRInt32(lineReflowStatus) < 0) {
- // Some kind of hard error
- rv = lineReflowStatus;
- goto done;
- }
- mChildCount += lineLayout.mNewFrames;
-
- // Add line to the block; do this before placing the line in case
- // PushLines is needed.
- if (nsnull == prevLine) {
- // For the first line, initialize mFirstContentOffset
- mFirstContentOffset = line->mFirstContentOffset;
- mFirstChild = line->mFirstChild;
- mLines = line;
- }
- else {
- prevLine->mNextLine = line;
- line->mPrevLine = prevLine;
- }
-
- // Now place it. It's possible it won't fit.
- rv = PlaceLine(aState, lineLayout, line);
- if (NS_LINE_LAYOUT_COMPLETE != rv) {
- goto done;
- }
- kidIndex = lineLayout.mState.mKidIndex;
- kidPrevInFlow = lineLayout.mKidPrevInFlow;
-
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- prevLine = line;
- line = line->mNextLine;
- aState.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
- }
-
-done:
- aState.mCurrentLine = nsnull;
- if (aState.mBlockIsPseudo) {
- PropagateContentOffsets();
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- }
-#endif
- return rv;
-}
-
-nsresult
-nsBlockFrame::InitializeState(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize,
- nsBlockReflowState& aState)
-{
- nsresult rv;
- rv = aState.Initialize(aPresContext, aSpaceManager,
- aReflowState, aMaxElementSize, this);
-
- // Apply border and padding adjustments for regular frames only
- if (!aState.mBlockIsPseudo) {
- const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStylePosition* myPosition = (const nsStylePosition*)
- mStyleContext->GetStyleData(eStyleStruct_Position);
-
- mySpacing->CalcBorderPaddingFor(this, aState.mBorderPadding);
- aState.mY = aState.mBorderPadding.top;
- aState.mX = aState.mBorderPadding.left;
-
- if (aState.mUnconstrainedWidth) {
- // If our width is unconstrained don't bother futzing with the
- // available width/height because they don't matter - we are
- // going to get reflowed again.
- aState.mDeltaWidth = NS_UNCONSTRAINEDSIZE;
- }
- else {
- // When we are constrained we need to apply the width/height
- // style properties. When we have a width/height it applies to
- // the content width/height of our box. The content width/height
- // doesn't include the border+padding so we have to add that in
- // instead of subtracting it out of our maxsize.
- nscoord lr =
- aState.mBorderPadding.left + aState.mBorderPadding.right;
-
- // Get and apply the stylistic size. Note: do not limit the
- // height until we are done reflowing.
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState,
- aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aState.mAvailSize.width = aState.mStyleSize.width + lr;
- }
- else {
- aState.mAvailSize.width -= lr;
- }
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
- }
- else {
- aState.mBorderPadding.SizeTo(0, 0, 0, 0);
- aState.mDeltaWidth = aState.mAvailSize.width - mRect.width;
- }
-
- // Setup initial list ordinal value
- nsIAtom* tag = mContent->GetTag();
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- nsHTMLValue value;
- if (eContentAttr_HasValue ==
- ((nsIHTMLContent*)mContent)->GetAttribute(nsHTMLAtoms::start, value)) {
- if (eHTMLUnit_Integer == value.GetUnit()) {
- aState.mNextListOrdinal = value.GetIntValue();
- }
- }
- }
- NS_RELEASE(tag);
-
- // Setup list flags in block reflow state if this block is a list
- // item.
- const nsStyleDisplay* myDisplay = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_DISPLAY_LIST_ITEM == myDisplay->mDisplay) {
- const nsStyleList* myList = (const nsStyleList*)
- mStyleContext->GetStyleData(eStyleStruct_List);
- if (NS_STYLE_LIST_STYLE_POSITION_OUTSIDE == myList->mListStylePosition) {
- aState.mListPositionOutside = PR_TRUE;
- }
- }
-
- return rv;
-}
-
-PRBool
-nsBlockFrame::MoreToReflow(nsBlockReflowState& aState)
-{
- PRBool rv = PR_FALSE;
- if (NextChildOffset() < mContent->ChildCount()) {
- rv = PR_TRUE;
- }
- return rv;
-}
-
-nsBlockReflowState*
-nsBlockFrame::FindBlockReflowState(nsIPresContext* aPresContext,
- nsIFrame* aFrame)
-{
- nsBlockReflowState* state = nsnull;
- if (nsnull != aFrame) {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
- while (nsnull != parent) {
- nsBlockFrame* block;
- nsresult rv = parent->QueryInterface(kBlockFrameCID, (void**) &block);
- if (NS_OK == rv) {
- nsIPresShell* shell = aPresContext->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(block);
- NS_RELEASE(shell);
- break;
- }
- parent->GetGeometricParent(parent);
- }
- }
- return state;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::ContentAppended(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer)
-{
- return nsHTMLContainerFrame::ContentAppended(aShell, aPresContext, aContainer);
-}
-
-NS_METHOD
-nsBlockFrame::ContentInserted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- return nsHTMLContainerFrame::ContentInserted(aShell, aPresContext, aContainer,
- aChild, aIndexInParent);
-}
-
-NS_METHOD
-nsBlockFrame::ContentReplaced(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aOldChild,
- nsIContent* aNewChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-NS_METHOD
-nsBlockFrame::ContentDeleted(nsIPresShell* aShell,
- nsIPresContext* aPresContext,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInParent)
-{
- nsresult rv = NS_OK;
- return rv;
-}
-
-// XXX if there is nothing special going on here, then remove this
-// implementation and let nsFrame do it.
-NS_METHOD
-nsBlockFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nsresult rv = NS_OK;
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = mRect.height;
- aMetrics.descent = 0;
- return rv;
-}
-
-//----------------------------------------------------------------------
-
-NS_METHOD
-nsBlockFrame::Reflow(nsIPresContext* aPresContext,
- nsISpaceManager* aSpaceManager,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsRect& aDesiredRect,
- nsReflowStatus& aStatus)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PreReflowCheck();
- }
-#endif
-
- nsBlockReflowState state;
- nsresult rv = NS_OK;
-
- if (eReflowReason_Initial == aReflowState.reason) {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 == (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 != (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
- else {
-//XXX remove this code and uncomment the assertion when the table code plays nice
-#ifdef NS_DEBUG
- if (0 != (NS_FRAME_FIRST_REFLOW & mState)) {
- printf("XXX: table code isn't setting the reflow reason properly! [nsBlockFrame.cpp]\n");
- }
-#endif
-//XXX NS_ASSERTION(0 == (NS_FRAME_FIRST_REFLOW & mState), "bad mState");
- }
-
- aStatus = NS_FRAME_COMPLETE;
- rv = InitializeState(aPresContext, aSpaceManager, aReflowState,
- aDesiredSize.maxElementSize, state);
-
- NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d",
- aReflowState.reason, state.mDeltaWidth));
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- nsIPresShell* shell = state.mPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Is the reflow command target at us?
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
- if (this == target) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- if (nsIReflowCommand::FrameAppended == type) {
- nsLineData* lastLine = LastLine();
-
- // Restore the state
- if (nsnull != lastLine) {
- state.RecoverState(lastLine);
- }
-
- // Reflow unmapped children
- PRInt32 kidIndex = NextChildOffset();
- PRInt32 contentChildCount = mContent->ChildCount();
- if (kidIndex == contentChildCount) {
- // There is nothing to do here
- if (nsnull != lastLine) {
- state.mY = lastLine->mBounds.YMost();
- }
- }
- else {
- rv = ReflowUnmapped(state);
- }
- } else {
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- }
- } else {
- // The command is passing through us. Get the next frame in the
- // reflow chain
- nsIFrame* nextFrame;
- aReflowState.reflowCommand->GetNext(nextFrame);
-
- // Restore our state as if nextFrame is the next frame to reflow
- nsLineData* line = FindLine(nextFrame);
- state.RecoverState(line);
-
- // Get some available space to start reflowing with
- GetAvailableSpace(state, state.mY);
-
- // Reflow the affected line
- nsLineLayout lineLayout(state);
-
- state.mCurrentLine = &lineLayout;
- lineLayout.Initialize(state, line);
-
- // Have the line handle the incremental reflow
- nsRect oldBounds = line->mBounds;
- rv = lineLayout.IncrementalReflowFromChild(aReflowState.reflowCommand,
- nextFrame);
-
- // Now place the line. It's possible it won't fit
- rv = PlaceLine(state, lineLayout, line);
- // XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- mLastContentOffset = line->mLastContentOffset;
- mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
- state.mPrevKidFrame = lineLayout.mState.mPrevKidFrame;
-
- // Now figure out what to do with the frames that follow
- rv = IncrementalReflowAfter(state, line, rv, oldBounds);
- }
- }
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- } else {
- nsresult rv = NS_OK;
- nsIPresShell* shell = aPresContext->GetShell();
- shell->PutCachedData(this, &state);
-
- // Check for an overflow list
- DrainOverflowList();
-
- if (nsnull != mLines) {
- rv = ReflowMapped(state);
- }
-
- if (NS_OK == rv) {
- if ((nsnull != mLines) && (state.mAvailSize.height <= 0)) {
- // We are out of space
- }
- if (MoreToReflow(state)) {
- rv = ReflowUnmapped(state);
- }
- }
-
-#ifdef NS_DEBUG
- if (0 != mContent->ChildCount()) {
- NS_ASSERTION(nsnull != mLines, "reflowed zero children");
- }
-#endif
-
- // Return our desired rect
- ComputeDesiredRect(state, aReflowState.maxSize, aDesiredRect);
-
- // Set return status
- aStatus = NS_FRAME_COMPLETE;
- if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
- rv = NS_OK;
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
-
- // Now that reflow has finished, remove the cached pointer
- shell->RemoveCachedData(this);
- NS_RELEASE(shell);
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLines(PR_TRUE);
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsBlockFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredRect.width, aDesiredRect.height));
- return rv;
-}
-
-nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
-{
- // Find the line that contains the aFrame
- nsLineData* line = mLines;
- while (nsnull != line) {
- nsIFrame* child = line->mFirstChild;
- for (PRInt32 count = line->mChildCount; count > 0; count--) {
- if (child == aFrame) {
- return line;
- }
-
- child->GetNextSibling(child);
- }
-
- // Move to the next line
- line = line->mNextLine;
- }
-
- return nsnull;
-}
-
-nsLineData* nsBlockFrame::LastLine()
-{
- nsLineData* lastLine = mLines;
-
- // Get the last line
- if (nsnull != lastLine) {
- while (nsnull != lastLine->mNextLine) {
- lastLine = lastLine->mNextLine;
- }
- }
-
- return lastLine;
-}
-
-nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
- nsLineData* aLine,
- nsresult aReflowStatus,
- const nsRect& aOldBounds)
-{
- // Now just reflow all the lines that follow...
- // XXX Obviously this needs to be more efficient
- return ReflowMappedFrom(aState, aLine->mNextLine);
-}
-
-void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
- const nsSize& aMaxSize,
- nsRect& aDesiredRect)
-{
- aDesiredRect.x = 0;
- aDesiredRect.y = 0;
-
- // Special check for zero sized content: If our content is zero
- // sized then we collapse into nothingness.
- if ((0 == aState.mKidXMost - aState.mBorderPadding.left) &&
- (0 == aState.mY - aState.mBorderPadding.top)) {
- aDesiredRect.width = 0;
- aDesiredRect.height = 0;
- }
- else {
- aDesiredRect.width = aState.mKidXMost + aState.mBorderPadding.right;
- if (!aState.mUnconstrainedWidth) {
- // Make sure we're at least as wide as the max size we were given
- nscoord maxWidth = aState.mAvailSize.width + aState.mBorderPadding.left +
- aState.mBorderPadding.right;
- if (aDesiredRect.width < maxWidth) {
- aDesiredRect.width = maxWidth;
- }
- }
- aState.mY += aState.mBorderPadding.bottom;
- nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
- aState.mPrevNegBottomMargin;
- if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
- // It's possible that we don't have room for the last bottom
- // margin (the last bottom margin is the margin following a block
- // element that we contain; it isn't applied immediately because
- // of the margin collapsing logic). This can happen when we are
- // reflowed in a limited amount of space because we don't know in
- // advance what the last bottom margin will be.
- nscoord maxY = aMaxSize.height;
- if (aState.mY + lastBottomMargin > maxY) {
- lastBottomMargin = maxY - aState.mY;
- if (lastBottomMargin < 0) {
- lastBottomMargin = 0;
- }
- }
- }
- aState.mY += lastBottomMargin;
- aDesiredRect.height = aState.mY;
-
- if (!aState.mBlockIsPseudo) {
- // Clamp the desired rect height when style height applies
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredRect.height = aState.mBorderPadding.top +
- aState.mStyleSize.height + aState.mBorderPadding.bottom;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-
-void nsBlockFrame::ReflowFloater(nsIPresContext* aPresContext,
- nsBlockReflowState& aState,
- nsIFrame* aFloaterFrame)
-{
- // Compute the available space for the floater. Use the default
- // 'auto' width and height values
- nsSize kidAvailSize(0, NS_UNCONSTRAINEDSIZE);
- nsSize styleSize;
- PRIntn styleSizeFlags = nsCSSLayout::GetStyleSize(aPresContext, *aState.reflowState,
- styleSize);
-
- // XXX The width and height are for the content area only. Add in space for
- // border and padding
- if (styleSizeFlags & NS_SIZE_HAS_WIDTH) {
- kidAvailSize.width = styleSize.width;
- }
- if (styleSizeFlags & NS_SIZE_HAS_HEIGHT) {
- kidAvailSize.height = styleSize.height;
- }
-
- // Resize reflow the anchored item into the available space
- // XXX Check for complete?
- nsReflowMetrics desiredSize(nsnull);
- nsReflowState reflowState(aFloaterFrame, *aState.reflowState, kidAvailSize,
- eReflowReason_Initial);
- nsReflowStatus status;
-
- aFloaterFrame->WillReflow(*aPresContext);
- aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status);
- aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height);
-
- aFloaterFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
-}
-
-PRBool
-nsBlockFrame::AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
-
- if (nsnull != state) {
- // Get the frame associated with the space manager, and get its
- // nsIAnchoredItems interface
- nsIFrame* frame = state->mSpaceManager->GetFrame();
- nsIAnchoredItems* anchoredItems = nsnull;
-
- frame->QueryInterface(kIAnchoredItemsIID, (void**)&anchoredItems);
- NS_ASSERTION(nsnull != anchoredItems, "no anchored items interface");
- if (nsnull != anchoredItems) {
- anchoredItems->AddAnchoredItem(aFloater,
- nsIAnchoredItems::anHTMLFloater,
- this);
-
- // Reflow the floater
- ReflowFloater(aPresContext, *state, aFloater);
-
- // Determine whether we place it at the top or we place it below the
- // current line
- if (IsLeftMostChild(aPlaceholder)) {
- if (nsnull == mRunInFloaters) {
- mRunInFloaters = new nsVoidArray;
- }
- mRunInFloaters->AppendElement(aPlaceholder);
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- } else {
- // Add the placeholder to our to-do list
- state->mPendingFloaters.AppendElement(aPlaceholder);
- }
- return PR_TRUE;
- }
- }
-
- return PR_FALSE;
-}
-
-// XXX Deprecated
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder)
-{
-#if 0
- nsIPresShell* shell = aPresContext->GetShell();
- nsBlockReflowState* state = (nsBlockReflowState*) shell->GetCachedData(this);
- NS_RELEASE(shell);
- if (nsnull != state) {
- PlaceFloater(aPresContext, aFloater, aPlaceholder, *state);
- }
-#endif
-}
-
-PRBool
-nsBlockFrame::IsLeftMostChild(nsIFrame* aFrame)
-{
- do {
- nsIFrame* parent;
- aFrame->GetGeometricParent(parent);
-
- // See if there are any non-zero sized child frames that precede
- // aFrame in the child list
- nsIFrame* child;
- parent->FirstChild(child);
- while ((nsnull != child) && (aFrame != child)) {
- nsSize size;
-
- // Is the child zero-sized?
- child->GetSize(size);
- if ((size.width > 0) || (size.height > 0)) {
- // We found a non-zero sized child frame that precedes aFrame
- return PR_FALSE;
- }
- child->GetNextSibling(child);
- }
-
- // aFrame is the left-most non-zero sized frame in its geometric parent.
- // Walk up one level and check that its parent is left-most as well
- aFrame = parent;
- } while (aFrame != this);
- return PR_TRUE;
-}
-
-// Used when placing run-in floaters (floaters displayed at the top of the
-// block as supposed to below the current line)
-void
-nsBlockFrame::PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder,
- nsBlockReflowState& aState)
-{
- nsISpaceManager* sm = aState.mSpaceManager;
-
- // Get the type of floater
- const nsStyleDisplay* floaterDisplay;
- aFloater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay);
-
- // Commit some space in the space manager, and adjust our current
- // band of available space.
- nsRect region;
- aFloater->GetRect(region);
- region.y = aState.mY;
- if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
- region.x = aState.mX;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats,
- "bad float type");
- region.x = aState.mCurrentBand.availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- sm->AddRectRegion(aFloater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- aFloater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
-
- // Update the band of available space to reflect space taken up by
- // the floater
- GetAvailableSpace(aState, aState.mY);
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-// XXX It's unclear what coordinate space aY is in. Is it relative to the
-// upper-left origin of the containing block, or relative to aState.mY?
-void
-nsBlockFrame::PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
- nsVoidArray* aFloaterList,
- nscoord aY)
-{
- NS_PRECONDITION(aFloaterList->Count() > 0, "no floaters");
-
- nsISpaceManager* sm = aState.mSpaceManager;
- nsBlockBandData* bd = &aState.mCurrentBand;
-
- // XXX Factor this code with PlaceFloater()...
- PRInt32 numFloaters = aFloaterList->Count();
- for (PRInt32 i = 0; i < numFloaters; i++) {
- nsPlaceholderFrame* placeholderFrame = (nsPlaceholderFrame*)aFloaterList->ElementAt(i);
- nsIFrame* floater = placeholderFrame->GetAnchoredItem();
- nsRect region;
-
- // Get the band of available space
- // XXX This is inefficient to do this inside the loop...
- GetAvailableSpace(aState, aY);
-
- // Get the type of floater
- const nsStyleDisplay* sd;
- floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)sd);
-
- floater->GetRect(region);
- // XXX GetAvailableSpace() is translating availSpace by aState.mY...
- region.y = bd->availSpace.y - aState.mY;
- if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
- region.x = bd->availSpace.x;
- } else {
- NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
- region.x = bd->availSpace.XMost() - region.width;
- }
-
- // XXX Don't forget the floater's margins...
- sm->Translate(aState.mBorderPadding.left, 0);
- // XXX Temporary incremental hack
- sm->RemoveRegion(floater);
- sm->AddRectRegion(floater, region);
-
- // Set the origin of the floater in world coordinates
- nscoord worldX, worldY;
- sm->GetTranslation(worldX, worldY);
- floater->MoveTo(region.x + worldX, region.y + worldY);
- sm->Translate(-aState.mBorderPadding.left, 0);
- }
-
- // Pass on updated available space to the current line
- if (nsnull != aState.mCurrentLine) {
- nsLineLayout& lineLayout = *aState.mCurrentLine;
- GetAvailableSpace(aState, aY);
- lineLayout.SetReflowSpace(aState.mCurrentBand.availSpace);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineData*
-nsBlockFrame::GetFirstLine()
-{
- return mLines;
-}
-
-PRIntn
-nsBlockFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_TOP;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_BOTTOM;
- }
- return skip;
-}
diff --git a/mozilla/layout/html/base/src/nsBodyFrame.cpp b/mozilla/layout/html/base/src/nsBodyFrame.cpp
index 64b40cba17a..a5d4b7d306b 100644
--- a/mozilla/layout/html/base/src/nsBodyFrame.cpp
+++ b/mozilla/layout/html/base/src/nsBodyFrame.cpp
@@ -18,7 +18,6 @@
#include "nsBodyFrame.h"
#include "nsIContent.h"
#include "nsIContentDelegate.h"
-#include "nsBlockFrame.h"
#include "nsIReflowCommand.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
@@ -26,12 +25,11 @@
#include "nsIPresShell.h"
#include "nsIViewManager.h"
#include "nsIDeviceContext.h"
-#include "nsBlockFrame.h"
+#include "nsIRunaround.h"
#include "nsSpaceManager.h"
#include "nsHTMLAtoms.h"
-
-static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
-static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
+#include "nsHTMLIIDs.h"
+#include "nsCSSBlockFrame.h"
nsresult nsBodyFrame::NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
@@ -78,27 +76,28 @@ nsBodyFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
void nsBodyFrame::CreateColumnFrame(nsIPresContext* aPresContext)
{
+ nsIStyleContext* styleContext =
+ aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, this);
+
// Do we have a prev-in-flow?
if (nsnull == mPrevInFlow) {
// No, create a column pseudo frame
- nsBlockFrame::NewFrame(&mFirstChild, mContent, this);
+ NS_NewCSSBlockFrame(&mFirstChild, mContent, this);
mChildCount = 1;
-
- // Resolve style and set the style context
- nsIStyleContext* styleContext =
- aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, this);
mFirstChild->SetStyleContext(aPresContext,styleContext);
- NS_RELEASE(styleContext);
} else {
- nsBodyFrame* prevBody = (nsBodyFrame*)mPrevInFlow;
-
- nsIFrame* prevColumn = prevBody->mFirstChild;
- NS_ASSERTION(prevBody->ChildIsPseudoFrame(prevColumn), "bad previous column");
-
// Create a continuing column
- prevColumn->CreateContinuingFrame(aPresContext, this, nsnull, mFirstChild);
+ nsBodyFrame* prevBody = (nsBodyFrame*)mPrevInFlow;
+ nsIFrame* prevColumn = prevBody->mFirstChild;
+ NS_ASSERTION(prevBody->ChildIsPseudoFrame(prevColumn),
+ "bad previous column");
+
+ prevColumn->CreateContinuingFrame(aPresContext, this, styleContext,
+ mFirstChild);
mChildCount = 1;
}
+
+ NS_RELEASE(styleContext);
}
nsSize nsBodyFrame::GetColumnAvailSpace(nsIPresContext* aPresContext,
@@ -240,11 +239,15 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext,
mFirstChild->SetRect(desiredRect);
mFirstChild->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
+#if XXX
+ // the block knows to PropagateContentOffsets so this isn't necessary
+
// Set our last content offset and whether the last content is complete
// based on the state of the pseudo frame
- nsBlockFrame* blockPseudoFrame = (nsBlockFrame*)mFirstChild;
+ nsCSSBlockFrame* blockPseudoFrame = (nsCSSBlockFrame*)mFirstChild;
mLastContentOffset = blockPseudoFrame->GetLastContentOffset();
mLastContentIsComplete = blockPseudoFrame->GetLastContentIsComplete();
+#endif
// Return our desired size
ComputeDesiredSize(desiredRect, aReflowState.maxSize, borderPadding, aDesiredSize);
@@ -260,7 +263,8 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext,
}
}
- NS_FRAME_TRACE_MSG(("exit nsBodyFrame::Reflow: status=%d width=%d height=%d",
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("exit nsBodyFrame::Reflow: status=%d width=%d height=%d",
aStatus, aDesiredSize.width, aDesiredSize.height));
return NS_OK;
}
diff --git a/mozilla/layout/html/base/src/nsHTMLBullet.cpp b/mozilla/layout/html/base/src/nsHTMLBullet.cpp
index 5666a8a6fc5..8578ffb12f8 100644
--- a/mozilla/layout/html/base/src/nsHTMLBullet.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLBullet.cpp
@@ -18,7 +18,9 @@
#include "nsHTMLParts.h"
#include "nsHTMLTagContent.h"
#include "nsLeafFrame.h"
-#include "nsBlockFrame.h"
+#include "nsCSSBlockFrame.h"
+#include "nsIInlineReflow.h"
+#include "nsCSSLineLayout.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsIRenderingContext.h"
@@ -32,6 +34,21 @@
#include "nsHTMLBase.h"
#include "nsIView.h"
+// XXX eliminate the bullet numbering hackery:
+
+// 1) use a dependency graph of some sort that is updated when LI's
+// come and go in the content model (how do we invalidate it when a
+// content change occurs?): maybe for block's that are display:
+// list-item, they keep a side data structure that is the ordinal data
+// for it's children LI's?
+
+// 2) Alternatively, have the LI's number themselves automatically and
+// use a GetAttribute on the content to discover the correct number (N^2)
+
+// XXX Also eliminate the way that we find the
+// nsCSSBlockReflowState!!! It's bogus beyond belief! An ISA
+// QueryInterface on the reflow-state should do the trick.
+
class Bullet : public nsHTMLTagContent {
public:
Bullet();
@@ -49,40 +66,45 @@ public:
nsIFrame*& aResult);
};
-class BulletFrame : public nsLeafFrame {
+class BulletFrame : public nsFrame, nsIInlineReflow {
public:
BulletFrame(nsIContent* aContent, nsIFrame* aParentFrame);
virtual ~BulletFrame();
- NS_IMETHOD DeleteFrame();
+ // nsISupports
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+ // nsIFrame
+ NS_IMETHOD DeleteFrame();
NS_IMETHOD Paint(nsIPresContext &aCX,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
-
- NS_IMETHOD Reflow(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
-
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
+ // nsIInlineReflow
+ NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout);
+ NS_IMETHOD InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState);
+
protected:
- virtual void GetDesiredSize(nsIPresContext* aPresContext,
- const nsReflowState& aReflowState,
- nsReflowMetrics& aDesiredSize);
+ void GetDesiredSize(nsIPresContext* aPresContext,
+ nsCSSBlockReflowState* aBlockState,
+ const nsReflowState& aReflowState,
+ nsReflowMetrics& aMetrics);
- /**
- * Return the reflow state for the list container that contains this
- * list item frame. There may be no list container (a dangling LI)
- * therefore this may return nsnull.
- */
- nsBlockReflowState* GetListContainerReflowState(nsIPresContext* aCX);
+ PRInt32 GetListItemOrdinal(nsIPresContext* aCX,
+ nsCSSBlockReflowState* aBlockState,
+ const nsStyleList& aMol);
- PRInt32 GetListItemOrdinal(nsIPresContext* aCX, const nsStyleList& aMol);
+ void GetListItemText(nsIPresContext* aCX,
+ nsCSSBlockReflowState* aBlockState,
+ const nsStyleList& aMol,
+ nsString& aResult);
- void GetListItemText(nsIPresContext* aCX, nsString& aResult,
- const nsStyleList& aMol);
+ nsCSSBlockReflowState*
+ GetListContainerReflowState(nsIPresContext* aCX,
+ const nsReflowState& aReflowState);
PRPackedBool mOrdinalValid;
PRInt32 mOrdinal;
@@ -148,7 +170,7 @@ NS_NewHTMLBullet(nsIHTMLContent** aInstancePtrResult)
//----------------------------------------------------------------------
BulletFrame::BulletFrame(nsIContent* aContent, nsIFrame* aParentFrame)
- : nsLeafFrame(aContent, aParentFrame)
+ : nsFrame(aContent, aParentFrame)
{
}
@@ -156,12 +178,26 @@ BulletFrame::~BulletFrame()
{
}
+NS_IMETHODIMP
+BulletFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
+{
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ if (aIID.Equals(kIInlineReflowIID)) {
+ *aInstancePtrResult = (void*) ((nsIInlineReflow*)this);
+ return NS_OK;
+ }
+ return nsFrame::QueryInterface(aIID, aInstancePtrResult);
+}
+
NS_METHOD
BulletFrame::DeleteFrame()
{
// Release image loader first so that it's refcnt can go to zero
mImageLoader.DestroyLoader();
- return nsLeafFrame::DeleteFrame();
+ return nsFrame::DeleteFrame();
}
NS_METHOD
@@ -255,7 +291,7 @@ BulletFrame::Paint(nsIPresContext& aCX,
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
fm = aCX.GetMetricsFor(myFont->mFont);
- GetListItemText(&aCX, text, *myList);
+ GetListItemText(&aCX, nsnull, *myList, text);
aRenderingContext.SetFont(myFont->mFont);
aRenderingContext.DrawString(text, mPadding.left, mPadding.top,
fm->GetWidth(text));
@@ -266,73 +302,37 @@ BulletFrame::Paint(nsIPresContext& aCX,
return NS_OK;
}
-NS_METHOD
-BulletFrame::Reflow(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- GetDesiredSize(aCX, aReflowState, aDesiredSize);
- if (nsnull != aDesiredSize.maxElementSize) {
- aDesiredSize.maxElementSize->width = aDesiredSize.width;
- aDesiredSize.maxElementSize->height = aDesiredSize.height;
- }
-
- // Get cached state for containing block frame
- nsBlockReflowState* state =
- nsBlockFrame::FindBlockReflowState(aCX, this);
- if (nsnull != state) {
- nsLineLayout* lineLayoutState = state->mCurrentLine;
- if (nsnull != lineLayoutState) {
- lineLayoutState->mReflowResult =
- NS_LINE_LAYOUT_REFLOW_RESULT_AWARE;
- }
- }
-
- aStatus = NS_FRAME_COMPLETE;
- return NS_OK;
-}
+// XXX This is a hack to discover the block container that is keeping
+// track of our list item ordinal value
// Return the reflow state for the list container that contains this
// list item frame. There may be no list container (a dangling LI)
// therefore this may return nsnull.
-nsBlockReflowState*
-BulletFrame::GetListContainerReflowState(nsIPresContext* aCX)
+nsCSSBlockReflowState*
+BulletFrame::GetListContainerReflowState(nsIPresContext* aCX,
+ const nsReflowState& aReflowState)
{
- nsBlockReflowState* state = nsnull;
- nsIFrame* parent = mGeometricParent;
- while (nsnull != parent) {
- void* ft;
- nsresult status = parent->QueryInterface(kBlockFrameCID, &ft);
- if (NS_OK == status) {
- // The parent is a block. See if its content object is a list
- // container. Only UL, OL, MENU or DIR can be list containers.
- // XXX need something more flexible, say style?
- nsIContent* parentContent;
-
- parent->GetContent(parentContent);
- nsIAtom* tag = parentContent->GetTag();
- NS_RELEASE(parentContent);
- if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
- (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
- NS_RELEASE(tag);
- break;
- }
+ const nsReflowState* rs = aReflowState.parentReflowState;
+ while (nsnull != rs) {
+ nsIContent* content;
+ rs->frame->GetContent(content);
+ nsIAtom* tag = content->GetTag();
+ NS_RELEASE(content);
+ if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
+ (tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
NS_RELEASE(tag);
+ return (nsCSSBlockReflowState*) rs;
}
- parent->GetGeometricParent(parent);
+ NS_RELEASE(tag);
+ rs = rs->parentReflowState;
}
- if (nsnull != parent) {
- nsIPresShell* shell = aCX->GetShell();
- state = (nsBlockReflowState*) shell->GetCachedData(parent);
- NS_RELEASE(shell);
- }
- return state;
+ return nsnull;
}
PRInt32
-BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
- const nsStyleList& aListStyle)
+BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
+ nsCSSBlockReflowState* aReflowState,
+ const nsStyleList& aListStyle)
{
if (mOrdinalValid) {
return mOrdinal;
@@ -340,9 +340,6 @@ BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
PRInt32 ordinal = 0;
- // Get block reflow state for the list container
- nsBlockReflowState* state = GetListContainerReflowState(aCX);
-
// Try to get value directly from the list-item, if it specifies a
// value attribute. We do this with our parent's content.
nsHTMLValue value;
@@ -352,8 +349,8 @@ BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
if (eContentAttr_HasValue == html->GetAttribute(nsHTMLAtoms::value, value)) {
if (eHTMLUnit_Integer == value.GetUnit()) {
ordinal = value.GetIntValue();
- if (nsnull != state) {
- state->mNextListOrdinal = ordinal + 1;
+ if (nsnull != aReflowState) {
+ aReflowState->mNextListOrdinal = ordinal + 1;
}
NS_RELEASE(html);
goto done;
@@ -362,8 +359,8 @@ BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
NS_RELEASE(html);
// Get ordinal from block reflow state
- if (nsnull != state) {
- ordinal = state->mNextListOrdinal;
+ if (nsnull != aReflowState) {
+ ordinal = aReflowState->mNextListOrdinal;
if (ordinal < 0) {
// This is the first list item and the list container doesn't
// have a "start" attribute. Get the starting ordinal value
@@ -379,7 +376,7 @@ BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
break;
}
}
- state->mNextListOrdinal = ordinal + 1;
+ aReflowState->mNextListOrdinal = ordinal + 1;
}
done:
@@ -395,12 +392,15 @@ static const char* gUpperRomanCharsB = "VLD?";
static const char* gLowerAlphaChars = "abcdefghijklmnopqrstuvwxyz";
static const char* gUpperAlphaChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+// XXX change roman/alpha to use unsigned math so that maxint and
+// maxnegint will work
void
BulletFrame::GetListItemText(nsIPresContext* aCX,
- nsString& result,
- const nsStyleList& aListStyle)
+ nsCSSBlockReflowState* aReflowState,
+ const nsStyleList& aListStyle,
+ nsString& result)
{
- PRInt32 ordinal = GetListItemOrdinal(aCX, aListStyle);
+ PRInt32 ordinal = GetListItemOrdinal(aCX, aReflowState, aListStyle);
char cbuf[40];
switch (aListStyle.mListStyleType) {
case NS_STYLE_LIST_STYLE_DECIMAL:
@@ -411,7 +411,9 @@ BulletFrame::GetListItemText(nsIPresContext* aCX,
case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
{
- // XXX deal with an ordinal of ZERO
+ if (0 == ordinal) {
+ ordinal = 1;
+ }
nsAutoString addOn;
nsAutoString decStr;
decStr.Append(ordinal, 10);
@@ -512,23 +514,23 @@ BulletFrame::GetListItemText(nsIPresContext* aCX,
result.Append(".");
}
-// from laytext.c
-#define MIN_BULLET_SIZE 5
+#define MIN_BULLET_SIZE 5 // from laytext.c
void
BulletFrame::GetDesiredSize(nsIPresContext* aCX,
+ nsCSSBlockReflowState* aState,
const nsReflowState& aReflowState,
- nsReflowMetrics& aDesiredSize)
+ nsReflowMetrics& aMetrics)
{
const nsStyleList* myList =
(const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List);
if (myList->mListStyleImage.Length() > 0) {
mImageLoader.SetURL(myList->mListStyleImage);
- mImageLoader.GetDesiredSize(aCX, aReflowState, aDesiredSize);
+ mImageLoader.GetDesiredSize(aCX, aReflowState, aMetrics);
if (!mImageLoader.GetLoadImageFailed()) {
nsHTMLBase::CreateViewForFrame(aCX, this, mStyleContext, PR_FALSE);
- aDesiredSize.ascent = aDesiredSize.height;
- aDesiredSize.descent = 0;
+ aMetrics.ascent = aMetrics.height;
+ aMetrics.descent = 0;
return;
}
}
@@ -543,10 +545,10 @@ BulletFrame::GetDesiredSize(nsIPresContext* aCX,
nsAutoString text;
switch (myList->mListStyleType) {
case NS_STYLE_LIST_STYLE_NONE:
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- aDesiredSize.ascent = 0;
- aDesiredSize.descent = 0;
+ aMetrics.width = 0;
+ aMetrics.height = 0;
+ aMetrics.ascent = 0;
+ aMetrics.descent = 0;
break;
default:
@@ -565,10 +567,10 @@ BulletFrame::GetDesiredSize(nsIPresContext* aCX,
if (NS_STYLE_LIST_STYLE_POSITION_INSIDE == myList->mListStylePosition) {
mPadding.right = bulletSize / 2;
}
- aDesiredSize.width = mPadding.right + bulletSize;
- aDesiredSize.height = mPadding.bottom + bulletSize;
- aDesiredSize.ascent = mPadding.bottom + bulletSize;
- aDesiredSize.descent = 0;
+ aMetrics.width = mPadding.right + bulletSize;
+ aMetrics.height = mPadding.bottom + bulletSize;
+ aMetrics.ascent = mPadding.bottom + bulletSize;
+ aMetrics.descent = 0;
break;
case NS_STYLE_LIST_STYLE_DECIMAL:
@@ -576,17 +578,53 @@ BulletFrame::GetDesiredSize(nsIPresContext* aCX,
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
- GetListItemText(aCX, text, *myList);
+ GetListItemText(aCX, aState, *myList, text);
if (NS_STYLE_LIST_STYLE_POSITION_INSIDE == myList->mListStylePosition) {
// Inside bullets need some extra width to get the padding
// between the list item and the content that follows.
mPadding.right = fm->GetHeight() / 2; // From old layout engine
}
- aDesiredSize.width = mPadding.right + fm->GetWidth(text);
- aDesiredSize.height = fm->GetHeight();
- aDesiredSize.ascent = fm->GetMaxAscent();
- aDesiredSize.descent = fm->GetMaxDescent();
+ aMetrics.width = mPadding.right + fm->GetWidth(text);
+ aMetrics.height = fm->GetHeight();
+ aMetrics.ascent = fm->GetMaxAscent();
+ aMetrics.descent = fm->GetMaxDescent();
break;
}
NS_RELEASE(fm);
}
+
+NS_IMETHODIMP
+BulletFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState)
+{
+ nsCSSBlockReflowState* state =
+ GetListContainerReflowState(aLineLayout.mPresContext, aReflowState);
+
+ // Get the base size
+ GetDesiredSize(aLineLayout.mPresContext, state, aReflowState, aMetrics);
+
+ // Add in the border and padding; split the top/bottom between the
+ // ascent and descent to make things look nice
+ const nsStyleSpacing* space =(const nsStyleSpacing*)
+ mStyleContext->GetStyleData(eStyleStruct_Spacing);
+ nsMargin borderPadding;
+ space->CalcBorderPaddingFor(this, borderPadding);
+ aMetrics.width += borderPadding.left + borderPadding.right;
+ aMetrics.height += borderPadding.top + borderPadding.bottom;
+ aMetrics.ascent += borderPadding.top;
+ aMetrics.descent += borderPadding.bottom;
+
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = aMetrics.width;
+ aMetrics.maxElementSize->height = aMetrics.height;
+ }
+ return NS_INLINE_REFLOW_COMPLETE;
+}
+
+NS_IMETHODIMP
+BulletFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
+{
+ aLineLayout.EndTextRun();
+ return NS_OK;
+}
diff --git a/mozilla/layout/html/base/src/nsHTMLContainer.cpp b/mozilla/layout/html/base/src/nsHTMLContainer.cpp
index f5dd7838a2a..90ea819c102 100644
--- a/mozilla/layout/html/base/src/nsHTMLContainer.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLContainer.cpp
@@ -22,8 +22,7 @@
#include "nsIArena.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
-#include "nsBlockFrame.h"
-#include "nsInlineFrame.h"
+#include "nsCSSBlockFrame.h"
#include "nsIPresContext.h"
#include "nsHTMLIIDs.h"
#include "nsHTMLAtoms.h"
@@ -34,6 +33,8 @@
#include "prprf.h"
#include "nsISizeOfHandler.h"
+#include "nsCSSInlineFrame.h"
+
nsresult
NS_NewHTMLContainer(nsIHTMLContent** aInstancePtrResult,
nsIAtom* aTag)
@@ -230,11 +231,11 @@ nsHTMLContainer::CreateFrame(nsIPresContext* aPresContext,
switch (styleDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
- rv = nsBlockFrame::NewFrame(&frame, this, aParentFrame);
+ rv = NS_NewCSSBlockFrame(&frame, this, aParentFrame);
break;
case NS_STYLE_DISPLAY_INLINE:
- rv = nsInlineFrame::NewFrame(&frame, this, aParentFrame);
+ rv = NS_NewCSSInlineFrame(&frame, this, aParentFrame);
break;
default:
diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp
index 12ea5df79c8..7905c8f03a0 100644
--- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp
@@ -207,62 +207,6 @@ static void AdjustIndexInParents(nsIFrame* aContainerFrame,
}
}
-nsresult
-nsHTMLContainerFrame::CreateFrameFor(nsIPresContext* aPresContext,
- nsIContent* aContent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aResult)
-{
- // Get the style data for the frame
- const nsStylePosition* position = (const nsStylePosition*)
- aStyleContext->GetStyleData(eStyleStruct_Position);
- const nsStyleDisplay* display = (const nsStyleDisplay*)
- aStyleContext->GetStyleData(eStyleStruct_Display);
- nsIFrame* frame = nsnull;
-
- // See whether it wants any special handling
- nsresult rv;
- if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) {
- rv = nsAbsoluteFrame::NewFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else if (display->mFloats != NS_STYLE_FLOAT_NONE) {
- rv = nsPlaceholderFrame::NewFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else if ((NS_STYLE_OVERFLOW_SCROLL == display->mOverflow) ||
- (NS_STYLE_OVERFLOW_AUTO == display->mOverflow)) {
- rv = NS_NewScrollFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
- rv = nsFrame::NewFrame(&frame, aContent, this);
- if (NS_OK == rv) {
- frame->SetStyleContext(aPresContext, aStyleContext);
- }
- }
- else {
- // Ask the content delegate to create the frame
- nsIContentDelegate* delegate = aContent->GetDelegate(aPresContext);
- rv = delegate->CreateFrame(aPresContext, aContent, this,
- aStyleContext, frame);
- NS_RELEASE(delegate);
- }
- if (NS_OK == rv) {
- // Wrap the frame in a view if necessary
- rv = nsHTMLBase::CreateViewForFrame(aPresContext, frame, aStyleContext,
- PR_FALSE);
- }
- aResult = frame;
- return rv;
-}
-
NS_METHOD nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
@@ -321,7 +265,8 @@ NS_METHOD nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
nsIStyleContext* kidSC;
kidSC = aPresContext->ResolveStyleContextFor(aChild, parent);
nsIFrame* newFrame;
- nsresult rv = parent->CreateFrameFor(aPresContext, aChild, kidSC, newFrame);
+//XXX nsresult rv = parent->CreateFrameFor(aPresContext, aChild, kidSC, newFrame);
+ nsresult rv = nsHTMLBase::CreateFrame(aPresContext, this, aChild, nsnull, newFrame);
if (NS_OK != rv) {
return rv;
}
@@ -369,23 +314,25 @@ NS_METHOD nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
nsresult
nsHTMLContainerFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
{
- const nsStyleDisplay* display = (const nsStyleDisplay*)
- mStyleContext->GetStyleData(eStyleStruct_Display);
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("nsHTMLContainerFrame::ProcessInitialReflow: display=%d",
- display->mDisplay));
- if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
- // This container is a list-item container. Therefore it needs a
- // bullet content object.
- nsIHTMLContent* bullet;
- nsresult rv = NS_NewHTMLBullet(&bullet);
- if (NS_OK != rv) {
- return rv;
- }
+ if (nsnull == mPrevInFlow) {
+ const nsStyleDisplay* display = (const nsStyleDisplay*)
+ mStyleContext->GetStyleData(eStyleStruct_Display);
+ NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ ("nsHTMLContainerFrame::ProcessInitialReflow: display=%d",
+ display->mDisplay));
+ if (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay) {
+ // This container is a list-item container. Therefore it needs a
+ // bullet content object.
+ nsIHTMLContent* bullet;
+ nsresult rv = NS_NewHTMLBullet(&bullet);
+ if (NS_OK != rv) {
+ return rv;
+ }
- // Insert the bullet. Do not allow an incremental reflow operation
- // to occur.
- mContent->InsertChildAt(bullet, 0, PR_FALSE);
+ // Insert the bullet. Do not allow an incremental reflow operation
+ // to occur.
+ mContent->InsertChildAt(bullet, 0, PR_FALSE);
+ }
}
return NS_OK;
diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.h b/mozilla/layout/html/base/src/nsHTMLContainerFrame.h
index aefa2feb007..c7d4a11a232 100644
--- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.h
+++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.h
@@ -56,12 +56,8 @@ protected:
virtual PRIntn GetSkipSides() const = 0;
- nsresult CreateFrameFor(nsIPresContext* aPresContext,
- nsIContent* aContent,
- nsIStyleContext* aStyleContext,
- nsIFrame*& aResult);
-
nsresult ProcessInitialReflow(nsIPresContext* aPresContext);
};
#endif /* nsHTMLContainerFrame_h___ */
+
diff --git a/mozilla/layout/html/base/src/nsHTMLIIDs.cpp b/mozilla/layout/html/base/src/nsHTMLIIDs.cpp
index c80af44dc4a..27d79849233 100644
--- a/mozilla/layout/html/base/src/nsHTMLIIDs.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLIIDs.cpp
@@ -17,9 +17,15 @@
*/
#include "nsHTMLIIDs.h"
#include "nsIHTMLContent.h"
-#include "nsBlockFrame.h"
+#include "nsIAnchoredItems.h"
+#include "nsIFloaterContainer.h"
+#include "nsIRunaround.h"
+#include "nsIInlineReflow.h"
+#include "nsCSSBlockFrame.h"
+const nsIID kIAnchoredItemsIID = NS_IANCHORED_ITEMS_IID;
+const nsIID kIFloaterContainerIID = NS_IFLOATER_CONTAINER_IID;
const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID;
-const nsIID kBlockFrameCID = NS_BLOCKFRAME_CID;
-const nsIID kIInlineFrameIID = NS_IINLINE_FRAME_IID;
-
+const nsIID kIInlineReflowIID = NS_IINLINE_REFLOW_IID;
+const nsIID kIRunaroundIID = NS_IRUNAROUND_IID;
+const nsIID kBlockFrameCID = NS_BLOCK_FRAME_CID;
diff --git a/mozilla/layout/html/base/src/nsHTMLIIDs.h b/mozilla/layout/html/base/src/nsHTMLIIDs.h
index e9b5f541d92..d59972e1a07 100644
--- a/mozilla/layout/html/base/src/nsHTMLIIDs.h
+++ b/mozilla/layout/html/base/src/nsHTMLIIDs.h
@@ -20,8 +20,12 @@
#include "nsISupports.h"
+extern const nsIID kBlockFrameCID; // XXX temporary
+
+extern const nsIID kIAnchoredItemsIID;
+extern const nsIID kIFloaterContainerIID;
extern const nsIID kIHTMLContentIID;
-extern const nsIID kBlockFrameCID;
-extern const nsIID kIInlineFrameIID;
+extern const nsIID kIInlineReflowIID;
+extern const nsIID kIRunaroundIID;
#endif /* nsHTMLIIDs_h___ */
diff --git a/mozilla/layout/html/base/src/nsIFloaterContainer.h b/mozilla/layout/html/base/src/nsIFloaterContainer.h
index 8fbdaf03955..46d5d2aade8 100644
--- a/mozilla/layout/html/base/src/nsIFloaterContainer.h
+++ b/mozilla/layout/html/base/src/nsIFloaterContainer.h
@@ -18,14 +18,13 @@
#ifndef nsIFloaterContainer_h___
#define nsIFloaterContainer_h___
-#include
+#include "nsIFrame.h"
class nsPlaceholderFrame;
class nsIPresContext;
-// IID for the nsIFloaterContainer interface {5A305EE0-CB55-11d1-8556-00A02468FAB6}
-#define NS_IFLOATERCONTAINER_IID \
-{ 0x5a305ee0, 0xcb55, 0x11d1, \
- {0x85, 0x56, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}}
+// 5a305ee0-cb55-11d1-8556-00a02468fab6
+#define NS_IFLOATER_CONTAINER_IID \
+ { 0x5a305ee0, 0xcb55, 0x11d1, {0x85, 0x56, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}}
/**
* An interface for communicating with the enclosing block-level container
@@ -42,22 +41,10 @@ public:
* @param aPlaceholder the placeholder frame associated with the floating
* element.
*/
- virtual PRBool AddFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder) = 0;
-
- /**
- * Call to place the floating element, because the placeholder frame has been
- * reflowed.
- *
- * XXX This is kind of hokey and unreliable, because it relies on the placeholder
- * getting reflowed. That won't necessarily happen if its geometric parent just
- * decides to move it... It would probably be better if the implementor of this
- * interface managed the tracking of the placeholder within the containing line
- **/
- virtual void PlaceFloater(nsIPresContext* aPresContext,
- nsIFrame* aFloater,
- nsPlaceholderFrame* aPlaceholder) = 0;
+ virtual PRBool AddFloater(nsIPresContext* aPresContext,
+ const nsReflowState& aPlaceholderReflowState,
+ nsIFrame* aFloater,
+ nsPlaceholderFrame* aPlaceholder) = 0;
};
#endif /* nsIFloaterContainer_h___ */
diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp
deleted file mode 100644
index 06a623a8d1b..00000000000
--- a/mozilla/layout/html/base/src/nsInlineFrame.cpp
+++ /dev/null
@@ -1,1288 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsInlineFrame.h"
-#include "nsBlockFrame.h"
-#include "nsSize.h"
-#include "nsIContent.h"
-#include "nsIContentDelegate.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIPresContext.h"
-#include "nsIPresShell.h"
-#include "nsCSSLayout.h"
-#include "nsPlaceholderFrame.h"
-#include "nsIReflowCommand.h"
-#include "nsHTMLAtoms.h"
-#include "nsAbsoluteFrame.h"
-#include "nsLeafFrame.h"
-#include "nsIPtr.h"
-
-// XXX To Do:
-// 2. horizontal child margins
-// 3. borders/padding and splitting
-// 4. child relative positioning
-// 5. absolutely positioned children
-// 6. direction support
-// 7. CSS line-height property
-
-/* XXX */
-#include "nsHTMLIIDs.h"
-#include "nsBlockFrame.h"
-
-#define DEFAULT_ASCENT_LEN 10
-
-NS_DEF_PTR(nsIStyleContext);
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIContentDelegate);
-
-class nsInlineState
-{
-public:
- const nsStyleFont* font; // style font
- nsMargin borderPadding; // inner margin
- nsSize mStyleSize;
- PRIntn mStyleSizeFlags;
- nsSize availSize; // available space in which to reflow (starts as max size minus insets)
- nsSize* maxElementSize; // maximum element size (may be null)
- nscoord x; // running x-offset (starts at left inner edge)
- const nscoord y; // y-offset (top inner edge)
- nscoord maxAscent; // max child ascent
- nscoord maxDescent; // max child descent
- nscoord* ascents; // ascent information for each child
- PRBool unconstrainedWidth;
- PRBool unconstrainedHeight;
- nsLineLayout* lineLayout;
- PRBool atBreakPoint;
- const nsReflowState& reflowState;
- PRBool mNoWrap;
-
- // Constructor
- nsInlineState(nsIPresContext* aPresContext,
- nsIFrame* aInlineFrame,
- const nsStyleFont* aStyleFont,
- const nsMargin& aBorderPadding,
- const nsReflowState& aReflowState,
- nsSize* aMaxElementSize)
- : x(aBorderPadding.left), // determined by inner edge
- y(aBorderPadding.top), // determined by inner edge
- reflowState(aReflowState)
- {
- nsBlockReflowState* brs =
- nsBlockFrame::FindBlockReflowState(aPresContext, aInlineFrame);
- lineLayout = brs->mCurrentLine;
- atBreakPoint = PR_TRUE;
-
- font = aStyleFont;
- borderPadding = aBorderPadding;
-
- unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE);
- unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE);
-
- // If we're constrained adjust the available size so it excludes space
- // needed for border/padding
- availSize.width = reflowState.maxSize.width;
- if (PR_FALSE == unconstrainedWidth) {
- availSize.width -= aBorderPadding.left + aBorderPadding.right;
- }
- availSize.height = reflowState.maxSize.height;
- if (PR_FALSE == unconstrainedHeight) {
- availSize.height -= aBorderPadding.top + aBorderPadding.bottom;
- }
-
- // Initialize max element size
- maxElementSize = aMaxElementSize;
- if (nsnull != maxElementSize) {
- maxElementSize->SizeTo(0, 0);
- }
-
- ascents = ascentBuf;
- maxAscent = 0;
- maxDescent = 0;
- mNoWrap = PR_FALSE;
- }
-
- void SetNumAscents(PRIntn aNumAscents) {
- // We keep around ascent information so that we can vertically align
- // children after we figure out how many children fit.
- if (aNumAscents > DEFAULT_ASCENT_LEN) {
- ascents = new nscoord[aNumAscents];
- }
- }
-
- // Destructor
- ~nsInlineState() {
- if (ascents != ascentBuf) {
- delete ascents;
- }
- }
-
-private:
- nscoord ascentBuf[DEFAULT_ASCENT_LEN];
-};
-
-/////////////////////////////////////////////////////////////////////////////
-//
-
-nsresult nsInlineFrame::NewFrame(nsIFrame** aInstancePtrResult,
- nsIContent* aContent,
- nsIFrame* aParent)
-{
- NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
- if (nsnull == aInstancePtrResult) {
- return NS_ERROR_NULL_POINTER;
- }
- nsIFrame* it = new nsInlineFrame(aContent, aParent);
- if (nsnull == it) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- *aInstancePtrResult = it;
- return NS_OK;
-}
-
-nsInlineFrame::nsInlineFrame(nsIContent* aContent, nsIFrame* aParent)
- : nsHTMLContainerFrame(aContent, aParent)
-{
- NS_PRECONDITION(!IsPseudoFrame(), "can not be a pseudo frame");
-}
-
-nsInlineFrame::~nsInlineFrame()
-{
-}
-
-nsReflowStatus
-nsInlineFrame::ReflowChild(nsInlineState& aState,
- nsIFrame* aKidFrame,
- nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState)
-{
- nsReflowStatus status;
-
- NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
-#ifdef NS_DEBUG
- nsFrameState kidFrameState;
-
- aKidFrame->GetFrameState(kidFrameState);
- NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow");
-#endif
- nsIInlineFrame* iif;
- if (NS_OK == aKidFrame->QueryInterface(kIInlineFrameIID, (void**)&iif)) {
- iif->ReflowInline(*aState.lineLayout, aDesiredSize, aReflowState, status);
- }
- else {
- aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState, status);
- }
-
- if (NS_FRAME_IS_COMPLETE(status)) {
- nsIFrame* kidNextInFlow;
-
- aKidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull != kidNextInFlow) {
- // Remove all of the childs next-in-flows. Make sure that we ask
- // the right parent to do the removal (it's possible that the
- // parent is not this because we are executing pullup code)
- nsIFrame* parent;
-
- aKidFrame->GetGeometricParent(parent);
- DeleteNextInFlowsFor((nsContainerFrame*)parent, aKidFrame);
- }
- }
- return status;
-}
-
-void nsInlineFrame::PlaceChild(nsIFrame* aChild,
- PRInt32 aIndex,
- nsInlineState& aState,
- const nsReflowMetrics& aChildSize,
- const nsSize* aChildMaxElementSize)
-{
- // Set the child's rect
- aChild->SetRect(nsRect(aState.x, aState.y, aChildSize.width, aChildSize.height));
-
- // Adjust the running x-offset
- aState.x += aChildSize.width;
-
- // Update the array of ascents and the max ascent and descent
- aState.ascents[aIndex] = aChildSize.ascent;
- if (aChildSize.ascent > aState.maxAscent) {
- aState.maxAscent = aChildSize.ascent;
- }
- if (aChildSize.descent > aState.maxDescent) {
- aState.maxDescent = aChildSize.descent;
- }
-
- // If we're constrained then update the available width
- if (!aState.unconstrainedWidth) {
- aState.availSize.width -= aChildSize.width;
- }
-
- // Update the maximum element size
- if (nsnull != aChildMaxElementSize) {
- if (aChildMaxElementSize->width > aState.maxElementSize->width) {
- aState.maxElementSize->width = aChildMaxElementSize->width;
- }
- if (aChildMaxElementSize->height > aState.maxElementSize->height) {
- aState.maxElementSize->height = aChildMaxElementSize->height;
- }
- }
-}
-
-// XXX an image shouldn't be allowed to continue a word but text
-// should. hmmm.
-
-PRBool
-nsInlineFrame::CanFitChild(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame)
-{
- PRBool result = PR_TRUE;
- aState.atBreakPoint = nsnull == aState.lineLayout->mBreakFrame;
- if ((aState.availSize.width <= 0) &&
- (aChildFrame != mFirstChild) && (nsnull != mFirstChild)) {
- // If we are at a breakable position then it's ok to be out of
- // room. Otherwise the child is allowed to fit.
- if (aState.atBreakPoint) {
- result = PR_FALSE;
- }
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsInlineFrame::CanFitChild: availSize=%d result=%s",
- aState.availSize.width, result ? "true" : "false"));
- return result;
-}
-
-// XXX dup first-child check because of calling code not being nice! ick!
-PRBool
-nsInlineFrame::DidFitChild(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- nsReflowMetrics& aChildMetrics)
-{
- if ((aChildMetrics.width > aState.availSize.width) &&
- (aChildFrame != mFirstChild) && (nsnull != mFirstChild)) {
- // If we *were* at a breakable position then it's ok to be out of
- // room. Otherwise the child is allowed to fit.
- if (aState.atBreakPoint) {
- return PR_FALSE;
- }
- }
- return PR_TRUE;
-}
-
-/**
- * Reflow the frames we've already created
- *
- * @param aPresContext presentation context to use
- * @param aState current inline state
- * @param aChildFrame the first child frame to reflow
- * @param aChildIndex the first child frame's index in the frame list
- * @return true if we successfully reflowed all the mapped children and false
- * otherwise, e.g. we pushed children to the next in flow
- */
-PRBool
-nsInlineFrame::ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
- NS_PRECONDITION(nsnull != aChildFrame, "no children");
-
- PRInt32 childCount = aChildIndex;
- nsIFrame* prevKidFrame = nsnull;
-
- // Remember our original mLastContentIsComplete so that if we end up
- // having to push children, we have the correct value to hand to
- // PushChildren.
- PRBool originalLastContentIsComplete = mLastContentIsComplete;
-
- nsSize kidMaxElementSize;
- nsSize* pKidMaxElementSize = (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
- PRBool result = PR_TRUE;
-
- for (nsIFrame* kidFrame = aChildFrame; nsnull != kidFrame; ) {
- // If the previous child just reflowed has indicated a pending
- // break, stop reflowing our remaining children. This can only
- // happen when a prev-in-flow has pushed some junk into this
- // frame.
- if (NS_STYLE_CLEAR_NONE != aState.lineLayout->mPendingBreak) {
- PushChildren(kidFrame, prevKidFrame, originalLastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
-
- result = PR_FALSE;
- break;
- }
-
- // If the frame being reflowed is not appropriate (e.g. a block
- // frame) then we should stop! This can only happen when a
- // prev-in-flow has pushed some junk into this frame.
- const nsStyleDisplay* kidDisplay;
- kidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)kidDisplay);
- if ((NS_STYLE_DISPLAY_BLOCK == kidDisplay->mDisplay) ||
- (NS_STYLE_DISPLAY_LIST_ITEM == kidDisplay->mDisplay)) {
- if (mFirstChild != kidFrame) {
- PushChildren(kidFrame, prevKidFrame, originalLastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
- result = PR_FALSE;
- break;
- }
- }
-
- nsReflowMetrics kidSize(pKidMaxElementSize);
- nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize,
- eReflowReason_Resize);
- nsReflowStatus status;
-
- // Reflow the child into the available space
- PRBool room = CanFitChild(aPresContext, aState, kidFrame);
- if (room) {
- kidFrame->WillReflow(*aPresContext);
- status = ReflowChild(aState, kidFrame, aPresContext, kidSize, kidReflowState);
- }
-
- // Did the child fit?
- if (!room || !DidFitChild(aPresContext, aState, kidFrame, kidSize)) {
- // The child is too wide to fit in the available space, and it's
- // not our first child
-
- // Since we are giving the next-in-flow our last child, we
- // give it our original mLastContentIsComplete too (in case we
- // are pushing into an empty next-in-flow)
- PushChildren(kidFrame, prevKidFrame, originalLastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
-
- result = PR_FALSE;
- break;
- }
-
- // Place and size the child. We'll deal with vertical alignment when
- // we're all done
- PlaceChild(kidFrame, childCount, aState, kidSize, pKidMaxElementSize);
- childCount++;
-
- // Remember where we just were in case we end up pushing children
- prevKidFrame = kidFrame;
-
- // Is the child complete?
- mLastContentIsComplete = NS_FRAME_IS_COMPLETE(status);
- if (NS_FRAME_IS_NOT_COMPLETE(status)) {
- // No, the child isn't complete
- nsIFrame* kidNextInFlow;
-
- kidFrame->GetNextInFlow(kidNextInFlow);
- PRBool lastContentIsComplete = mLastContentIsComplete;
- if (nsnull == kidNextInFlow) {
- // The child doesn't have a next-in-flow so create a continuing
- // frame. This hooks the child into the flow
- nsIFrame* continuingFrame;
-
- nsIStyleContextPtr kidSC;
- kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
- kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
- continuingFrame);
- NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
-
- // Add the continuing frame to the sibling list
- nsIFrame* nextSib;
-
- kidFrame->GetNextSibling(nextSib);
- continuingFrame->SetNextSibling(nextSib);
- kidFrame->SetNextSibling(continuingFrame);
- if (nsnull == nextSib) {
- // Assume that the continuation frame we just created is
- // complete, for now. It will get reflowed by our
- // next-in-flow (we are going to push it now)
- lastContentIsComplete = PR_TRUE;
- }
- }
-
- // We've used up all of our available space so push the remaining
- // children to the next-in-flow
- nsIFrame* nextSibling;
-
- kidFrame->GetNextSibling(nextSibling);
- if (nsnull != nextSibling) {
- PushChildren(nextSibling, kidFrame, lastContentIsComplete);
- SetLastContentOffset(prevKidFrame);
- }
- result = PR_FALSE;
- break;
- }
-
- // Get the next child frame
- kidFrame->GetNextSibling(kidFrame);
- }
-
- // Update the child count member data
- mChildCount = childCount;
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- NS_POSTCONDITION(LengthOf(mFirstChild) == mChildCount, "bad child count");
-
- nsIFrame* lastChild;
- PRInt32 lastIndexInParent;
-
- LastChild(lastChild);
- lastChild->GetContentIndex(lastIndexInParent);
- NS_POSTCONDITION(lastIndexInParent == mLastContentOffset, "bad last content offset");
- VerifyLastIsComplete();
- }
-#endif
- return result;
-}
-
-/**
- * Try and pull-up frames from our next-in-flow
- *
- * @param aPresContext presentation context to use
- * @param aState current inline state
- * @return true if we successfully pulled-up all the children and false
- * otherwise, e.g. child didn't fit
- */
-PRBool nsInlineFrame::PullUpChildren(nsIPresContext* aPresContext,
- nsInlineState& aState)
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("enter nsInlineFrame::PullUpChildren: [%d,%d,%c] childCount=%d",
- mFirstContentOffset,
- mLastContentOffset,
- mLastContentIsComplete ? 'T' : 'F',
- mChildCount));
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
-
- nsInlineFrame* nextInFlow = (nsInlineFrame*)mNextInFlow;
- nsSize kidMaxElementSize;
- nsSize* pKidMaxElementSize = (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
-#ifdef NS_DEBUG
- PRInt32 kidIndex = NextChildOffset();
-#endif
- nsIFrame* prevKidFrame;
-
- LastChild(prevKidFrame);
-
- PRBool result = PR_TRUE;
-
- while (nsnull != nextInFlow) {
- nsReflowMetrics kidSize(pKidMaxElementSize);
- nsReflowStatus status;
-
- // Get the next child
- nsIFrame* kidFrame = nextInFlow->mFirstChild;
-
- // Any more child frames?
- if (nsnull == kidFrame) {
- // No. Any frames on its overflow list?
- if (nsnull != nextInFlow->mOverflowList) {
- // Move the overflow list to become the child list
- NS_ABORT();
- nextInFlow->AppendChildren(nextInFlow->mOverflowList);
- nextInFlow->mOverflowList = nsnull;
- kidFrame = nextInFlow->mFirstChild;
- } else {
- // We've pulled up all the children, so move to the next-in-flow.
- nextInFlow = (nsInlineFrame*)nextInFlow->mNextInFlow;
- continue;
- }
- }
-
- // It's time to stop pulling up if our last child wants a break
- if (NS_STYLE_CLEAR_NONE != aState.lineLayout->mPendingBreak) {
- result = PR_FALSE;
- break;
- }
-
- // If the frame being pulled up is not appropriate (e.g. a block
- // frame) then we should stop!
- const nsStyleDisplay* kidDisplay;
- kidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)kidDisplay);
- if ((NS_STYLE_DISPLAY_BLOCK == kidDisplay->mDisplay) ||
- (NS_STYLE_DISPLAY_LIST_ITEM == kidDisplay->mDisplay)) {
- result = PR_FALSE;
- break;
- }
-
- // If there is no room, stop pulling up
- if (!CanFitChild(aPresContext, aState, kidFrame)) {
- result = PR_FALSE;
- break;
- }
-
-// XXX inline reflow avoidance will be done by nsLineLayout
-#if XXX
- // See if the child fits in the available space. If it fits or
- // it's splittable then reflow it. The reason we can't just move
- // it is that we still need ascent/descent information
- nsSize kidFrameSize;
- nsSplittableType kidIsSplittable;
-
- kidFrame->GetSize(kidFrameSize);
- kidFrame->IsSplittable(kidIsSplittable);
- if ((kidFrameSize.width > aState.availSize.width) &&
- NS_FRAME_IS_NOT_SPLITTABLE(kidIsSplittable)) {
- result = PR_FALSE;
- break;
- }
-#endif
-
- nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize,
- eReflowReason_Resize);
- kidFrame->WillReflow(*aPresContext);
- status = ReflowChild(aState, kidFrame, aPresContext, kidSize, kidReflowState);
-
- // Did the child fit?
- if (!DidFitChild(aPresContext, aState, kidFrame, kidSize)) {
- // The child is too wide to fit in the available space, and it's
- // not our first child
- result = PR_FALSE;
- break;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("nsInlineFrame::PullUpChildren: pulled frame=%p [%c][%x]",
- kidFrame,
- NS_FRAME_IS_COMPLETE(status) ? 'T' : 'F',
- status));
-
- // Place and size the child. We'll deal with vertical alignment when
- // we're all done
- PlaceChild(kidFrame, mChildCount, aState, kidSize, pKidMaxElementSize);
-
- // Remove the frame from its current parent
- kidFrame->GetNextSibling(nextInFlow->mFirstChild);
- nextInFlow->mChildCount--;
- // Update the next-in-flows first content offset
- if (nsnull != nextInFlow->mFirstChild) {
- nextInFlow->SetFirstContentOffset(nextInFlow->mFirstChild);
- }
-
- // Link the frame into our list of children
- kidFrame->SetGeometricParent(this);
- nsIFrame* kidContentParent;
-
- kidFrame->GetContentParent(kidContentParent);
- if (nextInFlow == kidContentParent) {
- kidFrame->SetContentParent(this);
- }
- if (nsnull == prevKidFrame) {
- mFirstChild = kidFrame;
- SetFirstContentOffset(kidFrame);
- } else {
- prevKidFrame->SetNextSibling(kidFrame);
- }
- kidFrame->SetNextSibling(nsnull);
- mChildCount++;
- prevKidFrame = kidFrame;
-
- // Is the child we just pulled up complete?
- mLastContentIsComplete = NS_FRAME_IS_COMPLETE(status);
- if (NS_FRAME_IS_NOT_COMPLETE(status)) {
- // No the child isn't complete
- nsIFrame* kidNextInFlow;
-
- kidFrame->GetNextInFlow(kidNextInFlow);
- if (nsnull == kidNextInFlow) {
- // The child doesn't have a next-in-flow so create a
- // continuing frame. The creation appends it to the flow and
- // prepares it for reflow.
- nsIFrame* continuingFrame;
-
- nsIStyleContextPtr kidSC;
- kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
- kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
- continuingFrame);
- NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
-
- // Add the continuing frame to our sibling list and then push
- // it to the next-in-flow. This ensures the next-in-flow's
- // content offsets and child count are set properly. Note that
- // we can safely assume that the continuation is complete so
- // we pass PR_TRUE into PushChidren in case our next-in-flow
- // was just drained and now needs to know it's
- // mLastContentIsComplete state.
- kidFrame->SetNextSibling(continuingFrame);
-
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("nsInlineFrame::PullUpChildren: pushing frame=%p",
- continuingFrame));
- PushChildren(continuingFrame, kidFrame, PR_TRUE);
-
- // After we push the continuation frame we don't need to fuss
- // with mLastContentIsComplete beause the continuation frame
- // is no longer on *our* list.
- }
-
- // If the child isn't complete then it means that we've used up
- // all of our available space.
- result = PR_FALSE;
- break;
- }
- }
-
- // Update our last content offset
- if (nsnull != prevKidFrame) {
- NS_ASSERTION(IsLastChild(prevKidFrame), "bad last child");
- SetLastContentOffset(prevKidFrame);
- }
-
- // We need to make sure the first content offset is correct for any empty
- // next-in-flow frames (frames where we pulled up all the child frames)
- nextInFlow = (nsInlineFrame*)mNextInFlow;
- if ((nsnull != nextInFlow) && (nsnull == nextInFlow->mFirstChild)) {
- // We have at least one empty frame. Did we succesfully pull up all the
- // child frames?
- if (PR_FALSE == result) {
- // No, so we need to adjust the first content offset of all the empty
- // frames
- AdjustOffsetOfEmptyNextInFlows();
-#ifdef NS_DEBUG
- } else {
- // Yes, we successfully pulled up all the child frames which means all
- // the next-in-flows must be empty. Do a sanity check
- if (GetVerifyTreeEnable()) {
- while (nsnull != nextInFlow) {
- NS_ASSERTION(nsnull == nextInFlow->mFirstChild,
- "non-empty next-in-flow");
- nextInFlow = (nsInlineFrame*)nextInFlow->mNextInFlow;
- }
- }
-#endif
- }
- }
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("exit nsInlineFrame::PullUpChildren: [%d,%d,%c] childCount=%d",
- mFirstContentOffset,
- mLastContentOffset,
- mLastContentIsComplete ? 'T' : 'F',
- mChildCount));
- return result;
-}
-
-/**
- * Create new frames for content we haven't yet mapped
- *
- * @param aPresContext presentation context to use
- * @param aState current inline state
- * @return NS_FRAME_COMPLETE if all content has been mapped and 0 if we
- * should be continued
- */
-nsReflowStatus
-nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
- nsInlineState& aState)
-{
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- VerifyLastIsComplete();
- }
-#endif
- nsIFrame* kidPrevInFlow = nsnull;
- nsReflowStatus result = NS_FRAME_NOT_COMPLETE;
-
- // If we have no children and we have a prev-in-flow then we need to pick
- // up where it left off. If we have children, e.g. we're being resized, then
- // our content offset should already be set correctly...
- if ((nsnull == mFirstChild) && (nsnull != mPrevInFlow)) {
- nsInlineFrame* prev = (nsInlineFrame*)mPrevInFlow;
- NS_ASSERTION(prev->mLastContentOffset >= prev->mFirstContentOffset,
- "bad prevInFlow");
-
- mFirstContentOffset = prev->NextChildOffset();
- if (!prev->mLastContentIsComplete) {
- // Our prev-in-flow's last child is not complete
- prev->LastChild(kidPrevInFlow);
- }
- }
- mLastContentIsComplete = PR_TRUE;
-
- // Place our children, one at a time until we are out of children
- nsSize kidMaxElementSize;
- nsSize* pKidMaxElementSize =
- (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
- PRInt32 kidIndex = NextChildOffset();
- nsIFrame* prevKidFrame;
-
- PRBool breakAfter = PR_FALSE;
- LastChild(prevKidFrame);
- for (;;) {
- // Get the next content object
- nsIContentPtr kid = mContent->ChildAt(kidIndex);
- if (kid.IsNull()) {
- result = NS_FRAME_COMPLETE;
- break;
- }
-
- // It's time to stop pulling up if our previous child wants a line
- // break
- if (NS_STYLE_CLEAR_NONE != aState.lineLayout->mPendingBreak) {
- break;
- }
-
- // Make sure we still have room left
- if (!CanFitChild(aPresContext, aState, nsnull)) {
- // Note: return status was set to 0 above...
- break;
- }
-
- // Resolve style for the child
- nsIStyleContextPtr kidStyleContext =
- aPresContext->ResolveStyleContextFor(kid, this);
-
- // Figure out how we should treat the child
- nsIFrame* kidFrame;
- const nsStyleDisplay* kidDisplay =
- (const nsStyleDisplay*)kidStyleContext->GetStyleData(eStyleStruct_Display);
- const nsStylePosition* kidPosition = (const nsStylePosition*)
- kidStyleContext->GetStyleData(eStyleStruct_Position);
-
- // Check whether it wants to floated or absolutely positioned
- nsresult rv;
- if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) {
- rv = nsAbsoluteFrame::NewFrame(&kidFrame, kid, this);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(aPresContext, kidStyleContext);
- }
- } else if (kidDisplay->mFloats != NS_STYLE_FLOAT_NONE) {
- rv = nsPlaceholderFrame::NewFrame(&kidFrame, kid, this);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(aPresContext, kidStyleContext);
- }
- } else if (nsnull == kidPrevInFlow) {
- nsIContentDelegatePtr kidDel;
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- if (kidIndex != mFirstContentOffset) {
- // We don't allow block elements to be placed in us anywhere
- // other than at our left margin.
- goto done;
- }
- // FALLTHROUGH
-
- case NS_STYLE_DISPLAY_INLINE:
- kidDel = kid->GetDelegate(aPresContext);
- rv = kidDel->CreateFrame(aPresContext, kid, this,
- kidStyleContext, kidFrame);
- break;
-
- default:
- NS_ASSERTION(nsnull == kidPrevInFlow, "bad prev in flow");
- rv = nsFrame::NewFrame(&kidFrame, kid, this);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(aPresContext, kidStyleContext);
- }
- break;
- }
- } else {
- rv = kidPrevInFlow->CreateContinuingFrame(aPresContext, this,
- kidStyleContext, kidFrame);
- }
-
- // Try to reflow the child into the available space. It might not
- // fit or might need continuing.
- nsReflowMetrics kidSize(pKidMaxElementSize);
- nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize,
- eReflowReason_Resize);
- kidFrame->WillReflow(*aPresContext);
- nsReflowStatus status = ReflowChild(aState, kidFrame, aPresContext, kidSize,
- kidReflowState);
-
- // Did the child fit?
- if (!DidFitChild(aPresContext, aState, kidFrame, kidSize)) {
- // The child is too wide to fit in the available space, and it's
- // not our first child. Add the frame to our overflow list
- NS_ASSERTION(nsnull == mOverflowList, "bad overflow list");
- mOverflowList = kidFrame;
- prevKidFrame->SetNextSibling(nsnull);
- break;
- }
-
- // Place and size the child. We'll deal with vertical alignment when
- // we're all done
- PlaceChild(kidFrame, mChildCount, aState, kidSize, pKidMaxElementSize);
-
- // Link child frame into the list of children
- if (nsnull != prevKidFrame) {
- prevKidFrame->SetNextSibling(kidFrame);
- } else {
- mFirstChild = kidFrame; // our first child
- SetFirstContentOffset(kidFrame);
- }
- prevKidFrame = kidFrame;
- mChildCount++;
- kidIndex++;
-
- // Did the child complete?
- if (NS_FRAME_IS_NOT_COMPLETE(status)) {
- // If the child isn't complete then it means that we've used up
- // all of our available space
- mLastContentIsComplete = PR_FALSE;
- break;
- }
- kidPrevInFlow = nsnull;
-
- // If we need to break after the kidFrame, then do so now
- if (breakAfter) {
- break;
- }
- }
-
-done:;
- // Update the content mapping
- NS_ASSERTION(IsLastChild(prevKidFrame), "bad last child");
- SetLastContentOffset(prevKidFrame);
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- PRInt32 len = LengthOf(mFirstChild);
- NS_ASSERTION(len == mChildCount, "bad child count");
- VerifyLastIsComplete();
- }
-#endif
- return result;
-}
-
-void
-nsInlineFrame::InitializeState(nsIPresContext* aPresContext,
- const nsReflowState& aReflowState,
- nsInlineState& aState)
-{
- PRIntn ss = aState.mStyleSizeFlags =
- nsCSSLayout::GetStyleSize(aPresContext, aReflowState, aState.mStyleSize);
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- // When we are given a width, change the reflow behavior to
- // unconstrained.
- aState.unconstrainedWidth = PR_TRUE;
- aState.availSize.width = NS_UNCONSTRAINEDSIZE;
- }
-}
-
-NS_METHOD nsInlineFrame::Reflow(nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("enter nsInlineFrame::Reflow: this=%p: childCount=%d",
- this, mChildCount));
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- PreReflowCheck();
- }
-#endif
-
- if (eReflowReason_Initial == aReflowState.reason) {
- nsresult rv = ProcessInitialReflow(aPresContext);
- if (NS_OK != rv) {
- return rv;
- }
- }
-
- PRBool reflowMappedOK = PR_TRUE;
-
- aStatus = NS_FRAME_COMPLETE; // initialize out parameter
-
- // Get the style molecule
- const nsStyleFont* styleFont = (const nsStyleFont*)
- mStyleContext->GetStyleData(eStyleStruct_Font);
- const nsStyleSpacing* styleSpacing = (const nsStyleSpacing*)
- mStyleContext->GetStyleData(eStyleStruct_Spacing);
- const nsStyleText* styleText = (const nsStyleText*)
- mStyleContext->GetStyleData(eStyleStruct_Text);
-
- // Check for an overflow list
- if (eReflowReason_Incremental != aReflowState.reason) {
- MoveOverflowToChildList();
- }
-
- // Initialize our reflow state. We must wait until after we've processed
- // the overflow list, because our first content offset might change
- nsMargin borderPadding;
- styleSpacing->CalcBorderPaddingFor(this, borderPadding);
- nsInlineState state(aPresContext, this, styleFont, borderPadding,
- aReflowState, aDesiredSize.maxElementSize);
- InitializeState(aPresContext, aReflowState, state);
- state.SetNumAscents(mContent->ChildCount() - mFirstContentOffset);
- state.mNoWrap = NS_STYLE_WHITESPACE_NORMAL != styleText->mWhiteSpace;
-
- if (eReflowReason_Incremental == aReflowState.reason) {
- NS_ASSERTION(nsnull != aReflowState.reflowCommand, "null reflow command");
- nsIFrame* target;
- aReflowState.reflowCommand->GetTarget(target);
-
- if (target == this) {
- nsIReflowCommand::ReflowType type;
- aReflowState.reflowCommand->GetType(type);
-
- switch (type) {
- case nsIReflowCommand::FrameAppended:
- // Recover our state
- RecoverState(aPresContext, state, nsnull);
- aStatus = ReflowUnmappedChildren(aPresContext, state);
- break;
-
- default:
- NS_NOTYETIMPLEMENTED("unexpected reflow command");
- break;
- }
-
- } else {
- // The command is passing through us. Get the next frame in the reflow chain
- nsIFrame* kidFrame;
- aReflowState.reflowCommand->GetNext(kidFrame);
-
- nsReflowMetrics kidSize(aDesiredSize.maxElementSize);
- nsReflowState kidReflowState(kidFrame, aReflowState, state.availSize);
-
- // Restore our state as if nextFrame is the next frame to reflow
- PRInt32 kidIndex = RecoverState(aPresContext, state, kidFrame);
-
- // Reflow the child into the available space
- kidFrame->WillReflow(*aPresContext);
- aStatus = ReflowChild(state, kidFrame, aPresContext, kidSize, kidReflowState);
-
- // Did the child fit?
- if (!DidFitChild(aPresContext, state, kidFrame, kidSize)) {
- nsIFrame* prevFrame;
-
- // The child is too wide to fit in the available space, and
- // it's not our first child
- PrevChild(kidFrame, prevFrame);
- PushChildren(kidFrame, prevFrame, mLastContentIsComplete);
- SetLastContentOffset(prevFrame);
- mChildCount = kidIndex - 1;
- aStatus = NS_FRAME_NOT_COMPLETE;
-
- } else {
- // Place and size the child
- PlaceChild(kidFrame, kidIndex, state, kidSize, nsnull);
-
- nsIFrame* kidNextInFlow;
- kidFrame->GetNextInFlow(kidNextInFlow);
-
- // Is the child complete?
- if (NS_FRAME_IS_COMPLETE(aStatus)) {
- // Check whether the frame has next-in-flow(s) that are no longer needed
- if (nsnull != kidNextInFlow) {
- // Remove the next-in-flow(s)
- DeleteChildsNextInFlow(kidFrame);
- }
-
- // Adjust the frames that follow
- aStatus = IncrementalReflowAfter(aPresContext, state, kidFrame, kidIndex);
-
- } else {
- nsIFrame* nextSibling;
-
- // No, the child isn't complete
- if (nsnull == kidNextInFlow) {
- // The child doesn't have a next-in-flow so create a continuing
- // frame.
- nsIFrame* continuingFrame;
-
- nsIStyleContextPtr kidSC;
- kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
- kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame);
-
- // Link the child into the sibling list
- kidFrame->GetNextSibling(nextSibling);
- continuingFrame->SetNextSibling(nextSibling);
- kidFrame->SetNextSibling(continuingFrame);
- }
-
- // We've used up all of our available space, so push the remaining
- // children to the next-in-flow
- kidFrame->GetNextSibling(nextSibling);
- if (nsnull != nextSibling) {
- PushChildren(nextSibling, kidFrame, mLastContentIsComplete);
- }
-
- SetLastContentOffset(kidFrame);
- mChildCount = kidIndex;
- }
- }
- }
-
- } else {
- // Reflow any existing frames
- if (nsnull != mFirstChild) {
- reflowMappedOK = ReflowMappedChildrenFrom(aPresContext, state, mFirstChild, 0);
-
- if (PR_FALSE == reflowMappedOK) {
- // We didn't successfully reflow our mapped frames; therefore, we're not complete
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
- }
-
- // Did we successfully relow our mapped children?
- if (PR_TRUE == reflowMappedOK) {
-#if XXX
- // Any space left?
- if (state.availSize.width <= 0) {
- // No space left. Don't try to pull-up children or reflow unmapped
- if (NextChildOffset() < mContent->ChildCount()) {
- // No room left to map the remaining content; therefore, we're not complete
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
- } else
-#endif
- if (NextChildOffset() < mContent->ChildCount()) {
- // Try and pull-up some children from a next-in-flow
- if (PullUpChildren(aPresContext, state)) {
- // If we still have unmapped children then create some new frames
- if (NextChildOffset() < mContent->ChildCount()) {
- aStatus = ReflowUnmappedChildren(aPresContext, state);
- }
- } else {
- // We were unable to pull-up all the existing frames from the next in flow;
- // therefore, we're not complete
- aStatus = NS_FRAME_NOT_COMPLETE;
- }
- }
- }
-
- #if 0
- // XXX I don't think our return size properly accounts for the lineHeight
- // (which may not == state.maxAscent + state.maxDescent)
- // Return our size and our status
- #endif
- }
-
- // Vertically align the children
- nscoord lineHeight =
- nsCSSLayout::VerticallyAlignChildren(aPresContext, this, styleFont,
- borderPadding.top,
- mFirstChild, mChildCount,
- state.ascents, state.maxAscent);
-
- ComputeFinalSize(aPresContext, state, aDesiredSize);
-
-#ifdef NS_DEBUG
- if (GetVerifyTreeEnable()) {
- PostReflowCheck(aStatus);
- }
-#endif
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("exit nsInlineFrame::Reflow: this=%p: childCount=%d status=%scomplete",
- this, mChildCount,
- NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not "));
- return NS_OK;
-}
-
-void
-nsInlineFrame::ComputeFinalSize(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsReflowMetrics& aDesiredSize)
-{
- // Compute default size
- aDesiredSize.width = aState.x + aState.borderPadding.right;
- aDesiredSize.ascent = aState.borderPadding.top + aState.maxAscent;
- aDesiredSize.descent = aState.maxDescent + aState.borderPadding.bottom;
- aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
-
- // Apply width/height style properties
- PRIntn ss = aState.mStyleSizeFlags;
- if (0 != (ss & NS_SIZE_HAS_WIDTH)) {
- aDesiredSize.width = aState.borderPadding.left + aState.mStyleSize.width +
- aState.borderPadding.right;
- }
- if (0 != (ss & NS_SIZE_HAS_HEIGHT)) {
- aDesiredSize.height = aState.borderPadding.top + aState.mStyleSize.height +
- aState.borderPadding.bottom;
- }
-
- if ((nsnull != aDesiredSize.maxElementSize) && aState.mNoWrap) {
- aDesiredSize.maxElementSize->width = aDesiredSize.width;
- aDesiredSize.maxElementSize->height = aDesiredSize.height;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-PRIntn nsInlineFrame::GetSkipSides() const
-{
- PRIntn skip = 0;
- if (nsnull != mPrevInFlow) {
- skip |= 1 << NS_SIDE_LEFT;
- }
- if (nsnull != mNextInFlow) {
- skip |= 1 << NS_SIDE_RIGHT;
- }
- return skip;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-// Incremental reflow support
-
-NS_METHOD nsInlineFrame::GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics)
-{
- nscoord maxAscent = 0;
- nscoord maxDescent = 0;
- nsIFrame* kid = mFirstChild;
- while (nsnull != kid) {
- // XXX Properly handle max element size...
- nsReflowMetrics kidMetrics(aMetrics.maxElementSize);
- kid->GetReflowMetrics(aPresContext, kidMetrics);
- if (kidMetrics.ascent > maxAscent) maxAscent = kidMetrics.ascent;
- if (kidMetrics.descent > maxDescent) maxDescent = kidMetrics.descent;
- kid->GetNextSibling(kid);
- }
-
- // XXX what about border & padding
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
- aMetrics.ascent = maxAscent;
- aMetrics.descent = maxDescent;
-
- return NS_OK;
-}
-
-/**
- * Setup aState to the state it would have had we just reflowed our
- * children up to, but not including, aSkipChild. Return the index
- * of aSkipChild in our list of children.
- * If aSkipChild is nsnull then resets the state for appended content.
- */
-PRInt32 nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aSkipChild)
-{
- // Get ascent & descent info for all the children up to but not
- // including aSkipChild. Also compute the x coordinate for where
- // aSkipChild will be place after it is reflowed.
- PRInt32 i = 0;
- nsIFrame* kid = mFirstChild;
- nscoord x = aState.x;
- nscoord maxAscent = 0;
- nscoord maxDescent = 0;
- while ((nsnull != kid) && (kid != aSkipChild)) {
- nsReflowMetrics kidMetrics(nsnull);
- kid->GetReflowMetrics(aPresContext, kidMetrics);
- aState.ascents[i] = kidMetrics.ascent;
- if (kidMetrics.ascent > maxAscent) maxAscent = kidMetrics.ascent;
- if (kidMetrics.descent > maxDescent) maxDescent = kidMetrics.descent;
-
- // XXX Factor in left and right margins
- x += kidMetrics.width;
-
- kid->GetNextSibling(kid);
- i++;
- }
- aState.maxAscent = maxAscent;
- aState.maxDescent = maxDescent;
- aState.x = x;
- return i;
-}
-
-// XXX We need to return information about whether our next-in-flow is
-// dirty...
-nsReflowStatus
-nsInlineFrame::IncrementalReflowFrom(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex)
-{
- nsReflowStatus status = NS_FRAME_COMPLETE;
-
- // Just reflow all the mapped children starting with childFrame.
- // XXX This isn't the optimal thing to do...
- if (ReflowMappedChildrenFrom(aPresContext, aState, aChildFrame, aChildIndex)) {
- if (NextChildOffset() < mContent->ChildCount()) {
-#if XXX
- // Any space left?
- if (aState.availSize.width <= 0) {
- // No space left. Don't try to pull-up children
- status = NS_FRAME_NOT_COMPLETE;
- } else
-#endif
- {
- // Try and pull-up some children from a next-in-flow
- if (!PullUpChildren(aPresContext, aState)) {
- // We were not able to pull-up all the child frames from our
- // next-in-flow
- status = NS_FRAME_NOT_COMPLETE;
- }
- }
- }
- } else {
- // We were unable to reflow all our mapped frames
- status = NS_FRAME_NOT_COMPLETE;
- }
-
- return status;
-}
-
-nsReflowStatus
-nsInlineFrame::IncrementalReflowAfter(nsIPresContext* aPresContext,
- nsInlineState& aState,
- nsIFrame* aChildFrame,
- PRInt32 aChildIndex)
-{
- nsReflowStatus status = NS_FRAME_COMPLETE;
- nsIFrame* nextFrame;
-
- aChildFrame->GetNextSibling(nextFrame);
-
- // Just reflow all the remaining mapped children
- // XXX This isn't the optimal thing to do...
- if ((nsnull == nextFrame) ||
- ReflowMappedChildrenFrom(aPresContext, aState, nextFrame, aChildIndex + 1)) {
- if (NextChildOffset() < mContent->ChildCount()) {
-#if XXX
- // Any space left?
- if (aState.availSize.width <= 0) {
- // No space left. Don't try to pull-up children
- status = NS_FRAME_NOT_COMPLETE;
- } else
-#endif
- {
- // Try and pull-up some children from a next-in-flow
- if (!PullUpChildren(aPresContext, aState)) {
- // We were not able to pull-up all the child frames from our
- // next-in-flow
- status = NS_FRAME_NOT_COMPLETE;
- }
- }
- }
- } else {
- // We were unable to reflow all our mapped frames
- status = NS_FRAME_NOT_COMPLETE;
- }
-
- return status;
-}
-
-// In order to execute the vertical alignment code after incremental
-// reflow of the inline frame, we need to reposition any child frames
-// that were relatively positioned back to their computed x origin.
-// This should probably be done as a pre-alignment computation (and it
-// can be avoided if there are no relatively positioned children).
diff --git a/mozilla/layout/html/base/src/nsLeafFrame.cpp b/mozilla/layout/html/base/src/nsLeafFrame.cpp
index cb98d4125ea..601c890906d 100644
--- a/mozilla/layout/html/base/src/nsLeafFrame.cpp
+++ b/mozilla/layout/html/base/src/nsLeafFrame.cpp
@@ -60,6 +60,7 @@ NS_METHOD nsLeafFrame::Reflow(nsIPresContext* aPresContext,
// XXX add in code to check for width/height being set via css
// and if set use them instead of calling GetDesiredSize.
+
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
AddBordersAndPadding(aPresContext, aDesiredSize);
if (nsnull != aDesiredSize.maxElementSize) {
diff --git a/mozilla/layout/html/base/src/nsLineLayout.cpp b/mozilla/layout/html/base/src/nsLineLayout.cpp
deleted file mode 100644
index 1b651ec97b3..00000000000
--- a/mozilla/layout/html/base/src/nsLineLayout.cpp
+++ /dev/null
@@ -1,1695 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#include "nsLineLayout.h"
-#include "nsIStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsBlockFrame.h"
-#include "nsIContent.h"
-#include "nsIContentDelegate.h"
-#include "nsIPresContext.h"
-#include "nsISpaceManager.h"
-#include "nsIPtr.h"
-#include "nsAbsoluteFrame.h"
-#include "nsPlaceholderFrame.h"
-#include "nsCSSLayout.h"
-#include "nsCRT.h"
-#include "nsIReflowCommand.h"
-#include "nsIFontMetrics.h"
-#include "nsHTMLBase.h"
-#include "nsScrollFrame.h"
-
-#undef NOISY_REFLOW
-
-// XXX zap mAscentNum
-
-NS_DEF_PTR(nsIContent);
-NS_DEF_PTR(nsIStyleContext);
-
-nsLineData::nsLineData()
-{
- mNextLine = nsnull;
- mPrevLine = nsnull;
- mFirstChild = nsnull;
- mChildCount = 0;
- mFirstContentOffset = 0;
- mLastContentOffset = 0;
- mLastContentIsComplete = PR_TRUE;
- mIsBlock = PR_FALSE;
- mBounds.SetRect(0, 0, 0, 0);
- mFloaters = nsnull;
-}
-
-nsLineData::~nsLineData()
-{
- delete mFloaters;
-}
-
-void
-nsLineData::UnlinkLine()
-{
- nsLineData* prevLine = mPrevLine;
- nsLineData* nextLine = mNextLine;
- if (nsnull != nextLine) nextLine->mPrevLine = prevLine;
- if (nsnull != prevLine) prevLine->mNextLine = nextLine;
-}
-
-nsresult
-nsLineData::Verify(PRBool aFinalCheck) const
-{
- NS_ASSERTION(mNextLine != this, "bad line linkage");
- NS_ASSERTION(mPrevLine != this, "bad line linkage");
- if (nsnull != mPrevLine) {
- NS_ASSERTION(mPrevLine->mNextLine == this, "bad line linkage");
- }
- if (nsnull != mNextLine) {
- NS_ASSERTION(mNextLine->mPrevLine == this, "bad line linkage");
- }
-
- if (aFinalCheck) {
- NS_ASSERTION(0 != mChildCount, "empty line");
- NS_ASSERTION(nsnull != mFirstChild, "empty line");
-
- nsIFrame* nextLinesFirstChild = nsnull;
- if (nsnull != mNextLine) {
- nextLinesFirstChild = mNextLine->mFirstChild;
- }
-
- // Check that number of children are ok and that the index in parent
- // information agrees with the content offsets.
- PRInt32 offset = mFirstContentOffset;
- PRInt32 len = 0;
- nsIFrame* child = mFirstChild;
- while ((nsnull != child) && (child != nextLinesFirstChild)) {
- PRInt32 indexInParent;
- child->GetContentIndex(indexInParent);
- NS_ASSERTION(indexInParent == offset, "bad line offsets");
- len++;
- if (len != mChildCount) {
- offset++;
- }
- child->GetNextSibling(child);
- }
- NS_ASSERTION(offset == mLastContentOffset, "bad mLastContentOffset");
- NS_ASSERTION(len == mChildCount, "bad child count");
- }
-
- if (1 == mChildCount) {
- if (mIsBlock) {
- nsIFrame* child = mFirstChild;
- const nsStyleDisplay* display;
- child->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
- NS_ASSERTION((NS_STYLE_DISPLAY_BLOCK == display->mDisplay) ||
- (NS_STYLE_DISPLAY_LIST_ITEM == display->mDisplay),
- "bad mIsBlock state");
- }
- }
-
- // XXX verify content offsets and mLastContentIsComplete
- return NS_OK;
-}
-
-nsIFrame*
-nsLineData::GetLastChild()
-{
- nsIFrame* lastChild = mFirstChild;
- if (mChildCount > 1) {
- for (PRInt32 numKids = mChildCount - 1; --numKids >= 0; ) {
- nsIFrame* nextChild;
- lastChild->GetNextSibling(nextChild);
- lastChild = nextChild;
- }
- }
- return lastChild;
-}
-
-PRIntn
-nsLineData::GetLineNumber() const
-{
- PRIntn lineNumber = 0;
- nsLineData* prev = mPrevLine;
- while (nsnull != prev) {
- lineNumber++;
- prev = prev->mPrevLine;
- }
- return lineNumber;
-}
-
-void
-nsLineData::List(FILE* out, PRInt32 aIndent) const
-{
- // Indent
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
-
- // Output the first/last content offset
- fprintf(out, "line %d [%d,%d,%c] ",
- GetLineNumber(),
- mFirstContentOffset, mLastContentOffset,
- (mLastContentIsComplete ? 'T' : 'F'));
-
- // Output the bounds rect
- out << mBounds;
-
- // Output the children, one line at a time
- if (nsnull != mFirstChild) {
- fputs("<\n", out);
- aIndent++;
-
- nsIFrame* child = mFirstChild;
- for (PRInt32 numKids = mChildCount; --numKids >= 0; ) {
- child->List(out, aIndent);
- child->GetNextSibling(child);
- }
-
- aIndent--;
- for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
- fputs(">\n", out);
- } else {
- fputs("<>\n", out);
- }
-}
-
-//----------------------------------------------------------------------
-
-nsLineLayout::nsLineLayout(nsBlockReflowState& aState)
- : mBlockReflowState(aState)
-{
- mBlock = aState.mBlock;
- mSpaceManager = aState.mSpaceManager;
- mBlock->GetContent(mBlockContent);
- mPresContext = aState.mPresContext;
- mUnconstrainedWidth = aState.mUnconstrainedWidth;
- mUnconstrainedHeight = aState.mUnconstrainedHeight;
- mMaxElementSizePointer = aState.mMaxElementSizePointer;
-
- mAscents = mAscentBuf;
- mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
-}
-
-nsLineLayout::~nsLineLayout()
-{
- NS_IF_RELEASE(mBlockContent);
- if (mAscents != mAscentBuf) {
- delete [] mAscents;
- }
-}
-
-nsresult
-nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
-{
- nsresult rv = NS_OK;
-
- SetReflowSpace(aState.mCurrentBand.availSpace);
-
- mState.mSkipLeadingWhiteSpace = PR_TRUE;
- mState.mColumn = 0;
-
- mState.mKidFrame = nsnull;
- mState.mPrevKidFrame = nsnull;
- mState.mKidIndex = aLine->mFirstContentOffset;
- mState.mKidFrameNum = 0;
- mState.mMaxElementSize.width = 0;
- mState.mMaxElementSize.height = 0;
- mState.mMaxAscent = nsnull;
- mState.mMaxDescent = nsnull;
-
- mSavedState.mKidFrame = nsnull;
- mBreakFrame = nsnull;
- mPendingBreak = NS_STYLE_CLEAR_NONE;
-
- mLine = aLine;
- mKidPrevInFlow = nsnull;
- mNewFrames = 0;
- mFramesReflowed = 0;
-
- mMarginApplied = PR_FALSE;
-
- mMustReflowMappedChildren = PR_FALSE;
- mY = aState.mY;
- mMaxHeight = aState.mAvailSize.height;
- mReflowDataChanged = PR_FALSE;
-
- mLineHeight = 0;
-
- mNoWrap = PR_FALSE;
- const nsStyleText* styleText;
- mBlock->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)styleText);
- switch (styleText->mWhiteSpace) {
- case NS_STYLE_WHITESPACE_PRE:
- case NS_STYLE_WHITESPACE_NOWRAP:
- mNoWrap = PR_TRUE;
- break;
- }
-
- return rv;
-}
-
-void
-nsLineLayout::SetReflowSpace(nsRect& aAvailableSpaceRect)
-{
- nscoord x0 = aAvailableSpaceRect.x;
- mLeftEdge = x0;
- mState.mX = x0;
- mRightEdge = x0 + aAvailableSpaceRect.width;
-
- mMaxWidth = mRightEdge - x0;
- mReflowDataChanged = PR_TRUE;
- mMustReflowMappedChildren = PR_TRUE;
-}
-
-nsresult
-nsLineLayout::SetAscent(nscoord aAscent)
-{
- PRInt32 kidFrameNum = mState.mKidFrameNum;
- if (kidFrameNum == mMaxAscents) {
- mMaxAscents *= 2;
- nscoord* newAscents = new nscoord[mMaxAscents];
- if (nsnull != newAscents) {
- nsCRT::memcpy(newAscents, mAscents, sizeof(nscoord) * kidFrameNum);
- if (mAscents != mAscentBuf) {
- delete [] mAscents;
- }
- mAscents = newAscents;
- } else {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- }
- mAscents[kidFrameNum] = aAscent;
- return NS_OK;
-}
-
-void
-nsLineLayout::AtSpace()
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::AtSpace: kidFrame=%p kidIndex=%d mX=%d",
- mState.mKidFrame, mState.mKidIndex, mState.mX));
- mBreakFrame = nsnull;
- mSavedState.mKidFrame = nsnull;
-}
-
-void
-nsLineLayout::AtWordStart(nsIFrame* aFrame, nscoord aX)
-{
- if (nsnull == mBreakFrame) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::AtWordStart: aFrame=%p kidFrame=%p[%d] aX=%d mX=%d",
- aFrame,
- mState.mKidFrame, mState.mKidIndex,
- aX, mState.mX));
-
- mSavedState = mState;
- mBreakFrame = aFrame;
- mBreakX = aX;
- }
- else if (mBreakFrame == aFrame) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::AtWordStart: update aX=%d", aX));
- NS_ASSERTION((mSavedState.mKidFrame == mState.mKidFrame) &&
- (mSavedState.mKidIndex == mState.mKidIndex) &&
- (mSavedState.mKidFrameNum == mState.mKidFrameNum),
- "bad break state");
- mBreakX = aX;
- }
-}
-
-PRBool
-nsLineLayout::CanBreak()
-{
- if (nsnull == mBreakFrame) {
- // There is no word to break at
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::CanBreak: no break frame"));
- return PR_FALSE;
- }
-
- if (mSavedState.mKidFrame == mLine->mFirstChild) {
- // The line's first frame contains the break position; we are not
- // allowed to break if the break would empty the line.
- if (0 == mBreakX) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::CanBreak: breakX=0"));
- return PR_FALSE;
- }
- }
-
- // Compute the break x coordinate in our coordinate system by adding
- // in the X coordinates of each of the frames between the break
- // frame and the containing block frame.
- nscoord breakX = mBreakX;
- nsIFrame* frame = mBreakFrame;
- for (;;) {
- nsRect r;
- frame->GetRect(r);
- breakX += r.x;
- nsIFrame* parent;
- frame->GetGeometricParent(parent);
- if (parent == mBlock) {
- break;
- }
- frame = parent;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::CanBreak: backup from=%p[%d]/%d to=%p[%d]/%d breakX=%d",
- mState.mKidFrame, mState.mKidIndex, mState.mKidFrameNum,
- mSavedState.mKidFrame, mSavedState.mKidIndex, mSavedState.mKidFrameNum,
- breakX));
-
- // Revert the line layout back to where it was when the break point
- // was found.
- mState = mSavedState;
-
- // Change the right edge to the breakX so that when we reflow the
- // child it will stop just before the break point.
- mRightEdge = breakX;
-
- // Forgot word break
- mSavedState.mKidFrame = nsnull;
- mBreakFrame = nsnull;
-
- return PR_TRUE;
-}
-
-/**
- * Attempt to avoid reflowing a child by seeing if it's been touched
- * since the last time it was reflowed.
- */
-nsresult
-nsLineLayout::ReflowMappedChild()
-{
- nsIFrame* kidFrame = mState.mKidFrame;
-
- if (mMustReflowMappedChildren || PR_TRUE) {
-/*
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: must reflow frame=%p[%d]",
- kidFrame, mKidIndex));
-*/
- return ReflowChild(nsnull, PR_FALSE);
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: attempt frame=%p[%d]",
- kidFrame, mState.mKidIndex));
-
- // If the child is a container then we need to reflow it if there is
- // a change in width. Note that if it's an empty container then it
- // doesn't really matter how much space we give it.
- if (mBlockReflowState.mDeltaWidth != 0) {
- nsIFrame* f;
- kidFrame->FirstChild(f);
- if (nsnull != f) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: has children"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-
- // If we need the max-element size and we are splittable then we
- // have to reflow to get it.
- nsSplittableType splits;
- kidFrame->IsSplittable(splits);
-#if 0
- if (nsnull != mMaxElementSizePointer) {
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: need max-element-size"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-#else
- // XXX For now, if the child is splittable we reflow it. The reason
- // is that the text whitespace compression needs to be consulted
- // here to properly handle reflow avoidance. To do that properly we
- // really need a first-rate protocol here (WillPlace?
- // CanAvoidReflow?) that gets the frame involved.
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: splittable hack"));
- return ReflowChild(nsnull, PR_FALSE);
- }
-#endif
-
- nsFrameState state;
- kidFrame->GetFrameState(state);
-
- // XXX a better term for this is "dirty" and once we add a dirty
- // bit that's what we'll do here.
-
- // XXX this check will cause pass2 of table reflow to reflow
- // everything; tables will be even faster if we have a dirty bit
- // instead (that way we can avoid reflowing non-splittables on
- // pass2)
- if (0 != (state & NS_FRAME_IN_REFLOW)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: frame is dirty"));
- return ReflowChild(nsnull, PR_FALSE);
- }
-
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- // XXX a next-in-flow propogated dirty-bit eliminates this code
-
- // The splittable frame has not yet been reflowed. This means
- // that, in theory, its state is well defined. However, if it has
- // a prev-in-flow and that frame has been touched then we need to
- // reflow this frame.
- nsIFrame* prevInFlow;
- kidFrame->GetPrevInFlow(prevInFlow);
- if (nsnull != prevInFlow) {
- nsFrameState prevState;
- prevInFlow->GetFrameState(prevState);
- if (0 != (prevState & NS_FRAME_IN_REFLOW)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: prev-in-flow frame is dirty"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-
- // If the child has a next-in-flow then never-mind, we need to
- // reflow it in case it has more/less space to reflow into.
- nsIFrame* nextInFlow;
- kidFrame->GetNextInFlow(nextInFlow);
- if (nsnull != nextInFlow) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: frame has next-in-flow"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- }
-
- // Success! We have (so far) avoided reflowing the child. However,
- // we do need to place it and advance our position state. Get the
- // size of the child and its reflow metrics for placing.
- nsIStyleContextPtr kidSC;
- nsresult rv = kidFrame->GetStyleContext(mPresContext, kidSC.AssignRef());
- if (NS_OK != rv) {
- return rv;
- }
- const nsStyleDisplay* kidDisplay = (const nsStyleDisplay*)
- kidSC->GetStyleData(eStyleStruct_Display);
- if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
- // XXX If it floats it needs to go through the normal path so that
- // PlaceFloater is invoked.
- return ReflowChild(nsnull, PR_FALSE);
- }
- const nsStyleSpacing* kidSpacing = (const nsStyleSpacing*)
- kidSC->GetStyleData(eStyleStruct_Spacing);
- PRBool isBlock = PR_FALSE;
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- if (kidFrame != mLine->mFirstChild) {
- // Block items must be at the start of a line, therefore we need
- // to break before the block item.
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: block requires break-before"));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- isBlock = PR_TRUE;
- break;
- }
-
- // Compute new total width of child using its current margin values
- // (they may have changed since the last time the child was reflowed)
- nsRect kidRect;
- kidFrame->GetRect(kidRect);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kidFrame, kidMargin);
- nscoord totalWidth;
- totalWidth = kidMargin.left + kidMargin.right + kidRect.width;
-
- // If the child intersects the area affected by the reflow then
- // we need to reflow it.
- nscoord x = mState.mX;
- if (x + kidMargin.left + kidRect.width > mRightEdge) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: failed edge test"));
- // XXX if !splittable then return NS_LINE_LAYOUT_BREAK_BEFORE
- return ReflowChild(nsnull, PR_FALSE);
- }
-
- // Make sure the child will fit. The child always fits if it's the
- // first child on the line.
- nscoord availWidth = mRightEdge - x;
- if (mUnconstrainedWidth ||
- (kidFrame == mLine->mFirstChild) ||
- (totalWidth <= availWidth)) {
- // By convention, mReflowResult is set during ResizeReflow,
- // IncrementalReflow AND GetReflowMetrics by those frames that are
- // line layout aware.
- mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
- nsReflowMetrics kidMetrics(nsnull);
- kidFrame->GetReflowMetrics(mPresContext, kidMetrics);
-
- nsSize maxElementSize;
- nsSize* kidMaxElementSize = nsnull;
- if (nsnull != mMaxElementSizePointer) {
- kidMaxElementSize = &maxElementSize;
- maxElementSize.width = kidRect.width;
- maxElementSize.height = kidRect.height;
- }
- kidRect.x = x + kidMargin.left;
- kidRect.y = mY;
-
- if (NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE == mReflowResult) {
- mState.mSkipLeadingWhiteSpace = PR_FALSE;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: fit size=%d,%d",
- kidRect.width, kidRect.height));
- mLine->mIsBlock = isBlock;
- return PlaceChild(kidRect, kidMetrics, kidMaxElementSize, kidMargin,
- NS_FRAME_COMPLETE);
- }
-
- // The child doesn't fit as is; if it's splittable then reflow it
- // otherwise return break-before status so that the non-splittable
- // child is pushed to the next line.
- if (NS_FRAME_IS_SPLITTABLE(splits)) {
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowMappedChild: can't directly fit"));
- return ReflowChild(nsnull, PR_FALSE);
- }
- return NS_LINE_LAYOUT_BREAK_BEFORE;
-}
-
-// Return values: <0 for error
-// 0 == NS_LINE_LAYOUT
-nsresult
-nsLineLayout::ReflowChild(nsIReflowCommand* aReflowCommand,
- PRBool aNewChild)
-{
- nsIFrame* kidFrame = mState.mKidFrame;
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: attempt frame=%p[%d] mX=%d availWidth=%d",
- kidFrame, mState.mKidIndex,
- mState.mX, mRightEdge - mState.mX));
-
- // Get kid frame's style context
- nsIStyleContextPtr kidSC;
- nsresult rv = kidFrame->GetStyleContext(mPresContext, kidSC.AssignRef());
- if (NS_OK != rv) {
- return rv;
- }
-
- // See if frame belongs in the line.
- // XXX absolute positioning
- // XXX floating frames
- // XXX break-before
- const nsStyleDisplay * kidDisplay = (const nsStyleDisplay*)
- kidSC->GetStyleData(eStyleStruct_Display);
- PRBool isBlock = PR_FALSE;
- PRBool isFirstChild = PRBool(kidFrame == mLine->mFirstChild);
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_NONE:
- // Make sure the frame remains zero sized.
- kidFrame->WillReflow(*mPresContext);
- kidFrame->SetRect(nsRect(mState.mX, mY, 0, 0));
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: display=none"));
- return NS_LINE_LAYOUT_COMPLETE;
-
- case NS_STYLE_DISPLAY_INLINE:
- break;
-
- default:
- isBlock = PR_TRUE;
- if (!isFirstChild) {
- // XXX Make sure child is dirty for next time
- kidFrame->WillReflow(*mPresContext);
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: block requires break-before"));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- break;
- }
-
- // Get the available size to reflow the child into
- PRBool didBreak = PR_FALSE;
- reflow_it_again_sam:
- nscoord availWidth = mRightEdge - mState.mX;
- nsSize kidAvailSize;
- kidAvailSize.width = availWidth;
- kidAvailSize.height = mMaxHeight;
- const nsStyleSpacing* kidSpacing = (const nsStyleSpacing*)
- kidSC->GetStyleData(eStyleStruct_Spacing);
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kidFrame, kidMargin);
- if (!mUnconstrainedWidth) {
- if (mNoWrap) {
- // When our reflow is constrained and we are we are not supposed
- // to wrap make sure the child will fit regardless of how much
- // space is left.
- if (isBlock) {
- // Never give a block an infinite width
- kidAvailSize.width = mRightEdge - mLeftEdge;
- }
- else {
- kidAvailSize.width = NS_UNCONSTRAINEDSIZE;
- }
- }
- else {
- kidAvailSize.width -= kidMargin.left + kidMargin.right;
- if (!isFirstChild && (kidAvailSize.width <= 0)) {
- // No room.
- if (!didBreak && CanBreak()) {
- kidFrame = mState.mKidFrame;
- didBreak = PR_TRUE;
- mPendingBreak = NS_STYLE_CLEAR_NONE;
- goto reflow_it_again_sam;
- }
-
- // XXX Make sure child is dirty for next time
- kidFrame->WillReflow(*mPresContext);
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: !fit"));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- }
- }
-
- // Reflow the child
- mFramesReflowed++;
- nsRect kidRect;
- nsSize maxElementSize;
- nsSize* kidMaxElementSize = nsnull;
- nsReflowStatus kidReflowStatus;
- if (nsnull != mMaxElementSizePointer) {
- kidMaxElementSize = &maxElementSize;
- }
- nsReflowMetrics kidMetrics(kidMaxElementSize);
-
- // Get reflow reason set correctly. It's possible that we created a
- // child and then decided that we cannot reflow it (for example, a
- // block frame that isn't at the start of a line). In this case the
- // reason will be wrong so we need to check the frame state.
- nsReflowReason kidReason = eReflowReason_Resize;
- if (nsnull != aReflowCommand) {
- kidReason = eReflowReason_Incremental;
- }
- else if (aNewChild) {
- kidReason = eReflowReason_Initial;
- }
- else {
- nsFrameState state;
- kidFrame->GetFrameState(state);
- if (NS_FRAME_FIRST_REFLOW & state) {
- kidReason = eReflowReason_Initial;
- }
- }
-
- nsReflowState kidReflowState(kidFrame, *mBlockReflowState.reflowState,
- kidAvailSize, kidReason);
- kidReflowState.reflowCommand = aReflowCommand;
- mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
- nscoord dx = mState.mX + kidMargin.left;
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: reflowing frame into %d,%d",
- kidAvailSize.width, kidAvailSize.height));
- if (isBlock) {
- // Calculate top margin by collapsing with previous bottom margin
- nscoord negTopMargin;
- nscoord posTopMargin;
- nsMargin kidMargin;
- kidSpacing->CalcMarginFor(kidFrame, kidMargin);
- if (kidMargin.top < 0) {
- negTopMargin = -kidMargin.top;
- posTopMargin = 0;
- } else {
- negTopMargin = 0;
- posTopMargin = kidMargin.top;
- }
-
- // XXX if (nav4_compatability)
- // Calculate the previous margin's positive and negative value.
- // If the current top margin is not defined by css then just use
- // what is cached in the block reflow state. Otherwise if the top
- // margin is defined by css then wipe out any synthetic margin.
- nscoord prevPos = mBlockReflowState.mPrevPosBottomMargin;
- nscoord prevNeg = mBlockReflowState.mPrevNegBottomMargin;
- if (eStyleUnit_Null != kidSpacing->mMargin.GetTopUnit()) {
- if (mBlockReflowState.mPrevMarginSynthetic) {
- prevPos = 0;
- prevNeg = 0;
- }
- }
- else {
- // When our top margin is not specified by css...act like
- // ebina's engine.
- if ((nsnull != mLine->mPrevLine) && !mLine->mPrevLine->mIsBlock) {
- // Supply a default top margin
- const nsStyleFont* styleFont;
- mBlock->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)styleFont);
- nsIFontMetrics* fm = mPresContext->GetMetricsFor(styleFont->mFont);
- mBlockReflowState.mPrevNegBottomMargin = 0;
- mBlockReflowState.mPrevPosBottomMargin = fm->GetHeight();
- mBlockReflowState.mPrevMarginSynthetic = PR_TRUE;
- NS_RELEASE(fm);
- }
- }
-
- nscoord maxPos = PR_MAX(prevPos, posTopMargin);
- nscoord maxNeg = PR_MAX(prevNeg, negTopMargin);
- nscoord topMargin = maxPos - maxNeg;
-
- // This is no longer a break point
- mSavedState.mKidFrame = nsnull;
- mBreakFrame = nsnull;
-
- mY += topMargin;
- mBlockReflowState.mY += topMargin;
- // XXX tell block what topMargin ended up being so that it can
- // undo it if it ends up pushing the line.
-
- NS_ASSERTION(0 == mPendingBreak, "whoops: uncleared break");
- mSpaceManager->Translate(dx, mY);
- kidFrame->WillReflow(*mPresContext);
- kidFrame->MoveTo(dx, mY);
- rv = mBlock->ReflowBlockChild(kidFrame, mPresContext,
- mSpaceManager, kidMetrics, kidReflowState,
- kidRect, kidReflowStatus);
- mSpaceManager->Translate(-dx, -mY);
-
- if ((0 == kidRect.width) && (0 == kidRect.height)) {
- // When a block child collapses into nothingness we don't apply
- // it's margins.
- mY -= topMargin;
- mBlockReflowState.mY -= topMargin;
- }
- else {
- // XXX if (nav4_compatability)
- // If the block frame we just reflowed has no bottom margin as
- // specified by css, then we supply our own.
- if (eStyleUnit_Null == kidSpacing->mMargin.GetBottomUnit()) {
- // ebina's engine uses the height of the font for the bottom margin.
- nsIStyleContext* blockSC;
- const nsStyleFont* styleFont;
- mBlock->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)styleFont);
- nsIFontMetrics* fm = mPresContext->GetMetricsFor(styleFont->mFont);
- mBlockReflowState.mPrevNegBottomMargin = 0;
- mBlockReflowState.mPrevPosBottomMargin = fm->GetHeight();
- mBlockReflowState.mPrevMarginSynthetic = PR_TRUE;
- NS_RELEASE(fm);
- }
- else {
- // Save away bottom margin information for later
- if (kidMargin.bottom < 0) {
- mBlockReflowState.mPrevNegBottomMargin = -kidMargin.bottom;
- mBlockReflowState.mPrevPosBottomMargin = 0;
- } else {
- mBlockReflowState.mPrevNegBottomMargin = 0;
- mBlockReflowState.mPrevPosBottomMargin = kidMargin.bottom;
- }
- mBlockReflowState.mPrevMarginSynthetic = PR_FALSE;
- }
- }
-
- kidRect.x = dx;
- kidRect.y = mY;
- kidMetrics.width = kidRect.width;
- kidMetrics.height = kidRect.height;
- kidMetrics.ascent = kidRect.height;
- kidMetrics.descent = 0;
- }
- else {
- // Apply bottom margin speculatively before reflowing the child
- nscoord bottomMargin = mBlockReflowState.mPrevPosBottomMargin -
- mBlockReflowState.mPrevNegBottomMargin;
- if (!mMarginApplied) {
- // Before we place the first inline child on this line apply
- // the previous block's bottom margin.
- mY += bottomMargin;
- mBlockReflowState.mY += bottomMargin;
- }
-
- NS_ASSERTION(0 == mPendingBreak, "whoops: uncleared break");
- kidFrame->WillReflow(*mPresContext);
- kidFrame->MoveTo(dx, mY);
- rv = mBlock->ReflowInlineChild(*this, kidFrame, kidMetrics,
- kidReflowState, kidReflowStatus);
-
- // See if speculative application of the margin should stick
- if (!mMarginApplied) {
- if (0 == kidMetrics.height) {
- // No, undo margin application when we get a zero height child.
- mY -= bottomMargin;
- mBlockReflowState.mY -= bottomMargin;
- }
- else {
- // Yes, keep the margin application.
- mMarginApplied = PR_TRUE;
- mBlockReflowState.mPrevPosBottomMargin = 0;
- mBlockReflowState.mPrevNegBottomMargin = 0;
- // XXX tell block what bottomMargin ended up being so that it can
- // undo it if it ends up pushing the line.
- }
- }
-
- kidRect.x = dx;
- kidRect.y = mY;
- kidRect.width = kidMetrics.width;
- kidRect.height = kidMetrics.height;
- }
- if (NS_OK != rv) return rv;
-
- // See if the child fit
- if (kidMetrics.width > kidAvailSize.width) {
- if (!isFirstChild) {
- if (!didBreak && CanBreak()) {
- kidFrame = mState.mKidFrame;
- didBreak = PR_TRUE;
- mPendingBreak = NS_STYLE_CLEAR_NONE;
- goto reflow_it_again_sam;
- }
- else {
- // We are out of room.
- // XXX mKidPrevInFlow
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: !fit size=%d,%d",
- kidRect.width, kidRect.height));
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
- }
- }
-
- // Non-aware children that take up space act like words; which means
- // that space immediately following them must not be skipped over.
- if (NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE == mReflowResult) {
- if ((kidRect.width != 0) && (kidRect.height != 0)) {
- mState.mSkipLeadingWhiteSpace = PR_FALSE;
- }
- }
-
- // Now place the child
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::ReflowChild: fit size=%d,%d",
- kidRect.width, kidRect.height));
- mLine->mIsBlock = isBlock;
- return PlaceChild(kidRect, kidMetrics, kidMaxElementSize,
- kidMargin, kidReflowStatus);
-}
-
-nsresult
-nsLineLayout::PlaceChild(nsRect& kidRect,
- const nsReflowMetrics& kidMetrics,
- const nsSize* kidMaxElementSize,
- const nsMargin& kidMargin,
- nsReflowStatus kidReflowStatus)
-{
- nscoord horizontalMargins = 0;
-
- // Special case to position outside list bullets.
- // XXX RTL bullets
- PRBool isBullet = PR_FALSE;
- if (mBlockReflowState.mListPositionOutside) {
- PRBool isFirstChild = PRBool(mState.mKidFrame == mLine->mFirstChild);
- PRBool isFirstLine = PRBool(nsnull == mLine->mPrevLine);
- if (isFirstChild && isFirstLine) {
- nsIFrame* blockPrevInFlow;
- mBlock->GetPrevInFlow(blockPrevInFlow);
- PRBool isFirstInFlow = PRBool(nsnull == blockPrevInFlow);
- if (isFirstInFlow) {
- isBullet = PR_TRUE;
- // We are placing the first child of the block therefore this
- // is the bullet that is being reflowed. The bullet is placed
- // in the padding area of this block. Don't worry about
- // getting the Y coordinate of the bullet right (vertical
- // alignment will take care of that).
-
- // Compute gap between bullet and inner rect left edge
- const nsStyleFont* font;
- mBlock->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)font);
- nsIFontMetrics* fm = mPresContext->GetMetricsFor(font->mFont);
- nscoord kidAscent = fm->GetMaxAscent();
- nscoord dx = fm->GetHeight() / 2; // from old layout engine
- NS_RELEASE(fm);
-
- // XXX RTL bullets
- kidRect.x = mState.mX - kidRect.width - dx;
- mState.mKidFrame->SetRect(kidRect);
- }
- }
- }
- if (!isBullet) {
- // Place normal in-flow child
- mState.mKidFrame->SetRect(kidRect);
-
- // Advance
- // XXX RTL
- horizontalMargins = kidMargin.left + kidMargin.right;
- nscoord totalWidth = kidMetrics.width + horizontalMargins;
- mState.mX += totalWidth;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::PlaceChild: frame=%p[%d] {%d, %d, %d, %d}",
- mState.mKidFrame,
- mState.mKidIndex,
- kidRect.x, kidRect.y, kidRect.width, kidRect.height));
-
- if (nsnull != mMaxElementSizePointer) {
- // XXX I'm not certain that this is doing the right thing; rethink this
- nscoord elementWidth = kidMaxElementSize->width + horizontalMargins;
- if (elementWidth > mState.mMaxElementSize.width) {
- mState.mMaxElementSize.width = elementWidth;
- }
- if (kidMetrics.height > mState.mMaxElementSize.height) {
- mState.mMaxElementSize.height = kidMetrics.height;
- }
- }
- if (kidMetrics.ascent > mState.mMaxAscent) {
- mState.mMaxAscent = kidMetrics.ascent;
- }
- if (kidMetrics.descent > mState.mMaxDescent) {
- mState.mMaxDescent = kidMetrics.descent;
- }
- SetAscent(mLine->mIsBlock ? 0 : kidMetrics.ascent);
-
- // Set completion status
- nsresult rv = NS_LINE_LAYOUT_COMPLETE;
- mLine->mLastContentOffset = mState.mKidIndex;
- if (NS_FRAME_IS_COMPLETE(kidReflowStatus)) {
- mLine->mLastContentIsComplete = PR_TRUE;
- if (mLine->mIsBlock ||
- (NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER == mReflowResult) ||
- (NS_STYLE_CLEAR_NONE != mPendingBreak)) {
- rv = NS_LINE_LAYOUT_BREAK_AFTER;
- if (NS_STYLE_CLEAR_LINE == mPendingBreak) {
- mPendingBreak = NS_STYLE_CLEAR_NONE;
- }
- }
- mKidPrevInFlow = nsnull;
- }
- else {
- mLine->mLastContentIsComplete = PR_FALSE;
- rv = NS_LINE_LAYOUT_NOT_COMPLETE;
- mKidPrevInFlow = mState.mKidFrame;
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::PlaceChild: rv=%d", rv));
- return rv;
-}
-
-nsresult
-nsLineLayout::IncrementalReflowFromChild(nsIReflowCommand* aReflowCommand,
- nsIFrame* aChildFrame)
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
-
- mLine->mBounds.x = mState.mX;
- mLine->mBounds.y = mY;
- mState.mKidFrame = mLine->mFirstChild;
- mState.mKidFrameNum = 0;
- while (mState.mKidFrameNum < mLine->mChildCount) {
- nsresult childReflowStatus;
- if (mState.mKidFrame == aChildFrame) {
- childReflowStatus = ReflowChild(aReflowCommand, PR_FALSE);
- } else {
- childReflowStatus = ReflowMappedChild();
- }
-
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
-
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
-
-done:
- // Perform alignment operations
- AlignChildren();
-
- // Set final bounds of the line
- mLine->mBounds.height = mLineHeight;
- mLine->mBounds.width = mState.mX - mLine->mBounds.x;
-
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from ReflowMapped");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::SplitLine(PRInt32 aChildReflowStatus)
-{
- PRInt32 pushCount = mLine->mChildCount - mState.mKidFrameNum;
- nsresult rv = NS_LINE_LAYOUT_COMPLETE;
-
- if (NS_LINE_LAYOUT_NOT_COMPLETE == aChildReflowStatus) {
- // When a line is not complete it indicates that the last child on
- // the line reflowed and took some space but wasn't given enough
- // space to complete. Sometimes when this happens we will need to
- // create a next-in-flow for the child.
- nsIFrame* nextInFlow;
- mState.mPrevKidFrame->GetNextInFlow(nextInFlow);
- if (nsnull == nextInFlow) {
- // Create a continuation frame for the child frame and insert it
- // into our lines child list.
- nsIFrame* nextFrame;
- mState.mPrevKidFrame->GetNextSibling(nextFrame);
- nsIStyleContext* kidSC;
- mState.mPrevKidFrame->GetStyleContext(mPresContext, kidSC);
- mState.mPrevKidFrame->CreateContinuingFrame(mPresContext, mBlock, kidSC,
- nextInFlow);
- NS_RELEASE(kidSC);
- if (nsnull == nextInFlow) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- mState.mPrevKidFrame->SetNextSibling(nextInFlow);
- nextInFlow->SetNextSibling(nextFrame);
- mNewFrames++;
-
- // Add new child to our line
- mLine->mChildCount++;
-
- // Set mKidFrame to the new next-in-flow so that we will
- // push it when we push children. Increment the number of
- // remaining kids now that there is one more.
- mState.mKidFrame = nextInFlow;
- pushCount++;
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::SplitLine: created next in flow %p",
- nextInFlow));
- }
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsLineLayout::SplitLine: pushing %d frames",
- pushCount));
-
- if (0 != pushCount) {
- NS_ASSERTION(nsnull != mState.mKidFrame, "whoops");
- nsLineData* from = mLine;
- nsLineData* to = mLine->mNextLine;
- if (nsnull != to) {
- // Only push into the next line if it's empty; otherwise we can
- // end up pushing a frame which is continued into the same frame
- // as it's continuation. This causes all sorts of side effects
- // so we don't allow it.
- if (to->mChildCount != 0) {
- nsLineData* insertedLine = new nsLineData();
- from->mNextLine = insertedLine;
- to->mPrevLine = insertedLine;
- insertedLine->mPrevLine = from;
- insertedLine->mNextLine = to;
- to = insertedLine;
- to->mLastContentOffset = from->mLastContentOffset;
- to->mLastContentIsComplete = from->mLastContentIsComplete;
- }
- } else {
- to = new nsLineData();
- to->mPrevLine = from;
- from->mNextLine = to;
- }
- if (nsnull == to) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- PRInt32 kidIndexInParent;
- mState.mKidFrame->GetContentIndex(kidIndexInParent);
- to->mFirstChild = mState.mKidFrame;
- to->mChildCount += pushCount;
- to->mFirstContentOffset = kidIndexInParent;
-
- // The to-line is going to be reflowed therefore it's last content
- // offset and completion status don't matter. In fact, it's expensive
- // to compute them so don't bother.
-#ifdef NS_DEBUG
- to->mLastContentOffset = -1;
- to->mLastContentIsComplete = PRPackedBool(0x255);
-#endif
-
- from->mChildCount -= pushCount;
- NS_ASSERTION(0 != from->mChildCount, "bad push");
-#ifdef NS_DEBUG
- if (nsIFrame::GetVerifyTreeEnable()) {
- from->Verify();
- }
-#endif
-#ifdef NOISY_REFLOW
- printf("After push, from-line (%d):\n", pushCount);
- from->List(stdout, 1);
- printf("After push, to-line:\n");
- to->List(stdout, 1);
-#endif
- }
-
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("nsLineLayout::SplitLine: returning %d",
- aChildReflowStatus));
- return aChildReflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::ReflowMapped()
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
-
- mState.mKidFrame = mLine->mFirstChild;
- mState.mKidFrameNum = 0;
- while (mState.mKidFrameNum < mLine->mChildCount) {
- nsresult childReflowStatus = ReflowMappedChild();
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame->GetNextSibling(mState.mKidFrame);
- mState.mKidIndex++;
- mState.mKidFrameNum++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
-
-done:
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from ReflowMapped");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-static PRBool
-IsBlock(const nsStyleDisplay* aDisplay)
-{
- switch (aDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- return PR_TRUE;
- }
- return PR_FALSE;
-}
-
-// XXX fix this code to look at the available width and if it's too
-// small for the next child then skip the pullup (and return
-// BREAK_AFTER status).
-
-nsresult
-nsLineLayout::PullUpChildren()
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
- nsIFrame* prevKidFrame = mState.mPrevKidFrame;
-
- nsBlockFrame* currentBlock = mBlock;
- nsLineData* line = mLine->mNextLine;
- while (nsnull != currentBlock) {
-
- // Pull children from the next line
- while (nsnull != line) {
- // Get first child from next line
- mState.mKidFrame = line->mFirstChild;
- if (nsnull == mState.mKidFrame) {
- NS_ASSERTION(0 == line->mChildCount, "bad line list");
- nsLineData* nextLine = line->mNextLine;
- nsLineData* prevLine = line->mPrevLine;
- if (nsnull != prevLine) prevLine->mNextLine = nextLine;
- if (nsnull != nextLine) nextLine->mPrevLine = prevLine;
- delete line;/* XXX free-list in block-reflow-state? */
- line = nextLine;
- continue;
- }
-
- // XXX Avoid the pullup work if the child cannot already fit
- // (e.g. it's not splittable and can't fit)
-
- // XXX change this to use the next-line's mIsBlock when possible
- // (make sure push code set it's properly for this to work: only
- // from reflow-unmapped)
-
- // If the child is a block element then if this is not the first
- // line in the block or if it's the first line and it's not the
- // first child in the line then we cannot pull-up the child.
- nsresult rv;
- const nsStyleDisplay* kidDisplay;
- rv = mState.mKidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- if (IsBlock(kidDisplay)) {
- if ((nsnull != mLine->mPrevLine) || (0 != mLine->mChildCount)) {
- goto done;
- }
- }
-
- // Make pulled child part of this line
- NS_FRAME_LOG(NS_FRAME_TRACE_PUSH_PULL,
- ("nsLineLayout::PullUpChildren: trying to pull frame=%p",
- mState.mKidFrame));
- mLine->mChildCount++;
- if (0 == --line->mChildCount) {
- // Remove empty lines from the list
- nsLineData* nextLine = line->mNextLine;
- nsLineData* prevLine = line->mPrevLine;
- if (nsnull != prevLine) prevLine->mNextLine = nextLine;
- if (nsnull != nextLine) nextLine->mPrevLine = prevLine;
- delete line;/* XXX free-list in block-reflow-state? */
- line = nextLine;
- }
- else {
- // Repair the first content offset of the line. The first
- // child of the line's index-in-parent should be the line's
- // new first content offset.
- mState.mKidFrame->GetNextSibling(line->mFirstChild);
- PRInt32 indexInParent;
- line->mFirstChild->GetContentIndex(indexInParent);
- line->mFirstContentOffset = indexInParent;
-#ifdef NS_DEBUG
- if (nsIFrame::GetVerifyTreeEnable()) {
- line->Verify();
- }
-#endif
- }
-
- // Try to reflow it like any other mapped child
- nsresult childReflowStatus = ReflowMappedChild();
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidIndex++;
- mState.mKidFrameNum++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidIndex++;
- mState.mKidFrameNum++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
-
- // Grab the block's next in flow
- nsIFrame* nextInFlow;
- currentBlock->GetNextInFlow(nextInFlow);
- currentBlock = (nsBlockFrame*)nextInFlow;
- if (nsnull != currentBlock) {
- line = currentBlock->GetFirstLine();
- }
- }
-
-done:
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from PullUpChildren");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::CreateFrameFor(nsIContent* aKid)
-{
- nsIStyleContextPtr kidSC =
- mPresContext->ResolveStyleContextFor(aKid, mBlock); // XXX bad API
- if (nsnull == kidSC) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- const nsStylePosition* kidPosition = (const nsStylePosition*)
- kidSC->GetStyleData(eStyleStruct_Position);
- const nsStyleDisplay* kidDisplay = (const nsStyleDisplay*)
- kidSC->GetStyleData(eStyleStruct_Display);
-
- // Check whether it wants to floated or absolutely positioned
- PRBool isBlock = PR_FALSE;
- nsIFrame* kidFrame;
- nsresult rv;
- if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) {
- rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- }
- else if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
- rv = nsPlaceholderFrame::NewFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- }
- else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) ||
- (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) {
- rv = NS_NewScrollFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- }
- else if (nsnull == mKidPrevInFlow) {
- // Create initial frame for the child
- nsIContentDelegate* kidDel;
- switch (kidDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_NONE:
- rv = nsFrame::NewFrame(&kidFrame, aKid, mBlock);
- if (NS_OK == rv) {
- kidFrame->SetStyleContext(mPresContext, kidSC);
- }
- break;
-
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- isBlock = PR_TRUE;
- // FALL THROUGH
- default:
- kidDel = aKid->GetDelegate(mPresContext);
- rv = kidDel->CreateFrame(mPresContext, aKid, mBlock, kidSC, kidFrame);
- NS_RELEASE(kidDel);
- break;
- }
- } else {
- // Since kid has a prev-in-flow, use that to create the next
- // frame.
- rv = mKidPrevInFlow->CreateContinuingFrame(mPresContext, mBlock, kidSC,
- kidFrame);
- NS_ASSERTION(0 == mLine->mChildCount, "bad continuation");
- }
- if (NS_OK != rv) {
- return rv;
- }
- if (NS_OK == rv) {
- // Wrap the frame in a view if necessary
- rv = nsHTMLBase::CreateViewForFrame(mPresContext, kidFrame, kidSC,
- PR_FALSE);
- if (NS_OK != rv) {
- return rv;
- }
- }
-
- mState.mKidFrame = kidFrame;
- mNewFrames++;
-
- if (isBlock && (0 != mLine->mChildCount)) {
- // When we are not at the start of a line we need to break
- // before a block element.
- return NS_LINE_LAYOUT_BREAK_BEFORE;
- }
-
- return rv;
-}
-
-nsresult
-nsLineLayout::ReflowUnmapped()
-{
- nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
- for (;;) {
- nsIContentPtr kid = mBlockContent->ChildAt(mState.mKidIndex);
- if (kid.IsNull()) {
- break;
- }
-
- // Create a frame for the new content
- nsresult rv = CreateFrameFor(kid);
- if (rv < 0) {
- reflowStatus = rv;
- goto done;
- }
-
- // Add frame to our list
- if (nsnull != mState.mPrevKidFrame) {
- mState.mPrevKidFrame->SetNextSibling(mState.mKidFrame);
- }
- if (0 == mLine->mChildCount) {
- mLine->mFirstChild = mState.mKidFrame;
- mBlock->SetFirstChild(mState.mKidFrame);
- }
- mLine->mChildCount++;
-
- nsresult childReflowStatus;
- if (rv == NS_LINE_LAYOUT_BREAK_BEFORE) {
- // If we break before a frame is even supposed to layout then we
- // need to split the line.
- childReflowStatus = rv;
-
- // XXX Mark new frame dirty so it gets reflow later on
- mState.mKidFrame->WillReflow(*mPresContext);
- goto split_line;
- }
-
- // Reflow new child frame
- childReflowStatus = ReflowChild(nsnull, PR_TRUE);
- if (childReflowStatus < 0) {
- reflowStatus = childReflowStatus;
- goto done;
- }
- switch (childReflowStatus) {
- default:
- case NS_LINE_LAYOUT_COMPLETE:
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- mState.mKidIndex++;
- break;
-
- case NS_LINE_LAYOUT_NOT_COMPLETE:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_BEFORE:
- reflowStatus = childReflowStatus;
- goto split_line;
-
- case NS_LINE_LAYOUT_BREAK_AFTER:
- reflowStatus = childReflowStatus;
- mState.mPrevKidFrame = mState.mKidFrame;
- mState.mKidFrame = nsnull;
- mState.mKidFrameNum++;
- mState.mKidIndex++;
-
- split_line:
- reflowStatus = SplitLine(childReflowStatus);
- goto done;
- }
- }
- NS_ASSERTION(nsnull == mLine->mNextLine, "bad line list");
-
-done:
- NS_ASSERTION(((reflowStatus < 0) ||
- (reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
- (reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
- "bad return status from ReflowUnmapped");
- return reflowStatus;
-}
-
-//----------------------------------------------------------------------
-
-nsresult
-nsLineLayout::ReflowLine()
-{
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("enter nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
- mLine->mChildCount,
- mLine->mBounds.x, mLine->mBounds.y,
- mLine->mBounds.width, mLine->mBounds.height));
-
- nsresult rv = NS_LINE_LAYOUT_COMPLETE;
-
- mLine->mBounds.x = mState.mX;
- mLine->mBounds.y = mY;
- mOldChildCount = mLine->mChildCount;
-
- // Reflow the mapped frames
- if (0 != mLine->mChildCount) {
- rv = ReflowMapped();
- if (rv < 0) return rv;
- }
-
- // Pull-up any frames from the next line
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- if (nsnull != mLine->mNextLine) {
- rv = PullUpChildren();
- if (rv < 0) return rv;
- }
-
- // Try reflowing any unmapped children
- if (NS_LINE_LAYOUT_COMPLETE == rv) {
- if (nsnull == mLine->mNextLine) {
- rv = ReflowUnmapped();
- if (rv < 0) return rv;
- }
- }
- }
-
- // Perform alignment operations
- AlignChildren();
-
- // Set final bounds of the line
- mLine->mBounds.height = mLineHeight;
- mLine->mBounds.width = mState.mX - mLine->mBounds.x;
-
-#ifdef NS_DEBUG
- if (nsIFrame::GetVerifyTreeEnable()) {
- mLine->Verify();
- }
-#endif
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("exit nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
- mLine->mChildCount,
- mLine->mBounds.x, mLine->mBounds.y,
- mLine->mBounds.width, mLine->mBounds.height));
- return rv;
-}
-
-void
-nsLineLayout::AlignChildren()
-{
- NS_PRECONDITION(mLine->mChildCount == mState.mKidFrameNum, "bad line reflow");
-
- // Block lines don't require (or allow!) alignment
- if (mLine->mIsBlock) {
- mLineHeight = mState.mMaxAscent + mState.mMaxDescent;
- }
- else {
- // Avoid alignment when we didn't actually reflow any frames and we
- // also didn't change the number of frames we had (which means the
- // pullup code didn't pull anything up). When this happens it means
- // that nothing changed which means that we can avoid the alignment
- // work.
- if ((0 == mFramesReflowed) && (mOldChildCount == mLine->mChildCount)) {
- mLineHeight = mLine->mBounds.height;
- }
- }
-
- nsIStyleContextPtr blockSC;
- mBlock->GetStyleContext(mPresContext, blockSC.AssignRef());
- const nsStyleFont* blockFont = (const nsStyleFont*)
- blockSC->GetStyleData(eStyleStruct_Font);
- const nsStyleText* blockText = (const nsStyleText*)
- blockSC->GetStyleData(eStyleStruct_Text);
- const nsStyleDisplay* blockDisplay = (const nsStyleDisplay*)
- blockSC->GetStyleData(eStyleStruct_Display);
-
- // First vertically align the children on the line; this will
- // compute the actual line height for us.
- if (!mLine->mIsBlock) {
- mLineHeight =
- nsCSSLayout::VerticallyAlignChildren(mPresContext, mBlock, blockFont,
- mY,
- mLine->mFirstChild,
- mLine->mChildCount,
- mAscents, mState.mMaxAscent);
- }
-
- // Now horizontally place the children
- nsCSSLayout::HorizontallyPlaceChildren(mPresContext, mBlock,
- blockText->mTextAlign,
- blockDisplay->mDirection,
- mLine->mFirstChild,
- mLine->mChildCount,
- mState.mX - mLeftEdge,
- mMaxWidth);
-
- // Last, apply relative positioning
- nsCSSLayout::RelativePositionChildren(mPresContext, mBlock,
- mLine->mFirstChild,
- mLine->mChildCount);
-}
diff --git a/mozilla/layout/html/base/src/nsLineLayout.h b/mozilla/layout/html/base/src/nsLineLayout.h
deleted file mode 100644
index 34bc57051e2..00000000000
--- a/mozilla/layout/html/base/src/nsLineLayout.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-#ifndef nsLineLayout_h___
-#define nsLineLayout_h___
-
-#include "nsIFrame.h"
-#include "nsCoord.h"
-#include "nsSize.h"
-#include "nsVoidArray.h"
-
-class nsIPresContext;
-class nsISpaceManager;
-class nsBlockFrame;
-struct nsBlockReflowState;
-struct nsLineLayout;
-
-/* d76e29b0-ff56-11d1-89e7-006008911b81 */
-#define NS_IINLINE_FRAME_IID \
-{0xd76e29b0, 0xff56, 0x11d1, {0x89, 0xe7, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
-
-/**
- * Interface to "inline frames". Inline frames are those that are aware
- * of html line layout.
- *
- * Note that this interface does not expose AddRef/Release (like all frame
- * interfaces)
- */
-class nsIInlineFrame : private nsISupports {
-public:
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0;
-
- NS_IMETHOD ReflowInline(nsLineLayout& aLineLayout,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus) = 0;
-};
-
-//----------------------------------------------------------------------
-
-/**
- * Persistent per-line data
- */
-struct nsLineData {
- nsLineData();
- ~nsLineData();
-
- nsIFrame* GetLastChild();
- nsresult Verify(PRBool aFinalCheck = PR_TRUE) const;
- void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
- void UnlinkLine();
- PRIntn GetLineNumber() const;
-
- nsLineData* mNextLine;
- nsLineData* mPrevLine;
- nsIFrame* mFirstChild;
- PRInt32 mChildCount;
- PRInt32 mFirstContentOffset;
- PRInt32 mLastContentOffset;
- nsRect mBounds;
- PRPackedBool mLastContentIsComplete;
- PRPackedBool mIsBlock;
- nsVoidArray* mFloaters; // placeholder frames for below current line floaters
-};
-
-//----------------------------------------------------------------------
-
-/**
- * Transient state used during line reflow.
- */
-
-// State used during line layout that may need to be rewound because
-// of an inconvenient word break.
-struct nsLineLayoutState {
- // The next x coordinate to place the child frame
- nscoord mX;
-
- // This is true if the next frame to reflow should skip over leading
- // whitespace.
- PRBool mSkipLeadingWhiteSpace;
-
- // The column number when pre-formatting (for tab spacing)
- PRInt32 mColumn;
-
- // The child frame being considered for reflow
- nsIFrame* mKidFrame;
-
- // The previous child frame just reflowed
- nsIFrame* mPrevKidFrame;
-
- // The child frame's content index-in-parent
- PRInt32 mKidIndex;
-
- // The child frame number within this line
- PRInt32 mKidFrameNum;
-
- // Current line values values
- nsSize mMaxElementSize;
- nscoord mMaxAscent;
- nscoord mMaxDescent;
-};
-
-struct nsLineLayout {
- nsLineLayout(nsBlockReflowState& aState);
- ~nsLineLayout();
-
- nsresult Initialize(nsBlockReflowState& aState, nsLineData* aLine);
-
- void SetReflowSpace(nsRect& aAvailableSpaceRect);
-
- nsresult ReflowLine();
-
- nsresult IncrementalReflowFromChild(nsIReflowCommand* aReflowCommand,
- nsIFrame* aChildFrame);
-
- void AtSpace();
-
- void AtWordStart(nsIFrame* aFrame, nscoord aX);
-
- PRBool SkipLeadingWhiteSpace() {
- return mState.mSkipLeadingWhiteSpace;
- }
-
- void SetSkipLeadingWhiteSpace(PRBool aSkip) {
- mState.mSkipLeadingWhiteSpace = aSkip;
- }
-
- PRIntn GetColumn() {
- return mState.mColumn;
- }
-
- void SetColumn(PRIntn aNewColumn) {
- mState.mColumn = aNewColumn;
- }
-
- // A value set by line-layout cognizant frames. Frames that are not
- // aware of line layout leave the value unchanged and can thus be
- // detected by the line-layout algorithm.
- PRInt32 mReflowResult;
-
- // The presentation context
- nsIPresContext* mPresContext;
-
- // The block behind the line
- nsBlockFrame* mBlock;
- nsBlockReflowState& mBlockReflowState;
- nsISpaceManager* mSpaceManager;
- nsIContent* mBlockContent;
- PRBool mNoWrap;
-
- // The line we are reflowing
- nsLineData* mLine;
- nsIFrame* mKidPrevInFlow;
-
- // Whenever the line layout creates a frame this slot is incremented
- PRIntn mNewFrames;
- PRIntn mFramesReflowed;
- PRIntn mOldChildCount;
-
- nsLineLayoutState mState;
- nsLineLayoutState mSavedState;
-
- // The current breakable point in the line. If a line-break is
- // requested then this is where the line will break at.
- nsIFrame* mBreakFrame;
- nscoord mBreakX;
- PRUint8 mPendingBreak;
-
- // XXX ick
- // This is set by the block code when it updates the available
- // reflow area when a floater is placed.
- PRBool mReflowDataChanged;
- PRPackedBool mMustReflowMappedChildren;
-
- PRPackedBool mUnconstrainedWidth;
- PRPackedBool mUnconstrainedHeight;
- PRPackedBool mMarginApplied;
-
- nscoord mY;
- nscoord mLineHeight;
- nscoord mMaxWidth;
- nscoord mMaxHeight;
- nsSize* mMaxElementSizePointer;
- nscoord mLeftEdge;
- nscoord mRightEdge;
-
- nscoord* mAscents;
- nscoord mAscentBuf[20];
- nscoord mMaxAscents;
-
-protected:
- nsresult SetAscent(nscoord aAscent);
-
- nsresult ReflowMappedChild();
-
- nsresult ReflowChild(nsIReflowCommand* aReflowCommand, PRBool aNewChild);
-
- nsresult PlaceChild(nsRect& kidRect,
- const nsReflowMetrics& kidMetrics,
- const nsSize* kidMaxElementSize,
- const nsMargin& kidMargin,
- nsReflowStatus kidReflowStatus);
-
- nsresult ReflowMapped();
-
- nsresult SplitLine(PRInt32 aChildReflowStatus);
-
- nsresult PushChildren();
-
- nsresult CreateNextInFlow(nsIFrame* aFrame);
-
- nsresult PullUpChildren();
-
- nsresult CreateFrameFor(nsIContent* aKid);
-
- nsresult ReflowUnmapped();
-
- void AlignChildren();
-
- PRBool CanBreak();
-};
-
-// Value's for nsLineLayout.mReflowResult
-#define NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE 0
-#define NS_LINE_LAYOUT_REFLOW_RESULT_AWARE 1
-#define NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER 2
-
-// Return value's from nsLineLayout reflow methods
-#define NS_LINE_LAYOUT_COMPLETE 0
-#define NS_LINE_LAYOUT_NOT_COMPLETE 1
-#define NS_LINE_LAYOUT_BREAK_BEFORE 2
-#define NS_LINE_LAYOUT_BREAK_AFTER 3
-
-#endif /* nsLineLayout_h___ */
diff --git a/mozilla/layout/html/base/src/nsPlaceholderFrame.cpp b/mozilla/layout/html/base/src/nsPlaceholderFrame.cpp
index 5ce07ccbb92..d9c74c4c9ea 100644
--- a/mozilla/layout/html/base/src/nsPlaceholderFrame.cpp
+++ b/mozilla/layout/html/base/src/nsPlaceholderFrame.cpp
@@ -23,8 +23,7 @@
#include "nsIStyleContext.h"
#include "nsCSSLayout.h"
#include "nsIView.h"
-
-static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
+#include "nsHTMLIIDs.h"
nsresult
nsPlaceholderFrame::NewFrame(nsIFrame** aInstancePtrResult,
@@ -112,7 +111,7 @@ nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext,
}
// Notify our containing block that there's a new floater
- container->AddFloater(aPresContext, mAnchoredItem, this);
+ container->AddFloater(aPresContext, aReflowState, mAnchoredItem, this);
} else {
// XXX This causes anchored-items sizes to get fixed up; this is
@@ -125,7 +124,8 @@ nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext,
mAnchoredItem->WillReflow(*aPresContext);
mAnchoredItem->Reflow(aPresContext, desiredSize, reflowState, aStatus);
mAnchoredItem->SizeTo(desiredSize.width, desiredSize.height);
- container->PlaceFloater(aPresContext, mAnchoredItem, this);
+
+//XXXdeprecated container->PlaceFloater(aPresContext, mAnchoredItem, this);
mAnchoredItem->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
}
diff --git a/mozilla/layout/html/base/src/nsRootPart.cpp b/mozilla/layout/html/base/src/nsRootPart.cpp
index f10a338a329..a45ab36b6f1 100644
--- a/mozilla/layout/html/base/src/nsRootPart.cpp
+++ b/mozilla/layout/html/base/src/nsRootPart.cpp
@@ -282,7 +282,7 @@ void RootContentFrame::CreateFirstChild(nsIPresContext* aPresContext)
}
// XXX Hack
-#define PAGE_SPACING 100
+#define PAGE_SPACING_TWIPS 100
NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
@@ -342,35 +342,45 @@ NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext,
// Resize our frames
if (nsnull != mFirstChild) {
if (aPresContext->IsPaginated()) {
- nscoord y = PAGE_SPACING;
+ nscoord y = PAGE_SPACING_TWIPS;
nsReflowMetrics kidSize(aDesiredSize.maxElementSize);
+
+ // Compute the size of each page and the x coordinate within
+ // ourselves that the pages will be placed at.
nsSize pageSize(aPresContext->GetPageWidth(),
aPresContext->GetPageHeight());
+ nsIDeviceContext *dx = aPresContext->GetDeviceContext();
+ PRInt32 extra = aReflowState.maxSize.width - PAGE_SPACING_TWIPS*2 -
+ pageSize.width - NS_TO_INT_ROUND(dx->GetScrollBarWidth());
+ NS_RELEASE(dx);
+
+ // Note: nscoord is an unsigned type so don't combine these
+ // two statements or the extra will be promoted to unsigned
+ // and the >0 won't work!
+ nscoord x = PAGE_SPACING_TWIPS;
+ if (extra > 0) {
+ x += extra / 2;
+ }
// Tile the pages vertically
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
// Reflow the page
- nsReflowState kidReflowState(kidFrame, aReflowState, pageSize, reflowReason);
+ nsReflowState kidReflowState(kidFrame, aReflowState, pageSize,
+ reflowReason);
nsReflowStatus status;
- // Place and size the page. If the page is narrower than our max width then
- // center it horizontally
- nsIDeviceContext *dx = aPresContext->GetDeviceContext();
- PRInt32 extra = aReflowState.maxSize.width - kidSize.width -
- NS_TO_INT_ROUND(dx->GetScrollBarWidth());
- NS_RELEASE(dx);
- nscoord x = extra > 0 ? extra / 2 : 0;
-
+ // Place and size the page. If the page is narrower than our
+ // max width then center it horizontally
kidFrame->WillReflow(*aPresContext);
kidFrame->MoveTo(x, y);
- status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState);
-
+ status = ReflowChild(kidFrame, aPresContext, kidSize,
+ kidReflowState);
kidFrame->SetRect(nsRect(x, y, kidSize.width, kidSize.height));
kidFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
y += kidSize.height;
// Leave a slight gap between the pages
- y += PAGE_SPACING;
+ y += PAGE_SPACING_TWIPS;
// Is the page complete?
nsIFrame* kidNextInFlow;
@@ -404,8 +414,14 @@ NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext,
}
// Return our desired size
- aDesiredSize.width = aReflowState.maxSize.width;
aDesiredSize.height = y;
+ if (aDesiredSize.height < aReflowState.maxSize.height) {
+ aDesiredSize.height = aReflowState.maxSize.height;
+ }
+ aDesiredSize.width = PAGE_SPACING_TWIPS*2 + pageSize.width;
+ if (aDesiredSize.width < aReflowState.maxSize.width) {
+ aDesiredSize.width = aReflowState.maxSize.width;
+ }
} else {
// Allow the frame to be as wide as our max width, and as high
diff --git a/mozilla/layout/html/base/src/nsScrollFrame.cpp b/mozilla/layout/html/base/src/nsScrollFrame.cpp
index fd0f4ec4047..9d673b1d351 100644
--- a/mozilla/layout/html/base/src/nsScrollFrame.cpp
+++ b/mozilla/layout/html/base/src/nsScrollFrame.cpp
@@ -100,7 +100,8 @@ nsScrollBodyFrame::Reflow(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- NS_FRAME_TRACE_MSG(("enter nsScrollBodyFrame::Reflow: maxSize=%d,%d",
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("enter nsScrollBodyFrame::Reflow: maxSize=%d,%d",
aReflowState.maxSize.width,
aReflowState.maxSize.height));
@@ -259,9 +260,9 @@ nsScrollBodyFrame::Reflow(nsIPresContext* aPresContext,
PostReflowCheck(aStatus);
#endif
- NS_FRAME_TRACE_MSG(
- ("exit nsScrollBodyFrame::Reflow: status=%d width=%d height=%d",
- aStatus, aDesiredSize.width, aDesiredSize.height));
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("exit nsScrollBodyFrame::Reflow: status=%d width=%d height=%d",
+ aStatus, aDesiredSize.width, aDesiredSize.height));
return NS_OK;
}
@@ -324,7 +325,8 @@ nsScrollInnerFrame::Reflow(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- NS_FRAME_TRACE_MSG(("enter nsScrollInnerFrame::Reflow: maxSize=%d,%d",
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("enter nsScrollInnerFrame::Reflow: maxSize=%d,%d",
aReflowState.maxSize.width,
aReflowState.maxSize.height));
@@ -406,7 +408,7 @@ nsScrollInnerFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.height = aReflowState.maxSize.height;
}
- NS_FRAME_TRACE_MSG(
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
("exit nsScrollInnerFrame::Reflow: status=%d width=%d height=%d",
aStatus, aDesiredSize.width, aDesiredSize.height));
return NS_OK;
@@ -457,7 +459,8 @@ nsScrollOuterFrame::Reflow(nsIPresContext* aPresContext,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- NS_FRAME_TRACE_MSG(("enter nsScrollOuterFrame::Reflow: maxSize=%d,%d",
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
+ ("enter nsScrollOuterFrame::Reflow: maxSize=%d,%d",
aReflowState.maxSize.width,
aReflowState.maxSize.height));
@@ -521,7 +524,7 @@ nsScrollOuterFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
- NS_FRAME_TRACE_MSG(
+ NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
("exit nsScrollOuterFrame::Reflow: status=%d width=%d height=%d",
aStatus, aDesiredSize.width, aDesiredSize.height));
return NS_OK;
diff --git a/mozilla/layout/html/base/src/nsSpacerPart.cpp b/mozilla/layout/html/base/src/nsSpacerPart.cpp
index 4db1cdb8696..8d72c483a08 100644
--- a/mozilla/layout/html/base/src/nsSpacerPart.cpp
+++ b/mozilla/layout/html/base/src/nsSpacerPart.cpp
@@ -17,7 +17,9 @@
*/
#include "nsHTMLParts.h"
#include "nsHTMLTagContent.h"
-#include "nsBlockFrame.h"
+#include "nsFrame.h"
+#include "nsIInlineReflow.h"
+#include "nsCSSLineLayout.h"
#include "nsHTMLIIDs.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
@@ -31,15 +33,19 @@
#define TYPE_LINE 1 // line-break + vertical space
#define TYPE_IMAGE 2 // acts like a sized image with nothing to see
-class SpacerFrame : public nsFrame
-{
+class SpacerFrame : public nsFrame, nsIInlineReflow {
public:
SpacerFrame(nsIContent* aContent, nsIFrame* aParentFrame);
- NS_IMETHOD Reflow(nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
+ // nsISupports
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
+ // nsIInlineReflow
+ NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout);
+ NS_IMETHOD InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aDesiredSize,
+ const nsReflowState& aReflowState);
+
protected:
virtual ~SpacerFrame();
};
@@ -76,34 +82,36 @@ SpacerFrame::~SpacerFrame()
{
}
-NS_METHOD SpacerFrame::Reflow(nsIPresContext* aPresContext,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
+NS_IMETHODIMP
+SpacerFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
{
- // Get cached state for containing block frame
- nsLineLayout* lineLayoutState = nsnull;
- nsBlockReflowState* state =
- nsBlockFrame::FindBlockReflowState(aPresContext, this);
- if (nsnull != state) {
- lineLayoutState = state->mCurrentLine;
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
}
-
- // By default, we have no area
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- aDesiredSize.ascent = 0;
- aDesiredSize.descent = 0;
-
- if (nsnull == state) {
- // We don't do anything unless we are in a block container somewhere
- aStatus = NS_FRAME_COMPLETE;
+ if (aIID.Equals(kIInlineReflowIID)) {
+ *aInstancePtrResult = (void*) ((nsIInlineReflow*)this);
return NS_OK;
}
+ return nsFrame::QueryInterface(aIID, aInstancePtrResult);
+}
+
+NS_IMETHODIMP
+SpacerFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState)
+{
+ nsresult rv = NS_INLINE_REFLOW_COMPLETE;
+
+ // By default, we have no area
+ aMetrics.width = 0;
+ aMetrics.height = 0;
+ aMetrics.ascent = 0;
+ aMetrics.descent = 0;
nscoord width = 0;
nscoord height = 0;
- SpacerPart* part = (SpacerPart*) mContent;
+ SpacerPart* part = (SpacerPart*) mContent;/* XXX decouple */
PRUint8 type = part->GetType();
nsContentAttr ca;
if (type != TYPE_IMAGE) {
@@ -128,34 +136,41 @@ NS_METHOD SpacerFrame::Reflow(nsIPresContext* aPresContext,
}
}
- float p2t = aPresContext->GetPixelsToTwips();
+ float p2t = aLineLayout.mPresContext->GetPixelsToTwips();
switch (type) {
case TYPE_WORD:
if (0 != width) {
- aDesiredSize.width = nscoord(width * p2t);
+ aMetrics.width = nscoord(width * p2t);
}
break;
case TYPE_LINE:
if (0 != width) {
- if (nsnull != lineLayoutState) {
- lineLayoutState->mReflowResult =
- NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER;
- lineLayoutState->mPendingBreak = NS_STYLE_CLEAR_LINE;
- }
- aDesiredSize.height = nscoord(width * p2t);
- aDesiredSize.ascent = aDesiredSize.height;
+ rv = NS_INLINE_REFLOW_LINE_BREAK_AFTER;
+ aMetrics.height = nscoord(width * p2t);
+ aMetrics.ascent = aMetrics.height;
}
break;
case TYPE_IMAGE:
- aDesiredSize.width = nscoord(width * p2t);
- aDesiredSize.height = nscoord(height * p2t);
- aDesiredSize.ascent = aDesiredSize.height;
+ aMetrics.width = nscoord(width * p2t);
+ aMetrics.height = nscoord(height * p2t);
+ aMetrics.ascent = aMetrics.height;
break;
}
- aStatus = NS_FRAME_COMPLETE;
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = aMetrics.width;
+ aMetrics.maxElementSize->height = aMetrics.height;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+SpacerFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
+{
+ aLineLayout.EndTextRun();
return NS_OK;
}
diff --git a/mozilla/layout/html/base/src/nsTextContent.cpp b/mozilla/layout/html/base/src/nsTextContent.cpp
index d3f5d2c0ca0..02eae2b6312 100644
--- a/mozilla/layout/html/base/src/nsTextContent.cpp
+++ b/mozilla/layout/html/base/src/nsTextContent.cpp
@@ -18,6 +18,8 @@
#include "nsHTMLParts.h"
#include "nsCRT.h"
#include "nsSplittableFrame.h"
+#include "nsIInlineReflow.h"
+#include "nsCSSLineLayout.h"
#include "nsHTMLContent.h"
#include "nsString.h"
#include "nsIPresContext.h"
@@ -32,7 +34,6 @@
#include "nsIViewManager.h"
#include "nsITimerCallback.h"
#include "nsITimer.h"
-#include "nsBlockFrame.h"
#include "prtime.h"
#include "nsVoidArray.h"
#include "prprf.h"
@@ -57,7 +58,7 @@ PRBool IsInRange(nsIContent * aStart, nsIContent * aEnd, nsIContent * aContent);
#endif
// XXX TODO:
-// 0. tune justified text
+// 0. re-implement justified text
// 1. add in a rendering method that can render justified text
// 2. text renderer should negotiate with rendering context/font
// metrics to see what it can handle; for example, if the renderer can
@@ -65,6 +66,9 @@ PRBool IsInRange(nsIContent * aStart, nsIContent * aEnd, nsIContent * aContent);
// etc, then the text renderer should let the rc do the work;
// otherwise there should be XP fallback code here.
+// XXX TODO:
+// implement nsIFrame::Reflow
+
// XXX Speedup ideas
// 1. justified text can use word width information during resize reflows
// 2. when we are doing an unconstrained reflow we know we are going to
@@ -113,37 +117,35 @@ public:
nsVoidArray mFrames;
};
-class TextFrame : public nsSplittableFrame {
+class TextFrame : public nsSplittableFrame, nsIInlineReflow {
public:
TextFrame(nsIContent* aContent, nsIFrame* aParentFrame);
+ // nsISupports
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
+ // nsIFrame
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
-
- NS_IMETHOD Reflow(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus);
-
- NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
- nsReflowMetrics& aMetrics);
-
- NS_IMETHOD JustifyReflow(nsIPresContext* aCX,
- nscoord aAvailableSpace);
-
NS_IMETHOD GetCursorAt(nsIPresContext& aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame,
PRInt32& aCursor);
-
NS_IMETHOD ContentChanged(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aChild,
nsISupports* aSubContent);
-
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
+ NS_IMETHOD ListTag(FILE* out) const;
+ // nsIInlineReflow
+ NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout);
+ NS_IMETHOD InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState);
+
+ // TextFrame methods
PRInt32 GetPosition(nsIPresContext& aCX,
nsGUIEvent* aEvent,
nsIFrame * aNewFrame);
@@ -172,26 +174,18 @@ protected:
const nsRect& aDirtyRect,
nscoord dx, nscoord dy);
- void PaintJustifiedText(nsIRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nscoord dx, nscoord dy);
+ nsInlineReflowStatus ReflowPre(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState,
+ const nsStyleFont& aFont,
+ PRInt32 aStartingOffset);
- nsReflowStatus ReflowPre(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsSize& aMaxSize,
- nsSize* aMaxElementSize,
- const nsStyleFont& aFont,
- PRInt32 aStartingOffset,
- nsLineLayout* aLineState);
-
- nsReflowStatus ReflowNormal(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsSize& aMaxSize,
- nsSize* aMaxElementSize,
- const nsStyleFont& aFont,
- const nsStyleText& aTextStyle,
- PRInt32 aStartingOffset,
- nsLineLayout* aLineState);
+ nsInlineReflowStatus ReflowNormal(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState,
+ const nsStyleFont& aFontStyle,
+ const nsStyleText& aTextStyle,
+ PRInt32 aStartingOffset);
public:
PRInt32 mContentOffset;
@@ -200,13 +194,6 @@ public:
// XXX need a better packing
PRUint32 mFlags;
PRUint32 mColumn;
-
- // When this text frame is justified, this pointer is not null
- // and points to data about each word/space in the text
- PRUint32* mWords;
-#ifdef DEBUG_JUSTIFY
- PRInt32 mNumWords;
-#endif
};
// Flag information used by rendering code. This information is
@@ -221,6 +208,7 @@ public:
#define TEXT_GET_TAB_COUNT(_mf) ((_mf) >> 5)
#define TEXT_SET_TAB_COUNT(_mf,_tabs) (_mf) = (_mf) | ((_tabs)<< 5)
+#if XXX
// mWords bit definitions
#define WORD_IS_WORD 0x80000000L
#define WORD_IS_SPACE 0x00000000L
@@ -235,6 +223,7 @@ public:
((PRIntn) (((_wi) & WORD_LENGTH_MASK)/* >> WORD_LENGTH_SHIFT*/))
#define GET_WORD_WIDTH(_wi) \
((nscoord) ((PRUint32(_wi) & WORD_WIDTH_MASK) >> WORD_WIDTH_SHIFT))
+#endif
class Text : public nsHTMLContent, public nsIDOMText {
public:
@@ -411,9 +400,20 @@ TextFrame::~TextFrame()
// Release text timer when the last text frame is gone
gTextBlinker = nsnull;
}
- if (nsnull != mWords) {
- delete[] mWords;
+}
+
+NS_IMETHODIMP
+TextFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
+{
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
+ if (nsnull == aInstancePtrResult) {
+ return NS_ERROR_NULL_POINTER;
}
+ if (aIID.Equals(kIInlineReflowIID)) {
+ *aInstancePtrResult = (void*) ((nsIInlineReflow*)this);
+ return NS_OK;
+ }
+ return nsFrame::QueryInterface(aIID, aInstancePtrResult);
}
NS_METHOD TextFrame::GetCursorAt(nsIPresContext& aPresContext,
@@ -467,32 +467,25 @@ NS_METHOD TextFrame::Paint(nsIPresContext& aPresContext,
// Set font and color
aRenderingContext.SetColor(color->mColor);
aRenderingContext.SetFont(font->mFont);
-
- if (nsnull != mWords) {
- PaintJustifiedText(aRenderingContext, aDirtyRect, 0, 0);
- if (font->mThreeD) {
- nscoord onePixel = nscoord(1.0f * aPresContext.GetPixelsToTwips());
- aRenderingContext.SetColor(color->mBackgroundColor);
- PaintJustifiedText(aRenderingContext, aDirtyRect, onePixel, onePixel);
- }
- return NS_OK;
- }
PaintRegularText(aPresContext, aRenderingContext, aDirtyRect, 0, 0);
- //nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect);
+
+#if XXX
if (font->mThreeD) {
nscoord onePixel = nscoord(1.0f * aPresContext.GetPixelsToTwips());
aRenderingContext.SetColor(color->mBackgroundColor);
PaintRegularText(aPresContext, aRenderingContext, aDirtyRect, onePixel, onePixel);
}
+#endif
}
return NS_OK;
}
-void TextFrame::PaintRegularText(nsIPresContext& aPresContext,
- nsIRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nscoord dx, nscoord dy)
+void
+TextFrame::PaintRegularText(nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nscoord dx, nscoord dy)
{
// Skip leading space if necessary
Text* txt = (Text*) mContent;
@@ -660,124 +653,24 @@ void TextFrame::PaintRegularText(nsIPresContext& aPresContext,
}
}
-void TextFrame::PaintJustifiedText(nsIRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nscoord dx, nscoord dy)
+NS_IMETHODIMP
+TextFrame::FindTextRuns(nsCSSLineLayout& aLineLayout)
{
- Text* txt = (Text*) mContent;
- const PRUnichar* cp = txt->mText + mContentOffset;
- const PRUnichar* end = cp + mContentLength;
-
- // Get a word buffer that's big enough to hold all of the text in
- // case all of the text happens to be a word (not possible given how
- // the justification workds, but it's the fastest check that gets us
- // a big enough buffer). We only do this if we aren't going to use
- // multibyte rendering.
- char buf[100];
- char* s0 = buf;
- if ((mFlags & TEXT_HAS_MULTIBYTE) == 0) {
- PRInt32 maxLen = end - cp;
- if (maxLen > sizeof(buf)) {
- s0 = new char[maxLen];
- }
+ if (nsnull == mPrevInFlow) {
+ aLineLayout.AddText(this);
}
-
- // XXX justified text doesn't render underlines (etc) over spaces
- // while regular text does...fix this?
- PRUint32* wp = mWords;
- PRInt32 total = mContentLength;
- nscoord x = dx;
-#ifdef DEBUG_JUSTIFY
- PRIntn numWords = mNumWords;
-#endif
- while (total != 0) {
-#ifdef DEBUG_JUSTIFY
- NS_ASSERTION(numWords > 0, "bad word data");
-#endif
- PRUint32 wordInfo = *wp++;
- nscoord wordWidth = GET_WORD_WIDTH(wordInfo);
- PRIntn wordLen = GET_WORD_LENGTH(wordInfo);
- if (wordInfo & WORD_IS_WORD) {
- if (mFlags & TEXT_HAS_MULTIBYTE) {
- aRenderingContext.DrawString(cp, wordLen, x, dy, mRect.width);
- cp += wordLen;
- } else {
- char* s = s0;
- char* es = s + wordLen;
- while (s < es) {
- PRUint8 ch = (PRUint8) *cp++;
- *s++ = ch;
- }
- aRenderingContext.DrawString(s0, s - s0, x, dy, mRect.width);
- }
- } else {
- // skip over space characters in text array
- cp += wordLen;
- }
- x += wordWidth;
- total -= wordLen;
-#ifdef DEBUG_JUSTIFY
- --numWords;
- NS_ASSERTION(total >= 0, "bad word data");
-#endif
- }
-
- if (s0 != buf) {
- delete[] s0;
- }
-}
-
-NS_METHOD TextFrame::GetReflowMetrics(nsIPresContext* aCX,
- nsReflowMetrics& aMetrics)
-{
- // Get cached state for containing block frame
- nsLineLayout* lineLayoutState = nsnull;
- nsBlockReflowState* state = nsBlockFrame::FindBlockReflowState(aCX, this);
- if (nsnull != state) {
- lineLayoutState = state->mCurrentLine;
- if (nsnull != lineLayoutState) {
- lineLayoutState->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_AWARE;
- }
-
- if (0 == (mFlags & TEXT_IS_PRE)) {
- if (mRect.width != 0) {
- lineLayoutState->SetSkipLeadingWhiteSpace(
- (0 != (mFlags & TEXT_ENDS_IN_WHITESPACE)));
- }
- }
- }
-
- aMetrics.width = mRect.width;
- aMetrics.height = mRect.height;
-
- const nsStyleFont* font =
- (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
- nsIFontMetrics* fm = aCX->GetMetricsFor(font->mFont);
- aMetrics.ascent = fm->GetMaxAscent();
- aMetrics.descent = fm->GetMaxDescent();
- NS_RELEASE(fm);
-
return NS_OK;
}
-NS_METHOD TextFrame::Reflow(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsReflowState& aReflowState,
- nsReflowStatus& aStatus)
+NS_IMETHODIMP
+TextFrame::InlineReflow(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState)
{
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("enter TextFrame::Reflow: aMaxSize=%d,%d",
aReflowState.maxSize.width, aReflowState.maxSize.height));
- // Wipe out old justification information since it's going to change
- if (nsnull != mWords) {
- delete[] mWords;
- mWords = nsnull;
- }
-#ifdef DEBUG_JUSTIFY
- mNumWords = 0;
-#endif
-
// Get starting offset into the content
PRInt32 startingOffset = 0;
if (nsnull != mPrevInFlow) {
@@ -785,16 +678,6 @@ NS_METHOD TextFrame::Reflow(nsIPresContext* aCX,
startingOffset = prev->mContentOffset + prev->mContentLength;
}
- // Get cached state for containing block frame
- nsLineLayout* lineLayoutState = nsnull;
- nsBlockReflowState* state = nsBlockFrame::FindBlockReflowState(aCX, this);
- if (nsnull != state) {
- lineLayoutState = state->mCurrentLine;
- if (nsnull != lineLayoutState) {
- lineLayoutState->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_AWARE;
- }
- }
-
const nsStyleFont* font =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
@@ -811,38 +694,34 @@ NS_METHOD TextFrame::Reflow(nsIPresContext* aCX,
const nsStyleText* text =
(const nsStyleText*)mStyleContext->GetStyleData(eStyleStruct_Text);
+ nsInlineReflowStatus rs;
if (NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) {
// Use a specialized routine for pre-formatted text
- aStatus = ReflowPre(aCX, aDesiredSize, aReflowState.maxSize,
- aDesiredSize.maxElementSize, *font, startingOffset,
- lineLayoutState);
+ rs = ReflowPre(aLineLayout, aMetrics, aReflowState,
+ *font, startingOffset);
} else {
// Use normal wrapping routine for non-pre text (this includes
// text that is not wrapping)
- aStatus = ReflowNormal(aCX, aDesiredSize, aReflowState.maxSize,
- aDesiredSize.maxElementSize, *font, *text,
- startingOffset, lineLayoutState);
+ rs = ReflowNormal(aLineLayout, aMetrics, aReflowState,
+ *font, *text, startingOffset);
}
- NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
- ("exit TextFrame::Reflow: %scomplete width=%d",
- (NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not "),
- aDesiredSize.width));
- return NS_OK;
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit TextFrame::Reflow: rv=%x width=%d",
+ rs, aMetrics.width));
+ return rs;
}
// Reflow normal text (stuff that doesn't have to deal with horizontal
// tabs). Normal text reflow may or may not wrap depending on the
// "whiteSpace" style property.
-nsReflowStatus
-TextFrame::ReflowNormal(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsSize& aMaxSize,
- nsSize* aMaxElementSize,
+nsInlineReflowStatus
+TextFrame::ReflowNormal(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState,
const nsStyleFont& aFont,
const nsStyleText& aTextStyle,
- PRInt32 aStartingOffset,
- nsLineLayout* aLineState)
+ PRInt32 aStartingOffset)
{
Text* txt = (Text*) mContent;
const PRUnichar* cp = txt->mText + aStartingOffset;
@@ -850,7 +729,7 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
const PRUnichar* cpStart = cp;
mContentOffset = aStartingOffset;
- nsIFontMetrics* fm = aCX->GetMetricsFor(aFont.mFont);
+ nsIFontMetrics* fm = aLineLayout.mPresContext->GetMetricsFor(aFont.mFont);
PRInt32 spaceWidth = fm->GetWidth(' ');
PRBool wrapping = PR_TRUE;
if (NS_STYLE_WHITESPACE_NORMAL != aTextStyle.mWhiteSpace) {
@@ -859,11 +738,9 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
// Set whitespace skip flag
PRBool skipWhitespace = PR_FALSE;
- if (nsnull != aLineState) {
- if (aLineState->mState.mSkipLeadingWhiteSpace) {
- skipWhitespace = PR_TRUE;
- mFlags |= TEXT_SKIP_LEADING_WS;
- }
+ if (aLineLayout.GetSkipLeadingWhiteSpace()) {
+ skipWhitespace = PR_TRUE;
+ mFlags |= TEXT_SKIP_LEADING_WS;
}
// Try to fit as much of the text as possible. Note that if we are
@@ -876,7 +753,7 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
// XXX XP_IS_SPACE must not return true for the unicode   character
// XXX what about &zwj and it's cousins?
nscoord x = 0;
- nscoord maxWidth = aMaxSize.width;
+ nscoord maxWidth = aReflowState.maxSize.width;
nscoord maxWordWidth = 0;
const PRUnichar* lastWordEnd = cpStart;
const PRUnichar* lastWordStart = cpStart;
@@ -898,7 +775,9 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
break;
}
if (skipWhitespace) {
- aLineState->AtSpace();
+#if XXX_fix_me
+ aLineLayout->AtSpace();
+#endif
skipWhitespace = PR_FALSE;
continue;
}
@@ -936,14 +815,16 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
break;
}
+#if XXX_fix_me
// Update break state in line reflow state
// XXX move this out of the loop!
if (isWhitespace) {
- aLineState->AtSpace();
+ aLineLayout.AtSpace();
}
else {
- aLineState->AtWordStart(this, x);
+ aLineLayout.AtWordStart(this, x);
}
+#endif
// The word fits. Add it to the run of text.
x += width;
@@ -961,15 +842,13 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
mFlags |= TEXT_ENDS_IN_WHITESPACE;
}
- if (nsnull != aLineState) {
- if (0 == x) {
- // Since we collapsed into nothingness (all our whitespace
- // is ignored) leave the aState->mSkipLeadingWhiteSpace
- // flag alone since it doesn't want leading whitespace
- }
- else {
- aLineState->mState.mSkipLeadingWhiteSpace = endsInWhitespace;
- }
+ if (0 == x) {
+ // Since we collapsed into nothingness (all our whitespace
+ // is ignored) leave the aState->mSkipLeadingWhiteSpace
+ // flag alone since it doesn't want leading whitespace
+ }
+ else {
+ aLineLayout.SetSkipLeadingWhiteSpace(endsInWhitespace);
}
// XXX too much code here: some of it isn't needed
@@ -978,68 +857,64 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
if (0 == mContentLength) {
if (cp == end) {
// The entire chunk of text was whitespace that we skipped over.
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- aDesiredSize.ascent = 0;
- aDesiredSize.descent = 0;
+ aMetrics.width = 0;
+ aMetrics.height = 0;
+ aMetrics.ascent = 0;
+ aMetrics.descent = 0;
mContentLength = end - cpStart;
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = 0;
- aMaxElementSize->height = 0;
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = 0;
+ aMetrics.maxElementSize->height = 0;
}
NS_RELEASE(fm);
- return NS_FRAME_COMPLETE;
+ return NS_INLINE_REFLOW_COMPLETE;
}
}
// Set desired size to the computed size
- aDesiredSize.width = x;
- aDesiredSize.height = fm->GetHeight();
- aDesiredSize.ascent = fm->GetMaxAscent();
- aDesiredSize.descent = fm->GetMaxDescent();
+ aMetrics.width = x;
+ aMetrics.height = fm->GetHeight();
+ aMetrics.ascent = fm->GetMaxAscent();
+ aMetrics.descent = fm->GetMaxDescent();
if (!wrapping) {
maxWordWidth = x;
}
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = maxWordWidth;
- aMaxElementSize->height = fm->GetHeight();
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = maxWordWidth;
+ aMetrics.maxElementSize->height = fm->GetHeight();
}
NS_RELEASE(fm);
- return (cp == end) ? NS_FRAME_COMPLETE : NS_FRAME_NOT_COMPLETE;
+ return (cp == end) ? NS_INLINE_REFLOW_COMPLETE : NS_INLINE_REFLOW_NOT_COMPLETE;
}
-nsReflowStatus
-TextFrame::ReflowPre(nsIPresContext* aCX,
- nsReflowMetrics& aDesiredSize,
- const nsSize& aMaxSize,
- nsSize* aMaxElementSize,
+nsInlineReflowStatus
+TextFrame::ReflowPre(nsCSSLineLayout& aLineLayout,
+ nsReflowMetrics& aMetrics,
+ const nsReflowState& aReflowState,
const nsStyleFont& aFont,
- PRInt32 aStartingOffset,
- nsLineLayout* aLineState)
+ PRInt32 aStartingOffset)
{
+ nsInlineReflowStatus rs = NS_INLINE_REFLOW_COMPLETE;
+
Text* txt = (Text*) mContent;
const PRUnichar* cp = txt->mText + aStartingOffset;
const PRUnichar* cpStart = cp;
const PRUnichar* end = cp + txt->mLength - aStartingOffset;
mFlags |= TEXT_IS_PRE;
- nsIFontMetrics* fm = aCX->GetMetricsFor(aFont.mFont);
+ nsIFontMetrics* fm = aLineLayout.mPresContext->GetMetricsFor(aFont.mFont);
const PRInt32* widths = fm->GetWidths();
PRInt32 width = 0;
PRBool hasMultibyte = PR_FALSE;
PRUint16 tabs = 0;
- PRIntn col = 0;
- if (nsnull != aLineState) {
- col = aLineState->GetColumn();
- }
- mColumn = (PRUint16) col;
+ PRUint16 col = aLineLayout.GetColumn();
+ mColumn = col;
nscoord spaceWidth = widths[' '];
+
while (cp < end) {
PRUnichar ch = *cp++;
if (ch == '\n') {
- if (nsnull != aLineState) {
- aLineState->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER;
- }
+ rs = NS_INLINE_REFLOW_LINE_BREAK_AFTER;
break;
}
if (ch == '\t') {
@@ -1063,9 +938,7 @@ TextFrame::ReflowPre(nsIPresContext* aCX,
}
col++;
}
- if (nsnull != aLineState) {
- aLineState->SetColumn(col);
- }
+ aLineLayout.SetColumn(col);
if (hasMultibyte) {
mFlags |= TEXT_HAS_MULTIBYTE;
}
@@ -1073,208 +946,19 @@ TextFrame::ReflowPre(nsIPresContext* aCX,
mContentOffset = aStartingOffset;
mContentLength = cp - cpStart;
- aDesiredSize.width = width;
- aDesiredSize.height = fm->GetHeight();
- aDesiredSize.ascent = fm->GetMaxAscent();
- aDesiredSize.descent = fm->GetMaxDescent();
- if (nsnull != aMaxElementSize) {
- aMaxElementSize->width = aDesiredSize.width;
- aMaxElementSize->height = aDesiredSize.height;
+ aMetrics.width = width;
+ aMetrics.height = fm->GetHeight();
+ aMetrics.ascent = fm->GetMaxAscent();
+ aMetrics.descent = fm->GetMaxDescent();
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = aMetrics.width;
+ aMetrics.maxElementSize->height = aMetrics.height;
}
NS_RELEASE(fm);
- return (cp == end) ? NS_FRAME_COMPLETE : NS_FRAME_NOT_COMPLETE;
+
+ return rs;
}
-#define NUM_WORDS 20
-
-NS_METHOD TextFrame::JustifyReflow(nsIPresContext* aCX, nscoord aAvailableSpace)
-{
- if (mFlags & TEXT_IS_PRE) {
- // no way
- return NS_OK;
- }
-
- const nsStyleFont* font =
- (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
- nsIFontMetrics* fm = aCX->GetMetricsFor(font->mFont);
- PRInt32 spaceWidth = fm->GetWidth(' ');
-
- PRUint32 words[NUM_WORDS];
- PRUint32* wp0 = words;
- PRIntn maxWords = NUM_WORDS;
-
- PRBool skipWhitespace = PRBool((mFlags & TEXT_SKIP_LEADING_WS) != 0);
-
- // Count the number of spaces and words in the text we are going to
- // justify. Also measure each word in the text and skip over leading
- // space and compress down whitespace.
- Text* txt = (Text*) mContent;
- const PRUnichar* cp = txt->mText + mContentOffset;
- const PRUnichar* end = cp + mContentLength;
- PRUint32* wp = wp0;
- PRUint32* wpend = wp0 + maxWords;
- PRIntn spaceCount = 0;
- PRIntn total = 0;
- while (cp < end) {
- if (wp == wpend) {
- // Make space for more words
- PRUint32 numWords = wp - wp0;
- maxWords = maxWords * 2;
- PRUint32* newwp0 = new PRUint32[maxWords];
- if (nsnull == newwp0) {
- goto bail;
- }
- nsCRT::memcpy(newwp0, wp0, sizeof(PRUint32) * numWords);
- if (wp0 != words) {
- delete[] wp0;
- }
- wp0 = newwp0;
- wp = wp0 + numWords;
- wpend = wp0 + maxWords;
- }
-
- PRUint32 wordInfo;
- PRUint32 wordLen;
- nscoord wordWidth;
- const PRUnichar* wordStart = cp;
- PRUnichar ch = *cp++;
- if (XP_IS_SPACE(ch)) {
- // Compress whitespace down to a single whitespace
- while (cp < end) {
- ch = *cp;
- if (XP_IS_SPACE(ch)) {
- cp++;
- continue;
- }
- break;
- }
- // Use wordWidth as a flag for spaces to indicate which spaces
- // we give zero space to and which we don't.
- if (skipWhitespace) {
- wordWidth = 0;
- } else {
- wordWidth = spaceWidth;
- spaceCount++;
- }
- wordInfo = WORD_IS_SPACE;
- wordLen = cp - wordStart;
- } else {
- while (cp < end) {
- ch = *cp;
- if (!XP_IS_SPACE(ch)) {
- cp++;
- continue;
- }
- break;
- }
- wordLen = cp - wordStart;
- wordWidth = fm->GetWidth(wordStart, wordLen);
- skipWhitespace = PR_FALSE;
- wordInfo = WORD_IS_WORD;
- }
- if ((wordWidth > MAX_WORD_WIDTH) || (wordLen > MAX_WORD_LENGTH)) {
- // We can't fit the information about this word into our
- // bitfield. Bail.
- goto bail;
- }
- wordInfo = wordInfo |
- (wordLen << WORD_LENGTH_SHIFT) |
- (wordWidth << WORD_WIDTH_SHIFT);
- *wp++ = wordInfo;
- total += wordLen;
- }
- NS_ASSERTION(total == mContentLength, "bad total");
-
- // Now that we know where all the words and spaces are, and we have
- // measured the words, divy up the aAvailableSpace to each of the
- // spaces.
- if (spaceCount != 0) {
- /*
- * See if the last word is a space. If it is, don't count it as a space
- * and give it's space to the available space.
- */
- PRUint32 wordInfo = wp[-1];
- if ((wordInfo & WORD_IS_WORD) == 0) {
- if (--spaceCount == 0) {
- // Never mind: the one and only space was at the end. Harumph.
- goto bail;
- }
- aAvailableSpace += spaceWidth;
- // Update wordInfo to have a zero width for the trailing space
- wp[-1] = WORD_IS_SPACE | (wordInfo & WORD_LENGTH_MASK);
- }
- nscoord add = aAvailableSpace / spaceCount;
- if (add == 0) {
- add = 1;
- }
- PRIntn numWords = wp - wp0;
- mWords = new PRUint32[numWords];
- if (nsnull == mWords) {
- goto bail;
- }
- wp = wp0;
- PRUint32* tp = mWords;
- PRUint32* tpend = tp + numWords;
- total = 0;
-#ifdef DEBUG_JUSTIFY
- mNumWords = numWords;
-#endif
- while (--numWords >= 0) {
- wordInfo = *wp++;
- if (wordInfo & WORD_IS_WORD) {
- // We already know about the word
- *tp++ = wordInfo;
- total += GET_WORD_LENGTH(wordInfo);
- continue;
- } else {
- nscoord spaceWidth = GET_WORD_WIDTH(wordInfo);
- if (spaceWidth == 0) {
- // This is leading space that doesn't count
- *tp++ = wordInfo;
- total += GET_WORD_LENGTH(wordInfo);
- continue;
- }
- // This is a space that gets some of the available space
- if (add > aAvailableSpace) {
- add = aAvailableSpace;
- }
- spaceWidth += add;
- aAvailableSpace -= add;
- if (aAvailableSpace == 0) {
- // We used it all up already so stop adding
- add = 0;
- }
- if (--spaceCount == 0) {
- // Give the last space the remaining available space
- spaceWidth += aAvailableSpace;
- aAvailableSpace = 0;
- }
- if (spaceWidth > MAX_WORD_WIDTH) {
- // Sad but true; leave it be. Maybe the next word can use it
- *tp++ = wordInfo;
- total += GET_WORD_LENGTH(wordInfo);
- continue;
- }
- wordInfo = (wordInfo & ~WORD_WIDTH_MASK) |
- (spaceWidth << WORD_WIDTH_SHIFT);
- *tp++ = wordInfo;
- total += GET_WORD_LENGTH(wordInfo);
- }
- }
- NS_ASSERTION(aAvailableSpace == 0, "bad divy up");
- NS_ASSERTION(tp == tpend, "bad tp");
- NS_ASSERTION(total == mContentLength, "bad total");
- }
-
-bail:
- if (wp0 != words) {
- delete[] wp0;
- }
- NS_RELEASE(fm);
- return NS_OK;
-}
-#undef NUM_WORDS
-
//--------------------------------------------------------------------------
// CalcActualPosition
// This finds the actual interger offset into the text and the width of the
@@ -1337,16 +1021,10 @@ void TextFrame::CalcCursorPosition(nsIPresContext& aCX,
startingOffset = prev->GetContentOffset() + prev->GetContentLength();
}
- // Get cached state for containing block frame
- nsLineLayout* lineLayoutState = nsnull;
- nsBlockReflowState* state = nsBlockFrame::FindBlockReflowState(&aCX, this);
- if (nsnull != state) {
- lineLayoutState = state->mCurrentLine;
- if (nsnull != lineLayoutState) {
- lineLayoutState->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_AWARE;
- }
- }
-
+//XXX // Get cached state for containing block frame
+// if (nsnull != aLineLayout) {
+// aLineLayout->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_AWARE;
+// }
nsIContent * content;
GetContent(content);
@@ -1375,12 +1053,14 @@ void TextFrame::CalcCursorPosition(nsIPresContext& aCX,
// Set whitespace skip flag
PRBool skipWhitespace = PR_FALSE;
- if (nsnull != lineLayoutState) {
- if (lineLayoutState->SkipLeadingWhiteSpace()) {
+#if XXX_wont_work
+ if (nsnull != aLineLayout) {
+ if (aLineLayout->SkipLeadingWhiteSpace()) {
skipWhitespace = PR_TRUE;
mFlags |= TEXT_SKIP_LEADING_WS;
}
}
+#endif
// Try to fit as much of the text as possible. Note that if we are
// at the left margin then the first word always fits. In addition,
@@ -1563,20 +1243,50 @@ void TextFrame::CalcCursorPosition(nsIPresContext& aCX,
}
+NS_IMETHODIMP
+TextFrame::ListTag(FILE* out) const
+{
+ PRInt32 contentIndex;
+ GetContentIndex(contentIndex);
+ fprintf(out, "Text(%d)@%p", contentIndex, this);
+ return NS_OK;
+}
-NS_METHOD TextFrame::List(FILE* out, PRInt32 aIndent) const
+NS_IMETHODIMP
+TextFrame::List(FILE* out, PRInt32 aIndent) const
{
PRInt32 i;
for (i = aIndent; --i >= 0; ) fputs(" ", out);
- PRInt32 contentIndex;
- GetContentIndex(contentIndex);
- fprintf(out, "Text(%d)@%p[%d,%d] ",
- contentIndex, this,
- mContentOffset, mContentOffset+mContentLength-1);
+
+ // Output the tag
+ ListTag(out);
+ nsIView* view;
+ GetView(view);
+ if (nsnull != view) {
+ fprintf(out, " [view=%p]", view);
+ NS_RELEASE(view);
+ }
+
+ // Output the first/last content offset and prev/next in flow info
+ PRBool isComplete =
+ mContentOffset + mContentLength == ((Text*)mContent)->mLength;
+ fprintf(out, "[%d,%d,%c] ",
+ mContentOffset, mContentOffset+mContentLength-1,
+ isComplete ? 'T':'F');
+ if (nsnull != mPrevInFlow) {
+ fprintf(out, "prev-in-flow=%p ", mPrevInFlow);
+ }
+ if (nsnull != mNextInFlow) {
+ fprintf(out, "next-in-flow=%p ", mNextInFlow);
+ }
+
+ // Output the rect and state
out << mRect;
if (0 != mState) {
fprintf(out, " [state=%08x]", mState);
}
+
+ // Output the text
fputs("<\n", out);
aIndent++;
diff --git a/mozilla/layout/html/document/src/nsHTMLIFrame.cpp b/mozilla/layout/html/document/src/nsHTMLIFrame.cpp
index 8ecfbea1620..cc18d5c37ef 100644
--- a/mozilla/layout/html/document/src/nsHTMLIFrame.cpp
+++ b/mozilla/layout/html/document/src/nsHTMLIFrame.cpp
@@ -383,6 +383,7 @@ nsHTMLIFrame::CreateFrame(nsIPresContext* aPresContext,
return NS_ERROR_OUT_OF_MEMORY;
}
aResult = frame;
+ frame->SetStyleContext(aPresContext, aStyleContext);
return NS_OK;
}
diff --git a/mozilla/layout/html/document/src/ua.css b/mozilla/layout/html/document/src/ua.css
index cd905f816a1..fb0e68956f1 100644
--- a/mozilla/layout/html/document/src/ua.css
+++ b/mozilla/layout/html/document/src/ua.css
@@ -30,7 +30,7 @@ BODY {
line-height: 1.1;
background: rgb(255,255,255);
color: black;
- padding: 12px;
+ padding: 8px;
display: block;
cursor: arrow;
}
diff --git a/mozilla/layout/html/forms/src/Makefile b/mozilla/layout/html/forms/src/Makefile
index bbccf9423ca..4fadc5b1acb 100644
--- a/mozilla/layout/html/forms/src/Makefile
+++ b/mozilla/layout/html/forms/src/Makefile
@@ -38,7 +38,8 @@ CPPSRCS = \
MODULE = raptor
-INCLUDES += -I../../../base/src -I../../base/src -I../../style/src
+INCLUDES += -I../../../base/src -I../../base/src -I../../style/src \
+ -I../../linelayout/src
REQUIRES = xpcom raptor dom netlib js
diff --git a/mozilla/layout/html/forms/src/makefile.win b/mozilla/layout/html/forms/src/makefile.win
index ae95a48f2e9..5ea64799354 100644
--- a/mozilla/layout/html/forms/src/makefile.win
+++ b/mozilla/layout/html/forms/src/makefile.win
@@ -33,10 +33,10 @@ CPP_OBJS=.\$(OBJDIR)\nsForm.obj .\$(OBJDIR)\nsInput.obj \
.\$(OBJDIR)\nsInputRadio.obj \
.\$(OBJDIR)\nsInputText.obj .\$(OBJDIR)\nsSelect.obj
-LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
- -I..\..\base\src -I..\..\style\src \
- -I..\..\..\base\src \
- -I$(PUBLIC)\dom -I$(PUBLIC)\netlib
+LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
+ -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \
+ -I..\..\base\src -I..\..\style\src -I..\..\..\css\layout\src \
+ -I..\..\..\base\src
LCFLAGS = \
$(LCFLAGS) \
diff --git a/mozilla/layout/html/forms/src/nsInputFile.cpp b/mozilla/layout/html/forms/src/nsInputFile.cpp
index 677bb91146d..9504fecadbd 100644
--- a/mozilla/layout/html/forms/src/nsInputFile.cpp
+++ b/mozilla/layout/html/forms/src/nsInputFile.cpp
@@ -21,15 +21,12 @@
#include "nsInputFile.h"
#include "nsIContent.h"
#include "prtypes.h"
-#include "nsIFrame.h"
-#include "nsISupports.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIHTMLContent.h"
#include "nsHTMLIIDs.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLForms.h"
-#include "nsInlineFrame.h"
#include "nsIFileWidget.h"
#include "nsITextWidget.h"
#include "nsWidgetsCID.h"
@@ -40,7 +37,7 @@ PRInt32 nsInputFileFrame::gSpacing = 40;
nsString* nsInputFile::gFILE_TYPE = new nsString("file");
nsInputFileFrame::nsInputFileFrame(nsIContent* aContent, nsIFrame* aParentFrame)
- : nsInlineFrame(aContent, aParentFrame)
+ : nsCSSInlineFrame(aContent, aParentFrame)
{
}
@@ -106,6 +103,11 @@ void nsInputFileFrame::MouseClicked(nsIPresContext* aPresContext)
NS_RELEASE(textWidget);
}
+// XXX this method is 100% wrong; if nsInputFileFrame really is a
+// container then it's children's coordinates will be relative to the
+// container, and when the container is moved the children will
+// (therefore) automatically move with it.
+
NS_IMETHODIMP
nsInputFileFrame::MoveTo(nscoord aX, nscoord aY)
{
@@ -125,6 +127,8 @@ nsInputFileFrame::MoveTo(nscoord aX, nscoord aY)
return NS_OK;
}
+// XXX this shouldn't need to be done either
+
NS_IMETHODIMP
nsInputFileFrame::SizeTo(nscoord aWidth, nscoord aHeight)
{
@@ -141,6 +145,9 @@ nsInputFileFrame::SizeTo(nscoord aWidth, nscoord aHeight)
return NS_OK;
}
+// XXX hey chris: nsInlineFrame doesn't implement this anymore; this
+// needs to be reworked to deal with the new inline frame code
+
NS_IMETHODIMP nsInputFileFrame::Reflow(nsIPresContext* aCX,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
diff --git a/mozilla/layout/html/forms/src/nsInputFile.h b/mozilla/layout/html/forms/src/nsInputFile.h
index 157a8ad5f72..797dddb813b 100644
--- a/mozilla/layout/html/forms/src/nsInputFile.h
+++ b/mozilla/layout/html/forms/src/nsInputFile.h
@@ -20,7 +20,7 @@
#define nsInputFile_h___
#include "nsInput.h"
-#include "nsInlineFrame.h"
+#include "nsCSSInlineFrame.h"
#include "nsInputFrame.h"
class nsIAtom;
@@ -28,7 +28,7 @@ class nsString;
// this class definition will move to nsInputFile.cpp
-class nsInputFileFrame : public nsInlineFrame {
+class nsInputFileFrame : public nsCSSInlineFrame {
public:
nsInputFileFrame(nsIContent* aContent, nsIFrame* aParentFrame);
NS_IMETHOD Reflow(nsIPresContext* aCX,
diff --git a/mozilla/layout/html/style/src/nsCSSLayout.cpp b/mozilla/layout/html/style/src/nsCSSLayout.cpp
index be0fcccdc1a..42755c0a074 100644
--- a/mozilla/layout/html/style/src/nsCSSLayout.cpp
+++ b/mozilla/layout/html/style/src/nsCSSLayout.cpp
@@ -24,7 +24,6 @@
#include "nsIPresContext.h"
#include "nsRect.h"
#include "nsIPtr.h"
-#include "nsBlockFrame.h"
#include "nsHTMLIIDs.h"
NS_DEF_PTR(nsIStyleContext);
@@ -309,6 +308,7 @@ GetStyleDimension(nsIPresContext* aPresContext,
rv = PR_TRUE;
break;
}
+ aResult = 0;
rs = rs->parentReflowState;
}
}
@@ -338,10 +338,12 @@ nsCSSLayout::GetStyleSize(nsIPresContext* aPresContext,
if (NS_OK == result) {
if (GetStyleDimension(aPresContext, aReflowState, pos, pos->mWidth,
aStyleSize.width)) {
+NS_ASSERTION(aStyleSize.width < 100000, "bad % result");
rv |= NS_SIZE_HAS_WIDTH;
}
if (GetStyleDimension(aPresContext, aReflowState, pos, pos->mHeight,
aStyleSize.height)) {
+NS_ASSERTION(aStyleSize.height < 100000, "bad % result");
rv |= NS_SIZE_HAS_HEIGHT;
}
}
diff --git a/mozilla/layout/html/tests/Makefile b/mozilla/layout/html/tests/Makefile
index 5b424d98ae0..44be3e6fee3 100644
--- a/mozilla/layout/html/tests/Makefile
+++ b/mozilla/layout/html/tests/Makefile
@@ -26,8 +26,9 @@ CPPSRCS = \
TestHTMLTagLookup.cpp \
$(NULL)
-INCLUDES+=-I../src -I$(PUBLIC)/xpcom -I$(PUBLIC)/raptor -I$(PUBLIC)/netlib \
- -I$(PUBLIC)\js
+INCLUDES += -I../src \
+ -I$(PUBLIC)/xpcom -I$(PUBLIC)/raptor -I$(PUBLIC)/netlib \
+ -I$(PUBLIC)\js
DIRS =
diff --git a/mozilla/layout/html/tests/TestInlineFrame.cpp b/mozilla/layout/html/tests/TestInlineFrame.cpp
index 087bb0b17fa..68548c481a7 100644
--- a/mozilla/layout/html/tests/TestInlineFrame.cpp
+++ b/mozilla/layout/html/tests/TestInlineFrame.cpp
@@ -28,7 +28,7 @@
#include "nsSplittableFrame.h"
#include "nsIContentDelegate.h"
#include "nsIPresContext.h"
-#include "nsInlineFrame.h"
+#include "nsCSSInlineFrame.h"
#include "nsIAtom.h"
static NS_DEFINE_IID(kIContentDelegateIID, NS_ICONTENTDELEGATE_IID);
@@ -185,7 +185,7 @@ void FixedSizeContent::ToHTML(nsString& out)
///////////////////////////////////////////////////////////////////////////////
//
-class InlineFrame : public nsInlineFrame
+class InlineFrame : public nsCSSInlineFrame
{
public:
InlineFrame(nsIContent* aContent,
@@ -203,7 +203,7 @@ public:
InlineFrame::InlineFrame(nsIContent* aContent,
nsIFrame* aParent)
- : nsInlineFrame(aContent, aParent)
+ : nsCSSInlineFrame(aContent, aParent)
{
}
diff --git a/mozilla/layout/html/tests/makefile.win b/mozilla/layout/html/tests/makefile.win
index 9b6d51a10d2..0fa03b8b215 100644
--- a/mozilla/layout/html/tests/makefile.win
+++ b/mozilla/layout/html/tests/makefile.win
@@ -33,12 +33,20 @@ LCFLAGS = \
$(DEFINES) \
$(NULL)
-LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\dom \
- -I$(PUBLIC)\netlib -I..\base\src -I..\style\src \
- -I..\..\base\src -I$(PUBLIC)\js
+LINCS= \
+ -I$(PUBLIC)\xpcom \
+ -I$(PUBLIC)\raptor \
+ -I$(PUBLIC)\dom \
+ -I$(PUBLIC)\js \
+ -I$(PUBLIC)\netlib \
+ -I..\base\src \
+ -I..\style\src \
+ -I..\..\css\layout\src \
+ -I..\..\base\src
LLIBS= \
$(DIST)\lib\raptorhtmlbase_s.lib \
+ $(DIST)\lib\nglcsslay_s.lib \
$(DIST)\lib\raptorhtmlstyle_s.lib \
$(DIST)\lib\raptorlayout_s.lib \
$(DIST)\lib\raptorgfx.lib \
diff --git a/mozilla/layout/makefile.win b/mozilla/layout/makefile.win
index b5b1b618d1d..a13b208aea8 100644
--- a/mozilla/layout/makefile.win
+++ b/mozilla/layout/makefile.win
@@ -17,6 +17,6 @@
DEPTH=..
-DIRS=base html events build
+DIRS=base css html events build
include <$(DEPTH)\layout\config\rules.mak>
diff --git a/mozilla/layout/style/ua.css b/mozilla/layout/style/ua.css
index cd905f816a1..fb0e68956f1 100644
--- a/mozilla/layout/style/ua.css
+++ b/mozilla/layout/style/ua.css
@@ -30,7 +30,7 @@ BODY {
line-height: 1.1;
background: rgb(255,255,255);
color: black;
- padding: 12px;
+ padding: 8px;
display: block;
cursor: arrow;
}