diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp
index ac46b59140a..017a7055e5b 100644
--- a/mozilla/layout/generic/nsBlockFrame.cpp
+++ b/mozilla/layout/generic/nsBlockFrame.cpp
@@ -23,7 +23,6 @@
#include "nsLineBox.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
@@ -64,7 +63,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -75,7 +73,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -210,7 +207,6 @@ public:
const nsHTMLReflowState& mReflowState;
nsLineLayout* mLineLayout;
- nsInlineReflow* mInlineReflow;
nsISpaceManager* mSpaceManager;
nscoord mSpaceManagerX, mSpaceManagerY;
@@ -219,9 +215,6 @@ public:
nsReflowStatus mReflowStatus;
- nsBlockFrame* mRunInFromFrame;
- nsBlockFrame* mRunInToFrame;
-
nscoord mBottomEdge; // maximum Y
PRBool mUnconstrainedWidth;
@@ -275,12 +268,12 @@ public:
void
nsLineLayout::InitFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->InitFloater(aFrame);
+ mBlockRS->InitFloater(aFrame);
}
void
nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->AddFloater(aFrame, PR_FALSE);
+ mBlockRS->AddFloater(aFrame, PR_FALSE);
}
//----------------------------------------------------------------------
@@ -298,8 +291,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mIsMarginRoot(PR_FALSE),
mCarriedOutTopMargin(0)
{
- mInlineReflow = nsnull;
-
mLineLayout = aLineLayout;
mSpaceManager = aReflowState.spaceManager;
@@ -316,30 +307,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mBlock->GetNextInFlow((nsIFrame**)&mNextInFlow);
mKidXMost = 0;
- mRunInFromFrame = nsnull;
- mRunInToFrame = nsnull;
-
-#if 0
- // Compute "content area"
- mUnconstrainedWidth = aReflowState.computedWidth == NS_UNCONSTRAINEDSIZE;
- mUnconstrainedHeight = aReflowState.computedHeight == NS_UNCONSTRAINEDSIZE;
-#ifdef NS_DEBUG
- if ((!mUnconstrainedWidth && (aReflowState.computedWidth > 200000)) ||
- (!mUnconstrainedHeight && (aReflowState.computedHeight > 200000))) {
- mBlock->ListTag(stdout);
- printf(": bad parent: computed size is %d(0x%x),%d(0x%x)\n",
- aReflowState.computedWidth, aReflowState.computedWidth,
- aReflowState.computedHeight, aReflowState.computedHeight);
- if (aReflowState.computedWidth > 200000) {
- mUnconstrainedWidth = PR_TRUE;
- }
- if (aReflowState.computedHeight > 200000) {
- mUnconstrainedHeight = PR_TRUE;
- }
- }
-#endif
-#endif
-
// Compute content area width (the content area is inside the border
// and padding)
mUnconstrainedWidth = PR_FALSE;
@@ -893,30 +860,14 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- // Replace parent provided reflow state with our own significantly
- // more extensive version.
- nsLineLayout ll(aPresContext, aReflowState.spaceManager);
- nsLineLayout* lineLayout = ≪
+ nsLineLayout lineLayout(aPresContext, aReflowState.spaceManager,
+ &aReflowState, nsnull != aMetrics.maxElementSize);
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
- lineLayout);
+ &lineLayout);
+ lineLayout.Init(&state);
if (NS_BLOCK_MARGIN_ROOT & mFlags) {
state.mIsMarginRoot = PR_TRUE;
}
- lineLayout->Init(&state);
-
- // Prepare inline-reflow engine. Note that we will almost always use
- // the inline reflow engine so this setup is not wasted work:
- // because most content has compressed white-space in it, we will
- // use the inline reflow engine to get rid of it.
- nsInlineReflow inlineReflow(ll, aReflowState, this, PR_TRUE,
- state.mComputeMaxElementSize);
- state.mInlineReflow = &inlineReflow;
- lineLayout->PushInline(&inlineReflow);
-
- // Compute the blocks minimum line-height the first time that its
- // needed (which is now).
- nscoord minLineHeight = nsHTMLReflowState::CalcLineHeight(aPresContext, this);
- inlineReflow.SetMinLineHeight(minLineHeight);
if (eReflowReason_Resize != aReflowState.reason) {
RenumberLists();
@@ -956,7 +907,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
else {
// Get next frame in reflow command chain
aReflowState.reflowCommand->GetNext(state.mNextRCFrame);
- inlineReflow.SetNextRCFrame(state.mNextRCFrame);
// Now do the reflow
rv = PrepareChildIncrementalReflow(state);
@@ -989,7 +939,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
- lineLayout->PopInline();
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
@@ -1044,6 +993,20 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
borderPadding.right;
computedWidth = maxWidth;
}
+ else if (aState.mComputeMaxElementSize) {
+ // See if our max-element-size width is larger than our
+ // computed-width. This happens when we are impacted by a
+ // floater. When this does happen, our desired size needs to
+ // include room for the floater.
+ if (computedWidth < aMetrics.maxElementSize->width) {
+#ifdef DEBUG_kipp
+ ListTag(stdout);
+ printf(": adjusting width from %d to %d\n", computedWidth,
+ aMetrics.maxElementSize->width);
+#endif
+ computedWidth = aMetrics.maxElementSize->width;
+ }
+ }
aMetrics.width = computedWidth;
}
#ifdef DEBUG_kipp
@@ -1093,6 +1056,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
(0 == aState.mY - borderPadding.top))) {
aMetrics.width = 0;
aMetrics.height = 0;
+ aMetrics.mCarriedOutTopMargin = 0;
+ aMetrics.mCarriedOutBottomMargin = 0;
emptyFrame = PR_TRUE;
}
@@ -1218,17 +1183,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsresult
nsBlockFrame::PrepareInitialReflow(nsBlockReflowState& aState)
{
- if ((nsnull == mPrevInFlow) && (nsnull != aState.mReflowState.mRunInFrame)) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": run-in from: ");
- aState.mReflowState.mRunInFrame->ListTag(stdout);
- printf("\n");
-#endif
- // Take frames away from the run-in frame
- TakeRunInFrames(aState.mReflowState.mRunInFrame);
- }
-
PrepareResizeReflow(aState);
return NS_OK;
}
@@ -1598,7 +1552,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
// Pull data from a next-in-flow if we can
@@ -1663,7 +1617,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
}
@@ -1719,8 +1673,8 @@ nsBlockFrame::WillReflowLine(nsBlockReflowState& aState,
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- PRBool* aKeepReflowGoing)
+ nsLineBox* aLine,
+ PRBool* aKeepReflowGoing)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBlockFrame::ReflowLine: line=%p", aLine));
@@ -1748,7 +1702,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
}
// Setup the line-layout for the new line
- aState.mLineLayout->Reset();
aState.mCurrentLine = aLine;
aLine->ClearDirty();
aLine->SetNeedDidReflow();
@@ -1758,37 +1711,22 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
// When reflowing a block frame we always get the available space
aState.GetAvailableSpace();
-#if XXX_dead_code
- if ((nsnull != aState.lineLayout) &&
- (0 != aState.lineLayout->GetPlacedFrames())) {
- // Blocks are not allowed on the same line as anything else
- aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
- *aKeepReflowGoing = PR_FALSE;
- }
- else
-#endif
- {
- // Notify observers that we are about to reflow the line
- WillReflowLine(aState, aLine);
+ // Notify observers that we are about to reflow the line
+ WillReflowLine(aState, aLine);
- rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
+ if (NS_FAILED(rv)) {
+ return rv;
}
}
else {
- // When this class is an inline frame and we are reflowing inline
- // frames then there is no point in getting available space.
- nscoord x, availWidth, availHeight;
- aState.GetAvailableSpace();
-
// Setup initial coordinate system for reflowing the inline frames
// into.
+ aState.GetAvailableSpace();
const nsMargin& borderPadding = aState.BorderPadding();
- x = aState.mAvailSpaceRect.x + borderPadding.left;
- availWidth = aState.mAvailSpaceRect.width;
-
+ nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
+ nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord availHeight;
if (aState.mUnconstrainedHeight) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
@@ -1796,7 +1734,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
/* XXX get the height right! */
availHeight = aState.mAvailSpaceRect.height;
}
- aState.mInlineReflow->Init(x, aState.mY, availWidth, availHeight);
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ lineLayout->BeginLineReflow(x, aState.mY, availWidth, availHeight,
+ PR_FALSE /*XXX isTopOfPage*/);
// Notify observers that we are about to reflow the line
WillReflowLine(aState, aLine);
@@ -1863,6 +1803,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
rv = PlaceLine(aState, aLine, aKeepReflowGoing);
}
+ else {
+ lineLayout->EndLineReflow();
+ }
}
return rv;
@@ -2192,14 +2135,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": frame: ");
- nsFrame::ListTag(stdout, aFrame);
- printf(" followed by: ");
- nsFrame::ListTag(stdout, nextFrame);
- printf("\n");
-#endif
followingBlockFrame = (nsBlockFrame*) nextFrame;
break;
}
@@ -2217,30 +2152,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
return followingBlockFrame;
}
-#if XXX
-void
-nsBlockFrame::WillReflowFrame(nsBlockReflowState& aState,
- nsLineBox* aLine,
- nsIFrame* aFrame)
-{
- nsIStyleContext* kidSC;
- aFrame->GetStyleContext(kidSC);
- if (nsnull != kidSC) {
- nsIStyleContext* kidParentSC;
- kidParentSC = kidSC->GetParent();
- if (nsnull != kidParentSC) {
- if (kidParentSC != mStyleContext) {
- // The frame has changed situations so re-resolve its style
- // context in the new situation.
- aFrame->ReResolveStyleContext(&aState.mPresContext, mStyleContext);
- }
- NS_RELEASE(kidParentSC);
- }
- NS_RELEASE(kidSC);
- }
-}
-#endif
-
// XXX This should be a no-op when there is no first-line/letter style
// in force!
void
@@ -2305,15 +2216,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing)
{
NS_PRECONDITION(*aKeepReflowGoing, "bad caller");
- NS_PRECONDITION(0 == aState.mLineLayout->GetPlacedFrames(),
- "non-empty line with a block");
nsresult rv = NS_OK;
nsIFrame* frame = aLine->mFirstChild;
// Prepare the inline reflow engine
-//XXX nsBlockFrame* runInToFrame;
nsBlockFrame* compactWithFrame;
nscoord compactMarginWidth = 0;
PRBool isCompactFrame = PR_FALSE;
@@ -2321,38 +2229,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
switch (display->mDisplay) {
-#if XXX_runin
- case NS_STYLE_DISPLAY_RUN_IN:
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": trying to see if ");
- aFrame->ListTag(stdout);
- printf(" is a run-in candidate\n");
-#endif
- runInToFrame = FindFollowingBlockFrame(frame);
- if (nsnull != runInToFrame) {
-// XXX run-in frame should be pushed to the next-in-flow too if the
-// run-in-to frame is pushed.
- nsRect r(0, aState.mY, 0, 0);
- aLine->mBounds = r;
- aLine->mCombinedArea = r;
- aLine->mCarriedOutTopMargin = 0;
- aLine->mCarriedOutBottomMargin = 0;
- aLine->SetMarginFlags(0);
-#if XXX_need_line_outside_children
- aLine->ClearOutsideChildren();
-#endif
- aLine->mBreakType = NS_STYLE_CLEAR_NONE;
-//XXX aFrame->WillReflow(aState.mPresContext);
- frame->SetRect(r);
- aState.mPrevChild = frame;
- aState.mRunInToFrame = runInToFrame;
- aState.mRunInFrame = (nsBlockFrame*) frame;
- return rv;
- }
- break;
-#endif
-
case NS_STYLE_DISPLAY_COMPACT:
compactWithFrame = FindFollowingBlockFrame(frame);
if (nsnull != compactWithFrame) {
@@ -2392,15 +2268,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
}
-#if XXX_runin
- // Set run-in frame if this is the run-in-to frame. That way the
- // target block frame knows to pick up the children from the run-in
- // frame.
- if (frame == aState.mRunInToFrame) {
- brc.SetRunInFrame(aState.mRunInFrame);
- }
-#endif
-
// Compute the available space for the block
nscoord availHeight = aState.mUnconstrainedHeight
? NS_UNCONSTRAINEDSIZE
@@ -2655,9 +2522,10 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
// Reflow the inline frame
+ nsLineLayout* lineLayout = aState.mLineLayout;
nsReflowStatus frameReflowStatus;
- nsresult rv = aState.mInlineReflow->ReflowFrame(aFrame, aState.IsAdjacentWithTop(),
- frameReflowStatus);
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &aState.mNextRCFrame,
+ frameReflowStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2822,8 +2690,8 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
{
- PRInt32 pushCount = aLine->ChildCount() -
- aState.mInlineReflow->GetCurrentFrameNum();
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ PRInt32 pushCount = aLine->ChildCount() - lineLayout->GetCurrentSpanCount();
//printf("BEFORE (pushCount=%d):\n", pushCount);
//aLine->List(stdout, 0);
if (0 != pushCount) {
@@ -2858,10 +2726,10 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
to->SetIsBlock(aLine->IsBlock());
aLine->mChildCount -= pushCount;
- // Let inline reflow know that some frames are no longer part of
- // its state.
+ // Let line layout know that some frames are no longer part of its
+ // state.
if (!aLine->IsBlock()) {
- aState.mInlineReflow->ChangeFrameCount(aLine->ChildCount());
+ lineLayout->SplitLineTo(aLine->ChildCount());
}
#ifdef DEBUG
VerifyFrameCount(mLines);
@@ -2927,18 +2795,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// method is used for placing a line of inline frames. If the rare
// case is happening then the worst that will happen is that the
// bullet frame will be reflowed twice.
- nsInlineReflow& ir = *aState.mInlineReflow;
+ nsLineLayout* lineLayout = aState.mLineLayout;
PRBool addedBullet = PR_FALSE;
- if (HaveOutsideBullet() && (aLine == mLines) && !ir.IsZeroHeight()) {
+ if (HaveOutsideBullet() && (aLine == mLines) &&
+ !lineLayout->IsZeroHeight()) {
nsHTMLReflowMetrics metrics(nsnull);
ReflowBullet(aState, metrics);
- ir.AddFrame(mBullet, metrics);
+ lineLayout->AddBulletFrame(mBullet, metrics);
addedBullet = PR_TRUE;
}
- nscoord a, d;
- ir.VerticalAlignFrames(aLine->mBounds, a, d);
+ nsSize maxElementSize;
+ lineLayout->VerticalAlignFrames(aLine->mBounds, maxElementSize);
if (addedBullet) {
- ir.RemoveFrame(mBullet);
+ lineLayout->RemoveBulletFrame(mBullet);
}
#ifdef DEBUG_kipp
NS_ASSERTION((aLine->mBounds.YMost()) < 200000 && (aLine->mBounds.y > -200000), "oy");
@@ -2955,14 +2824,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#else
PRBool allowJustify = PR_FALSE;
#endif
- ir.TrimTrailingWhiteSpace(aLine->mBounds);
- ir.HorizontalAlignFrames(aLine->mBounds, allowJustify);
- ir.RelativePositionFrames(aLine->mCombinedArea);
+ lineLayout->TrimTrailingWhiteSpace(aLine->mBounds);
+ lineLayout->HorizontalAlignFrames(aLine->mBounds, allowJustify);
+ lineLayout->RelativePositionFrames(aLine->mCombinedArea);
// Calculate the bottom margin for the line.
nscoord lineBottomMargin = 0;
if (0 == aLine->mBounds.height) {
- nsIFrame* brFrame = aState.mLineLayout->GetBRFrame();
+ // XXX I don't think that this is necessary anymore because of the
+ // way that min-line-height is applied in the vertical alignment
+ // code; since we always have a line-height, a BR on its own line
+ // will get at least the default line-height amount of vertical
+ // space.
+ nsIFrame* brFrame = lineLayout->GetBRFrame();
if (nsnull != brFrame) {
// If a line ends in a BR, and the line is empty of height, then
// we make sure that the line ends up with some height
@@ -2984,43 +2858,32 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
}
}
- else {
- aState.mRunInFromFrame = nsnull;
- aState.mRunInToFrame = nsnull;
- }
// Calculate the lines top and bottom margin values. The margin will
// come from an embedded block frame, not from inline
// frames. Because this is an "inline" line, the child margins are
// all effectively zero so we pass in nsMargin(0, 0, 0, 0).
nscoord topMargin, bottomMargin;
+ nscoord cotm = lineLayout->GetCarriedOutTopMargin();
+ nscoord cobm = lineLayout->GetCarriedOutBottomMargin();
nsBlockReflowContext::CollapseMargins(nsMargin(0, 0, 0, 0),
- ir.GetCarriedOutTopMargin(),
- ir.GetCarriedOutBottomMargin(),
+ cotm, cobm,
aLine->mBounds.height,
aState.mPrevBottomMargin,
topMargin, bottomMargin);
-#if XXX
-ListTag(stdout);
-printf(": ");
-((nsFrame*)(aLine->mFirstChild))->ListTag(stdout);
-printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
- aState.mY, ir.GetCarriedOutTopMargin(), ir.GetCarriedOutBottomMargin(),
- topMargin, bottomMargin, aState.mPrevBottomMargin,
- aState.ShouldApplyTopMargin() ? "yes" : "no");
-#endif
if (!aState.ShouldApplyTopMargin()) {
aState.mCarriedOutTopMargin = topMargin;
topMargin = 0;
}
+ lineLayout->EndLineReflow();
+#ifdef DEBUG
+ lineLayout = nsnull;
+#endif
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
nscoord newY = aLine->mBounds.YMost() + topMargin + lineBottomMargin;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
- newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
// follows to our next-in-flow
@@ -3037,8 +2900,8 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
return rv;
}
- aLine->mCarriedOutTopMargin = ir.GetCarriedOutTopMargin();
- aLine->mCarriedOutBottomMargin = ir.GetCarriedOutBottomMargin();
+ aLine->mCarriedOutTopMargin = cotm;
+ aLine->mCarriedOutBottomMargin = cobm;
aState.mPrevBottomMargin = bottomMargin;
if (0 != topMargin) {
// Apply collapsed top-margin value
@@ -3048,7 +2911,7 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
}
aState.mY = newY;
- PostPlaceLine(aState, aLine, ir.GetMaxElementSize());
+ PostPlaceLine(aState, aLine, maxElementSize);
// Any below current line floaters to place?
if (0 != aState.mPendingFloaters.Count()) {
@@ -3094,8 +2957,8 @@ nsBlockFrame::ComputeLineMaxElementSize(nsBlockReflowState& aState,
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- const nsSize& aMaxElementSize)
+ nsLineBox* aLine,
+ const nsSize& aMaxElementSize)
{
// Update max-element-size
if (aState.mComputeMaxElementSize) {
@@ -3355,7 +3218,6 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
if (nsnull != lastFrame) {
lastFrame->SetNextSibling(aNewFrame);
}
- nsresult rv;
// Make sure that new inlines go onto the end of the lastLine when
// the lastLine is mapping inline frames.
@@ -3371,19 +3233,7 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
for (nsIFrame* frame = aNewFrame; nsnull != frame;
frame->GetNextSibling(&frame)) {
// See if the child is a block or non-block
- const nsStyleDisplay* kidDisplay;
- rv = frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- const nsStylePosition* kidPosition;
- rv = frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) kidPosition);
- if (NS_OK != rv) {
- return rv;
- }
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(frame);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -3517,15 +3367,8 @@ nsBlockFrame::InsertNewFrames(nsIPresContext& aPresContext,
nsIFrame* next;
newFrame->GetNextSibling(&next);
newFrame->SetNextSibling(nsnull);
-
- const nsStyleDisplay* display;
- newFrame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- newFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
- nsLineLayout::TreatFrameAsBlock(display, position)
+ nsLineLayout::TreatFrameAsBlock(newFrame)
? LINE_IS_BLOCK
: 0;
@@ -4092,7 +3935,7 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
- if (0 == mLineLayout->GetPlacedFrames()) {
+ if (mLineLayout->LineIsEmpty()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
@@ -4118,11 +3961,11 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
- mLineLayout->UpdateInlines(mAvailSpaceRect.x + BorderPadding().left,
- mY,
- mAvailSpaceRect.width,
- mAvailSpaceRect.height,
- isLeftFloater);
+ mLineLayout->UpdateBand(mAvailSpaceRect.x + BorderPadding().left,
+ mY,
+ mAvailSpaceRect.width,
+ mAvailSpaceRect.height,
+ isLeftFloater);
// Restore coordinate system
mSpaceManager->Translate(dx, dy);
@@ -4797,9 +4640,9 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
- nsLineLayout textRunThingy(aPresContext, nsnull);
+ nsLineLayout textRunThingy(aPresContext);
- // Ask each child that implements nsIInlineReflow to find its text runs
+ // Ask each child to find its text runs
nsLineBox* line = mLines;
while (nsnull != line) {
if (!line->IsBlock()) {
@@ -4822,8 +4665,8 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
}
}
else {
- // A frame that doesn't implement nsIInlineReflow isn't text
- // therefore it will end an open text run.
+ // A block frame isn't text therefore it will end an open text
+ // run.
textRunThingy.EndTextRun();
}
line = line->mNext;
@@ -4835,39 +4678,6 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
return NS_OK;
}
-void
-nsBlockFrame::TakeRunInFrames(nsBlockFrame* aRunInFrame)
-{
- // Simply steal the run-in-frame's line list and make it our
- // own. XXX Very similar to the logic in DrainOverflowLines...
- nsLineBox* line = aRunInFrame->mLines;
-
- // Make all the frames on the mOverflowLines list mine
- nsIFrame* lastFrame = nsnull;
- nsIFrame* frame = line->mFirstChild;
- while (nsnull != frame) {
- frame->SetParent(this);
- lastFrame = frame;
- frame->GetNextSibling(&frame);
- }
-
- // Join the line lists
- if (nsnull == mLines) {
- mLines = line;
- }
- else {
- // Join the sibling lists together
- lastFrame->SetNextSibling(mLines->mFirstChild);
-
- // Place overflow lines at the front of our line list
- nsLineBox* lastLine = nsLineBox::LastLine(line);
- lastLine->mNext = mLines;
- mLines = line;
- }
-
- aRunInFrame->mLines = nsnull;
-}
-
//----------------------------------------------------------------------
nsresult
@@ -5065,29 +4875,6 @@ nsAnonymousBlockFrame::RemoveFramesFrom(nsIFrame* aFrame)
#endif
}
-#if 0
-nscoord
-nsBlockFrame::ComputeCollapsedTopMargin(const nsHTMLReflowState& aReflowState)
-{
- nscoord myTopMargin = aReflowState.computedMargin.top;
- nsLineBox* line = mLines;
- if (nsnull != line) {
- if (line->IsEmptyLine()) {
- line = line->mNext;
- if (nsnull == line) {
- return myTopMargin;
- }
- }
- if (1 == line->ChildCount()) {
- nsHTMLReflowState rs();
- nscoord topMargin = line->mFirstChild->ComputeCollapsedTopMargin(rs);
- return nsBlockReflowContext::MaxMargin(topMargin, myTopMargin);
- }
- }
- return myTopMargin;
-}
-#endif
-
#ifdef DEBUG
void
nsBlockFrame::VerifyFrameCount(nsLineBox* line)
diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h
index dd9ca8b5067..0ea613b8178 100644
--- a/mozilla/layout/generic/nsBlockFrame.h
+++ b/mozilla/layout/generic/nsBlockFrame.h
@@ -277,8 +277,6 @@ protected:
nsLineBox* aLine,
nscoord aDeltaY);
- void TakeRunInFrames(nsBlockFrame* aRunInFrame);
-
nsresult ComputeTextRuns(nsIPresContext& aPresContext);
void BuildFloaterList();
diff --git a/mozilla/layout/generic/nsBlockReflowContext.cpp b/mozilla/layout/generic/nsBlockReflowContext.cpp
index 5ccb35f8d69..ac11c762211 100644
--- a/mozilla/layout/generic/nsBlockReflowContext.cpp
+++ b/mozilla/layout/generic/nsBlockReflowContext.cpp
@@ -38,7 +38,6 @@ nsBlockReflowContext::nsBlockReflowContext(nsIPresContext& aPresContext,
mOuterReflowState(aParentRS),
mMetrics(aComputeMaxElementSize ? &mMaxElementSize : nsnull)
{
- mRunInFrame = nsnull;
mCompactMarginWidth = 0;
mStyleSpacing = nsnull;
}
@@ -102,7 +101,6 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
availSpace, reason);
aComputedOffsets = reflowState.computedOffsets;
reflowState.lineLayout = nsnull;
- reflowState.mRunInFrame = mRunInFrame;
reflowState.mCompactMarginWidth = mCompactMarginWidth;
if (!aIsAdjacentWithTop) {
reflowState.isTopOfPage = PR_FALSE; // make sure this is cleared
@@ -312,6 +310,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
mFrame->SetRect(r);
aInFlowBounds = r;
aCombinedRect = mMetrics.mCombinedArea;
+ mTopMargin = 0;
+ mBottomMargin = 0;
fits = PR_TRUE;
}
else {
diff --git a/mozilla/layout/generic/nsBlockReflowContext.h b/mozilla/layout/generic/nsBlockReflowContext.h
index b3104e91802..f8835ddc398 100644
--- a/mozilla/layout/generic/nsBlockReflowContext.h
+++ b/mozilla/layout/generic/nsBlockReflowContext.h
@@ -40,10 +40,6 @@ public:
PRBool aComputeMaxElementSize);
~nsBlockReflowContext() { }
- void SetRunInFrame(nsBlockFrame* aRunInFrame) {
- mRunInFrame = aRunInFrame;
- }
-
void SetCompactMarginWidth(nscoord aCompactMarginWidth) {
mCompactMarginWidth = aCompactMarginWidth;
}
@@ -132,7 +128,6 @@ protected:
const nsHTMLReflowState& mOuterReflowState;
nsIFrame* mFrame;
- nsBlockFrame* mRunInFrame;
nscoord mCompactMarginWidth;
nsRect mSpace;
nsIFrame* mNextRCFrame;
diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp
index ac46b59140a..017a7055e5b 100644
--- a/mozilla/layout/generic/nsBlockReflowState.cpp
+++ b/mozilla/layout/generic/nsBlockReflowState.cpp
@@ -23,7 +23,6 @@
#include "nsLineBox.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
@@ -64,7 +63,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -75,7 +73,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -210,7 +207,6 @@ public:
const nsHTMLReflowState& mReflowState;
nsLineLayout* mLineLayout;
- nsInlineReflow* mInlineReflow;
nsISpaceManager* mSpaceManager;
nscoord mSpaceManagerX, mSpaceManagerY;
@@ -219,9 +215,6 @@ public:
nsReflowStatus mReflowStatus;
- nsBlockFrame* mRunInFromFrame;
- nsBlockFrame* mRunInToFrame;
-
nscoord mBottomEdge; // maximum Y
PRBool mUnconstrainedWidth;
@@ -275,12 +268,12 @@ public:
void
nsLineLayout::InitFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->InitFloater(aFrame);
+ mBlockRS->InitFloater(aFrame);
}
void
nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->AddFloater(aFrame, PR_FALSE);
+ mBlockRS->AddFloater(aFrame, PR_FALSE);
}
//----------------------------------------------------------------------
@@ -298,8 +291,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mIsMarginRoot(PR_FALSE),
mCarriedOutTopMargin(0)
{
- mInlineReflow = nsnull;
-
mLineLayout = aLineLayout;
mSpaceManager = aReflowState.spaceManager;
@@ -316,30 +307,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mBlock->GetNextInFlow((nsIFrame**)&mNextInFlow);
mKidXMost = 0;
- mRunInFromFrame = nsnull;
- mRunInToFrame = nsnull;
-
-#if 0
- // Compute "content area"
- mUnconstrainedWidth = aReflowState.computedWidth == NS_UNCONSTRAINEDSIZE;
- mUnconstrainedHeight = aReflowState.computedHeight == NS_UNCONSTRAINEDSIZE;
-#ifdef NS_DEBUG
- if ((!mUnconstrainedWidth && (aReflowState.computedWidth > 200000)) ||
- (!mUnconstrainedHeight && (aReflowState.computedHeight > 200000))) {
- mBlock->ListTag(stdout);
- printf(": bad parent: computed size is %d(0x%x),%d(0x%x)\n",
- aReflowState.computedWidth, aReflowState.computedWidth,
- aReflowState.computedHeight, aReflowState.computedHeight);
- if (aReflowState.computedWidth > 200000) {
- mUnconstrainedWidth = PR_TRUE;
- }
- if (aReflowState.computedHeight > 200000) {
- mUnconstrainedHeight = PR_TRUE;
- }
- }
-#endif
-#endif
-
// Compute content area width (the content area is inside the border
// and padding)
mUnconstrainedWidth = PR_FALSE;
@@ -893,30 +860,14 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- // Replace parent provided reflow state with our own significantly
- // more extensive version.
- nsLineLayout ll(aPresContext, aReflowState.spaceManager);
- nsLineLayout* lineLayout = ≪
+ nsLineLayout lineLayout(aPresContext, aReflowState.spaceManager,
+ &aReflowState, nsnull != aMetrics.maxElementSize);
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
- lineLayout);
+ &lineLayout);
+ lineLayout.Init(&state);
if (NS_BLOCK_MARGIN_ROOT & mFlags) {
state.mIsMarginRoot = PR_TRUE;
}
- lineLayout->Init(&state);
-
- // Prepare inline-reflow engine. Note that we will almost always use
- // the inline reflow engine so this setup is not wasted work:
- // because most content has compressed white-space in it, we will
- // use the inline reflow engine to get rid of it.
- nsInlineReflow inlineReflow(ll, aReflowState, this, PR_TRUE,
- state.mComputeMaxElementSize);
- state.mInlineReflow = &inlineReflow;
- lineLayout->PushInline(&inlineReflow);
-
- // Compute the blocks minimum line-height the first time that its
- // needed (which is now).
- nscoord minLineHeight = nsHTMLReflowState::CalcLineHeight(aPresContext, this);
- inlineReflow.SetMinLineHeight(minLineHeight);
if (eReflowReason_Resize != aReflowState.reason) {
RenumberLists();
@@ -956,7 +907,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
else {
// Get next frame in reflow command chain
aReflowState.reflowCommand->GetNext(state.mNextRCFrame);
- inlineReflow.SetNextRCFrame(state.mNextRCFrame);
// Now do the reflow
rv = PrepareChildIncrementalReflow(state);
@@ -989,7 +939,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
- lineLayout->PopInline();
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
@@ -1044,6 +993,20 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
borderPadding.right;
computedWidth = maxWidth;
}
+ else if (aState.mComputeMaxElementSize) {
+ // See if our max-element-size width is larger than our
+ // computed-width. This happens when we are impacted by a
+ // floater. When this does happen, our desired size needs to
+ // include room for the floater.
+ if (computedWidth < aMetrics.maxElementSize->width) {
+#ifdef DEBUG_kipp
+ ListTag(stdout);
+ printf(": adjusting width from %d to %d\n", computedWidth,
+ aMetrics.maxElementSize->width);
+#endif
+ computedWidth = aMetrics.maxElementSize->width;
+ }
+ }
aMetrics.width = computedWidth;
}
#ifdef DEBUG_kipp
@@ -1093,6 +1056,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
(0 == aState.mY - borderPadding.top))) {
aMetrics.width = 0;
aMetrics.height = 0;
+ aMetrics.mCarriedOutTopMargin = 0;
+ aMetrics.mCarriedOutBottomMargin = 0;
emptyFrame = PR_TRUE;
}
@@ -1218,17 +1183,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsresult
nsBlockFrame::PrepareInitialReflow(nsBlockReflowState& aState)
{
- if ((nsnull == mPrevInFlow) && (nsnull != aState.mReflowState.mRunInFrame)) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": run-in from: ");
- aState.mReflowState.mRunInFrame->ListTag(stdout);
- printf("\n");
-#endif
- // Take frames away from the run-in frame
- TakeRunInFrames(aState.mReflowState.mRunInFrame);
- }
-
PrepareResizeReflow(aState);
return NS_OK;
}
@@ -1598,7 +1552,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
// Pull data from a next-in-flow if we can
@@ -1663,7 +1617,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
}
@@ -1719,8 +1673,8 @@ nsBlockFrame::WillReflowLine(nsBlockReflowState& aState,
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- PRBool* aKeepReflowGoing)
+ nsLineBox* aLine,
+ PRBool* aKeepReflowGoing)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBlockFrame::ReflowLine: line=%p", aLine));
@@ -1748,7 +1702,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
}
// Setup the line-layout for the new line
- aState.mLineLayout->Reset();
aState.mCurrentLine = aLine;
aLine->ClearDirty();
aLine->SetNeedDidReflow();
@@ -1758,37 +1711,22 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
// When reflowing a block frame we always get the available space
aState.GetAvailableSpace();
-#if XXX_dead_code
- if ((nsnull != aState.lineLayout) &&
- (0 != aState.lineLayout->GetPlacedFrames())) {
- // Blocks are not allowed on the same line as anything else
- aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
- *aKeepReflowGoing = PR_FALSE;
- }
- else
-#endif
- {
- // Notify observers that we are about to reflow the line
- WillReflowLine(aState, aLine);
+ // Notify observers that we are about to reflow the line
+ WillReflowLine(aState, aLine);
- rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
+ if (NS_FAILED(rv)) {
+ return rv;
}
}
else {
- // When this class is an inline frame and we are reflowing inline
- // frames then there is no point in getting available space.
- nscoord x, availWidth, availHeight;
- aState.GetAvailableSpace();
-
// Setup initial coordinate system for reflowing the inline frames
// into.
+ aState.GetAvailableSpace();
const nsMargin& borderPadding = aState.BorderPadding();
- x = aState.mAvailSpaceRect.x + borderPadding.left;
- availWidth = aState.mAvailSpaceRect.width;
-
+ nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
+ nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord availHeight;
if (aState.mUnconstrainedHeight) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
@@ -1796,7 +1734,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
/* XXX get the height right! */
availHeight = aState.mAvailSpaceRect.height;
}
- aState.mInlineReflow->Init(x, aState.mY, availWidth, availHeight);
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ lineLayout->BeginLineReflow(x, aState.mY, availWidth, availHeight,
+ PR_FALSE /*XXX isTopOfPage*/);
// Notify observers that we are about to reflow the line
WillReflowLine(aState, aLine);
@@ -1863,6 +1803,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
rv = PlaceLine(aState, aLine, aKeepReflowGoing);
}
+ else {
+ lineLayout->EndLineReflow();
+ }
}
return rv;
@@ -2192,14 +2135,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": frame: ");
- nsFrame::ListTag(stdout, aFrame);
- printf(" followed by: ");
- nsFrame::ListTag(stdout, nextFrame);
- printf("\n");
-#endif
followingBlockFrame = (nsBlockFrame*) nextFrame;
break;
}
@@ -2217,30 +2152,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
return followingBlockFrame;
}
-#if XXX
-void
-nsBlockFrame::WillReflowFrame(nsBlockReflowState& aState,
- nsLineBox* aLine,
- nsIFrame* aFrame)
-{
- nsIStyleContext* kidSC;
- aFrame->GetStyleContext(kidSC);
- if (nsnull != kidSC) {
- nsIStyleContext* kidParentSC;
- kidParentSC = kidSC->GetParent();
- if (nsnull != kidParentSC) {
- if (kidParentSC != mStyleContext) {
- // The frame has changed situations so re-resolve its style
- // context in the new situation.
- aFrame->ReResolveStyleContext(&aState.mPresContext, mStyleContext);
- }
- NS_RELEASE(kidParentSC);
- }
- NS_RELEASE(kidSC);
- }
-}
-#endif
-
// XXX This should be a no-op when there is no first-line/letter style
// in force!
void
@@ -2305,15 +2216,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing)
{
NS_PRECONDITION(*aKeepReflowGoing, "bad caller");
- NS_PRECONDITION(0 == aState.mLineLayout->GetPlacedFrames(),
- "non-empty line with a block");
nsresult rv = NS_OK;
nsIFrame* frame = aLine->mFirstChild;
// Prepare the inline reflow engine
-//XXX nsBlockFrame* runInToFrame;
nsBlockFrame* compactWithFrame;
nscoord compactMarginWidth = 0;
PRBool isCompactFrame = PR_FALSE;
@@ -2321,38 +2229,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
switch (display->mDisplay) {
-#if XXX_runin
- case NS_STYLE_DISPLAY_RUN_IN:
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": trying to see if ");
- aFrame->ListTag(stdout);
- printf(" is a run-in candidate\n");
-#endif
- runInToFrame = FindFollowingBlockFrame(frame);
- if (nsnull != runInToFrame) {
-// XXX run-in frame should be pushed to the next-in-flow too if the
-// run-in-to frame is pushed.
- nsRect r(0, aState.mY, 0, 0);
- aLine->mBounds = r;
- aLine->mCombinedArea = r;
- aLine->mCarriedOutTopMargin = 0;
- aLine->mCarriedOutBottomMargin = 0;
- aLine->SetMarginFlags(0);
-#if XXX_need_line_outside_children
- aLine->ClearOutsideChildren();
-#endif
- aLine->mBreakType = NS_STYLE_CLEAR_NONE;
-//XXX aFrame->WillReflow(aState.mPresContext);
- frame->SetRect(r);
- aState.mPrevChild = frame;
- aState.mRunInToFrame = runInToFrame;
- aState.mRunInFrame = (nsBlockFrame*) frame;
- return rv;
- }
- break;
-#endif
-
case NS_STYLE_DISPLAY_COMPACT:
compactWithFrame = FindFollowingBlockFrame(frame);
if (nsnull != compactWithFrame) {
@@ -2392,15 +2268,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
}
-#if XXX_runin
- // Set run-in frame if this is the run-in-to frame. That way the
- // target block frame knows to pick up the children from the run-in
- // frame.
- if (frame == aState.mRunInToFrame) {
- brc.SetRunInFrame(aState.mRunInFrame);
- }
-#endif
-
// Compute the available space for the block
nscoord availHeight = aState.mUnconstrainedHeight
? NS_UNCONSTRAINEDSIZE
@@ -2655,9 +2522,10 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
// Reflow the inline frame
+ nsLineLayout* lineLayout = aState.mLineLayout;
nsReflowStatus frameReflowStatus;
- nsresult rv = aState.mInlineReflow->ReflowFrame(aFrame, aState.IsAdjacentWithTop(),
- frameReflowStatus);
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &aState.mNextRCFrame,
+ frameReflowStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2822,8 +2690,8 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
{
- PRInt32 pushCount = aLine->ChildCount() -
- aState.mInlineReflow->GetCurrentFrameNum();
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ PRInt32 pushCount = aLine->ChildCount() - lineLayout->GetCurrentSpanCount();
//printf("BEFORE (pushCount=%d):\n", pushCount);
//aLine->List(stdout, 0);
if (0 != pushCount) {
@@ -2858,10 +2726,10 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
to->SetIsBlock(aLine->IsBlock());
aLine->mChildCount -= pushCount;
- // Let inline reflow know that some frames are no longer part of
- // its state.
+ // Let line layout know that some frames are no longer part of its
+ // state.
if (!aLine->IsBlock()) {
- aState.mInlineReflow->ChangeFrameCount(aLine->ChildCount());
+ lineLayout->SplitLineTo(aLine->ChildCount());
}
#ifdef DEBUG
VerifyFrameCount(mLines);
@@ -2927,18 +2795,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// method is used for placing a line of inline frames. If the rare
// case is happening then the worst that will happen is that the
// bullet frame will be reflowed twice.
- nsInlineReflow& ir = *aState.mInlineReflow;
+ nsLineLayout* lineLayout = aState.mLineLayout;
PRBool addedBullet = PR_FALSE;
- if (HaveOutsideBullet() && (aLine == mLines) && !ir.IsZeroHeight()) {
+ if (HaveOutsideBullet() && (aLine == mLines) &&
+ !lineLayout->IsZeroHeight()) {
nsHTMLReflowMetrics metrics(nsnull);
ReflowBullet(aState, metrics);
- ir.AddFrame(mBullet, metrics);
+ lineLayout->AddBulletFrame(mBullet, metrics);
addedBullet = PR_TRUE;
}
- nscoord a, d;
- ir.VerticalAlignFrames(aLine->mBounds, a, d);
+ nsSize maxElementSize;
+ lineLayout->VerticalAlignFrames(aLine->mBounds, maxElementSize);
if (addedBullet) {
- ir.RemoveFrame(mBullet);
+ lineLayout->RemoveBulletFrame(mBullet);
}
#ifdef DEBUG_kipp
NS_ASSERTION((aLine->mBounds.YMost()) < 200000 && (aLine->mBounds.y > -200000), "oy");
@@ -2955,14 +2824,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#else
PRBool allowJustify = PR_FALSE;
#endif
- ir.TrimTrailingWhiteSpace(aLine->mBounds);
- ir.HorizontalAlignFrames(aLine->mBounds, allowJustify);
- ir.RelativePositionFrames(aLine->mCombinedArea);
+ lineLayout->TrimTrailingWhiteSpace(aLine->mBounds);
+ lineLayout->HorizontalAlignFrames(aLine->mBounds, allowJustify);
+ lineLayout->RelativePositionFrames(aLine->mCombinedArea);
// Calculate the bottom margin for the line.
nscoord lineBottomMargin = 0;
if (0 == aLine->mBounds.height) {
- nsIFrame* brFrame = aState.mLineLayout->GetBRFrame();
+ // XXX I don't think that this is necessary anymore because of the
+ // way that min-line-height is applied in the vertical alignment
+ // code; since we always have a line-height, a BR on its own line
+ // will get at least the default line-height amount of vertical
+ // space.
+ nsIFrame* brFrame = lineLayout->GetBRFrame();
if (nsnull != brFrame) {
// If a line ends in a BR, and the line is empty of height, then
// we make sure that the line ends up with some height
@@ -2984,43 +2858,32 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
}
}
- else {
- aState.mRunInFromFrame = nsnull;
- aState.mRunInToFrame = nsnull;
- }
// Calculate the lines top and bottom margin values. The margin will
// come from an embedded block frame, not from inline
// frames. Because this is an "inline" line, the child margins are
// all effectively zero so we pass in nsMargin(0, 0, 0, 0).
nscoord topMargin, bottomMargin;
+ nscoord cotm = lineLayout->GetCarriedOutTopMargin();
+ nscoord cobm = lineLayout->GetCarriedOutBottomMargin();
nsBlockReflowContext::CollapseMargins(nsMargin(0, 0, 0, 0),
- ir.GetCarriedOutTopMargin(),
- ir.GetCarriedOutBottomMargin(),
+ cotm, cobm,
aLine->mBounds.height,
aState.mPrevBottomMargin,
topMargin, bottomMargin);
-#if XXX
-ListTag(stdout);
-printf(": ");
-((nsFrame*)(aLine->mFirstChild))->ListTag(stdout);
-printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
- aState.mY, ir.GetCarriedOutTopMargin(), ir.GetCarriedOutBottomMargin(),
- topMargin, bottomMargin, aState.mPrevBottomMargin,
- aState.ShouldApplyTopMargin() ? "yes" : "no");
-#endif
if (!aState.ShouldApplyTopMargin()) {
aState.mCarriedOutTopMargin = topMargin;
topMargin = 0;
}
+ lineLayout->EndLineReflow();
+#ifdef DEBUG
+ lineLayout = nsnull;
+#endif
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
nscoord newY = aLine->mBounds.YMost() + topMargin + lineBottomMargin;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
- newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
// follows to our next-in-flow
@@ -3037,8 +2900,8 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
return rv;
}
- aLine->mCarriedOutTopMargin = ir.GetCarriedOutTopMargin();
- aLine->mCarriedOutBottomMargin = ir.GetCarriedOutBottomMargin();
+ aLine->mCarriedOutTopMargin = cotm;
+ aLine->mCarriedOutBottomMargin = cobm;
aState.mPrevBottomMargin = bottomMargin;
if (0 != topMargin) {
// Apply collapsed top-margin value
@@ -3048,7 +2911,7 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
}
aState.mY = newY;
- PostPlaceLine(aState, aLine, ir.GetMaxElementSize());
+ PostPlaceLine(aState, aLine, maxElementSize);
// Any below current line floaters to place?
if (0 != aState.mPendingFloaters.Count()) {
@@ -3094,8 +2957,8 @@ nsBlockFrame::ComputeLineMaxElementSize(nsBlockReflowState& aState,
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- const nsSize& aMaxElementSize)
+ nsLineBox* aLine,
+ const nsSize& aMaxElementSize)
{
// Update max-element-size
if (aState.mComputeMaxElementSize) {
@@ -3355,7 +3218,6 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
if (nsnull != lastFrame) {
lastFrame->SetNextSibling(aNewFrame);
}
- nsresult rv;
// Make sure that new inlines go onto the end of the lastLine when
// the lastLine is mapping inline frames.
@@ -3371,19 +3233,7 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
for (nsIFrame* frame = aNewFrame; nsnull != frame;
frame->GetNextSibling(&frame)) {
// See if the child is a block or non-block
- const nsStyleDisplay* kidDisplay;
- rv = frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- const nsStylePosition* kidPosition;
- rv = frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) kidPosition);
- if (NS_OK != rv) {
- return rv;
- }
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(frame);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -3517,15 +3367,8 @@ nsBlockFrame::InsertNewFrames(nsIPresContext& aPresContext,
nsIFrame* next;
newFrame->GetNextSibling(&next);
newFrame->SetNextSibling(nsnull);
-
- const nsStyleDisplay* display;
- newFrame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- newFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
- nsLineLayout::TreatFrameAsBlock(display, position)
+ nsLineLayout::TreatFrameAsBlock(newFrame)
? LINE_IS_BLOCK
: 0;
@@ -4092,7 +3935,7 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
- if (0 == mLineLayout->GetPlacedFrames()) {
+ if (mLineLayout->LineIsEmpty()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
@@ -4118,11 +3961,11 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
- mLineLayout->UpdateInlines(mAvailSpaceRect.x + BorderPadding().left,
- mY,
- mAvailSpaceRect.width,
- mAvailSpaceRect.height,
- isLeftFloater);
+ mLineLayout->UpdateBand(mAvailSpaceRect.x + BorderPadding().left,
+ mY,
+ mAvailSpaceRect.width,
+ mAvailSpaceRect.height,
+ isLeftFloater);
// Restore coordinate system
mSpaceManager->Translate(dx, dy);
@@ -4797,9 +4640,9 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
- nsLineLayout textRunThingy(aPresContext, nsnull);
+ nsLineLayout textRunThingy(aPresContext);
- // Ask each child that implements nsIInlineReflow to find its text runs
+ // Ask each child to find its text runs
nsLineBox* line = mLines;
while (nsnull != line) {
if (!line->IsBlock()) {
@@ -4822,8 +4665,8 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
}
}
else {
- // A frame that doesn't implement nsIInlineReflow isn't text
- // therefore it will end an open text run.
+ // A block frame isn't text therefore it will end an open text
+ // run.
textRunThingy.EndTextRun();
}
line = line->mNext;
@@ -4835,39 +4678,6 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
return NS_OK;
}
-void
-nsBlockFrame::TakeRunInFrames(nsBlockFrame* aRunInFrame)
-{
- // Simply steal the run-in-frame's line list and make it our
- // own. XXX Very similar to the logic in DrainOverflowLines...
- nsLineBox* line = aRunInFrame->mLines;
-
- // Make all the frames on the mOverflowLines list mine
- nsIFrame* lastFrame = nsnull;
- nsIFrame* frame = line->mFirstChild;
- while (nsnull != frame) {
- frame->SetParent(this);
- lastFrame = frame;
- frame->GetNextSibling(&frame);
- }
-
- // Join the line lists
- if (nsnull == mLines) {
- mLines = line;
- }
- else {
- // Join the sibling lists together
- lastFrame->SetNextSibling(mLines->mFirstChild);
-
- // Place overflow lines at the front of our line list
- nsLineBox* lastLine = nsLineBox::LastLine(line);
- lastLine->mNext = mLines;
- mLines = line;
- }
-
- aRunInFrame->mLines = nsnull;
-}
-
//----------------------------------------------------------------------
nsresult
@@ -5065,29 +4875,6 @@ nsAnonymousBlockFrame::RemoveFramesFrom(nsIFrame* aFrame)
#endif
}
-#if 0
-nscoord
-nsBlockFrame::ComputeCollapsedTopMargin(const nsHTMLReflowState& aReflowState)
-{
- nscoord myTopMargin = aReflowState.computedMargin.top;
- nsLineBox* line = mLines;
- if (nsnull != line) {
- if (line->IsEmptyLine()) {
- line = line->mNext;
- if (nsnull == line) {
- return myTopMargin;
- }
- }
- if (1 == line->ChildCount()) {
- nsHTMLReflowState rs();
- nscoord topMargin = line->mFirstChild->ComputeCollapsedTopMargin(rs);
- return nsBlockReflowContext::MaxMargin(topMargin, myTopMargin);
- }
- }
- return myTopMargin;
-}
-#endif
-
#ifdef DEBUG
void
nsBlockFrame::VerifyFrameCount(nsLineBox* line)
diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h
index ac46b59140a..017a7055e5b 100644
--- a/mozilla/layout/generic/nsBlockReflowState.h
+++ b/mozilla/layout/generic/nsBlockReflowState.h
@@ -23,7 +23,6 @@
#include "nsLineBox.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
@@ -64,7 +63,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -75,7 +73,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -210,7 +207,6 @@ public:
const nsHTMLReflowState& mReflowState;
nsLineLayout* mLineLayout;
- nsInlineReflow* mInlineReflow;
nsISpaceManager* mSpaceManager;
nscoord mSpaceManagerX, mSpaceManagerY;
@@ -219,9 +215,6 @@ public:
nsReflowStatus mReflowStatus;
- nsBlockFrame* mRunInFromFrame;
- nsBlockFrame* mRunInToFrame;
-
nscoord mBottomEdge; // maximum Y
PRBool mUnconstrainedWidth;
@@ -275,12 +268,12 @@ public:
void
nsLineLayout::InitFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->InitFloater(aFrame);
+ mBlockRS->InitFloater(aFrame);
}
void
nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->AddFloater(aFrame, PR_FALSE);
+ mBlockRS->AddFloater(aFrame, PR_FALSE);
}
//----------------------------------------------------------------------
@@ -298,8 +291,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mIsMarginRoot(PR_FALSE),
mCarriedOutTopMargin(0)
{
- mInlineReflow = nsnull;
-
mLineLayout = aLineLayout;
mSpaceManager = aReflowState.spaceManager;
@@ -316,30 +307,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mBlock->GetNextInFlow((nsIFrame**)&mNextInFlow);
mKidXMost = 0;
- mRunInFromFrame = nsnull;
- mRunInToFrame = nsnull;
-
-#if 0
- // Compute "content area"
- mUnconstrainedWidth = aReflowState.computedWidth == NS_UNCONSTRAINEDSIZE;
- mUnconstrainedHeight = aReflowState.computedHeight == NS_UNCONSTRAINEDSIZE;
-#ifdef NS_DEBUG
- if ((!mUnconstrainedWidth && (aReflowState.computedWidth > 200000)) ||
- (!mUnconstrainedHeight && (aReflowState.computedHeight > 200000))) {
- mBlock->ListTag(stdout);
- printf(": bad parent: computed size is %d(0x%x),%d(0x%x)\n",
- aReflowState.computedWidth, aReflowState.computedWidth,
- aReflowState.computedHeight, aReflowState.computedHeight);
- if (aReflowState.computedWidth > 200000) {
- mUnconstrainedWidth = PR_TRUE;
- }
- if (aReflowState.computedHeight > 200000) {
- mUnconstrainedHeight = PR_TRUE;
- }
- }
-#endif
-#endif
-
// Compute content area width (the content area is inside the border
// and padding)
mUnconstrainedWidth = PR_FALSE;
@@ -893,30 +860,14 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- // Replace parent provided reflow state with our own significantly
- // more extensive version.
- nsLineLayout ll(aPresContext, aReflowState.spaceManager);
- nsLineLayout* lineLayout = ≪
+ nsLineLayout lineLayout(aPresContext, aReflowState.spaceManager,
+ &aReflowState, nsnull != aMetrics.maxElementSize);
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
- lineLayout);
+ &lineLayout);
+ lineLayout.Init(&state);
if (NS_BLOCK_MARGIN_ROOT & mFlags) {
state.mIsMarginRoot = PR_TRUE;
}
- lineLayout->Init(&state);
-
- // Prepare inline-reflow engine. Note that we will almost always use
- // the inline reflow engine so this setup is not wasted work:
- // because most content has compressed white-space in it, we will
- // use the inline reflow engine to get rid of it.
- nsInlineReflow inlineReflow(ll, aReflowState, this, PR_TRUE,
- state.mComputeMaxElementSize);
- state.mInlineReflow = &inlineReflow;
- lineLayout->PushInline(&inlineReflow);
-
- // Compute the blocks minimum line-height the first time that its
- // needed (which is now).
- nscoord minLineHeight = nsHTMLReflowState::CalcLineHeight(aPresContext, this);
- inlineReflow.SetMinLineHeight(minLineHeight);
if (eReflowReason_Resize != aReflowState.reason) {
RenumberLists();
@@ -956,7 +907,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
else {
// Get next frame in reflow command chain
aReflowState.reflowCommand->GetNext(state.mNextRCFrame);
- inlineReflow.SetNextRCFrame(state.mNextRCFrame);
// Now do the reflow
rv = PrepareChildIncrementalReflow(state);
@@ -989,7 +939,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
- lineLayout->PopInline();
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
@@ -1044,6 +993,20 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
borderPadding.right;
computedWidth = maxWidth;
}
+ else if (aState.mComputeMaxElementSize) {
+ // See if our max-element-size width is larger than our
+ // computed-width. This happens when we are impacted by a
+ // floater. When this does happen, our desired size needs to
+ // include room for the floater.
+ if (computedWidth < aMetrics.maxElementSize->width) {
+#ifdef DEBUG_kipp
+ ListTag(stdout);
+ printf(": adjusting width from %d to %d\n", computedWidth,
+ aMetrics.maxElementSize->width);
+#endif
+ computedWidth = aMetrics.maxElementSize->width;
+ }
+ }
aMetrics.width = computedWidth;
}
#ifdef DEBUG_kipp
@@ -1093,6 +1056,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
(0 == aState.mY - borderPadding.top))) {
aMetrics.width = 0;
aMetrics.height = 0;
+ aMetrics.mCarriedOutTopMargin = 0;
+ aMetrics.mCarriedOutBottomMargin = 0;
emptyFrame = PR_TRUE;
}
@@ -1218,17 +1183,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsresult
nsBlockFrame::PrepareInitialReflow(nsBlockReflowState& aState)
{
- if ((nsnull == mPrevInFlow) && (nsnull != aState.mReflowState.mRunInFrame)) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": run-in from: ");
- aState.mReflowState.mRunInFrame->ListTag(stdout);
- printf("\n");
-#endif
- // Take frames away from the run-in frame
- TakeRunInFrames(aState.mReflowState.mRunInFrame);
- }
-
PrepareResizeReflow(aState);
return NS_OK;
}
@@ -1598,7 +1552,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
// Pull data from a next-in-flow if we can
@@ -1663,7 +1617,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
}
@@ -1719,8 +1673,8 @@ nsBlockFrame::WillReflowLine(nsBlockReflowState& aState,
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- PRBool* aKeepReflowGoing)
+ nsLineBox* aLine,
+ PRBool* aKeepReflowGoing)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBlockFrame::ReflowLine: line=%p", aLine));
@@ -1748,7 +1702,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
}
// Setup the line-layout for the new line
- aState.mLineLayout->Reset();
aState.mCurrentLine = aLine;
aLine->ClearDirty();
aLine->SetNeedDidReflow();
@@ -1758,37 +1711,22 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
// When reflowing a block frame we always get the available space
aState.GetAvailableSpace();
-#if XXX_dead_code
- if ((nsnull != aState.lineLayout) &&
- (0 != aState.lineLayout->GetPlacedFrames())) {
- // Blocks are not allowed on the same line as anything else
- aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
- *aKeepReflowGoing = PR_FALSE;
- }
- else
-#endif
- {
- // Notify observers that we are about to reflow the line
- WillReflowLine(aState, aLine);
+ // Notify observers that we are about to reflow the line
+ WillReflowLine(aState, aLine);
- rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
+ if (NS_FAILED(rv)) {
+ return rv;
}
}
else {
- // When this class is an inline frame and we are reflowing inline
- // frames then there is no point in getting available space.
- nscoord x, availWidth, availHeight;
- aState.GetAvailableSpace();
-
// Setup initial coordinate system for reflowing the inline frames
// into.
+ aState.GetAvailableSpace();
const nsMargin& borderPadding = aState.BorderPadding();
- x = aState.mAvailSpaceRect.x + borderPadding.left;
- availWidth = aState.mAvailSpaceRect.width;
-
+ nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
+ nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord availHeight;
if (aState.mUnconstrainedHeight) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
@@ -1796,7 +1734,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
/* XXX get the height right! */
availHeight = aState.mAvailSpaceRect.height;
}
- aState.mInlineReflow->Init(x, aState.mY, availWidth, availHeight);
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ lineLayout->BeginLineReflow(x, aState.mY, availWidth, availHeight,
+ PR_FALSE /*XXX isTopOfPage*/);
// Notify observers that we are about to reflow the line
WillReflowLine(aState, aLine);
@@ -1863,6 +1803,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
rv = PlaceLine(aState, aLine, aKeepReflowGoing);
}
+ else {
+ lineLayout->EndLineReflow();
+ }
}
return rv;
@@ -2192,14 +2135,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": frame: ");
- nsFrame::ListTag(stdout, aFrame);
- printf(" followed by: ");
- nsFrame::ListTag(stdout, nextFrame);
- printf("\n");
-#endif
followingBlockFrame = (nsBlockFrame*) nextFrame;
break;
}
@@ -2217,30 +2152,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
return followingBlockFrame;
}
-#if XXX
-void
-nsBlockFrame::WillReflowFrame(nsBlockReflowState& aState,
- nsLineBox* aLine,
- nsIFrame* aFrame)
-{
- nsIStyleContext* kidSC;
- aFrame->GetStyleContext(kidSC);
- if (nsnull != kidSC) {
- nsIStyleContext* kidParentSC;
- kidParentSC = kidSC->GetParent();
- if (nsnull != kidParentSC) {
- if (kidParentSC != mStyleContext) {
- // The frame has changed situations so re-resolve its style
- // context in the new situation.
- aFrame->ReResolveStyleContext(&aState.mPresContext, mStyleContext);
- }
- NS_RELEASE(kidParentSC);
- }
- NS_RELEASE(kidSC);
- }
-}
-#endif
-
// XXX This should be a no-op when there is no first-line/letter style
// in force!
void
@@ -2305,15 +2216,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing)
{
NS_PRECONDITION(*aKeepReflowGoing, "bad caller");
- NS_PRECONDITION(0 == aState.mLineLayout->GetPlacedFrames(),
- "non-empty line with a block");
nsresult rv = NS_OK;
nsIFrame* frame = aLine->mFirstChild;
// Prepare the inline reflow engine
-//XXX nsBlockFrame* runInToFrame;
nsBlockFrame* compactWithFrame;
nscoord compactMarginWidth = 0;
PRBool isCompactFrame = PR_FALSE;
@@ -2321,38 +2229,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
switch (display->mDisplay) {
-#if XXX_runin
- case NS_STYLE_DISPLAY_RUN_IN:
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": trying to see if ");
- aFrame->ListTag(stdout);
- printf(" is a run-in candidate\n");
-#endif
- runInToFrame = FindFollowingBlockFrame(frame);
- if (nsnull != runInToFrame) {
-// XXX run-in frame should be pushed to the next-in-flow too if the
-// run-in-to frame is pushed.
- nsRect r(0, aState.mY, 0, 0);
- aLine->mBounds = r;
- aLine->mCombinedArea = r;
- aLine->mCarriedOutTopMargin = 0;
- aLine->mCarriedOutBottomMargin = 0;
- aLine->SetMarginFlags(0);
-#if XXX_need_line_outside_children
- aLine->ClearOutsideChildren();
-#endif
- aLine->mBreakType = NS_STYLE_CLEAR_NONE;
-//XXX aFrame->WillReflow(aState.mPresContext);
- frame->SetRect(r);
- aState.mPrevChild = frame;
- aState.mRunInToFrame = runInToFrame;
- aState.mRunInFrame = (nsBlockFrame*) frame;
- return rv;
- }
- break;
-#endif
-
case NS_STYLE_DISPLAY_COMPACT:
compactWithFrame = FindFollowingBlockFrame(frame);
if (nsnull != compactWithFrame) {
@@ -2392,15 +2268,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
}
-#if XXX_runin
- // Set run-in frame if this is the run-in-to frame. That way the
- // target block frame knows to pick up the children from the run-in
- // frame.
- if (frame == aState.mRunInToFrame) {
- brc.SetRunInFrame(aState.mRunInFrame);
- }
-#endif
-
// Compute the available space for the block
nscoord availHeight = aState.mUnconstrainedHeight
? NS_UNCONSTRAINEDSIZE
@@ -2655,9 +2522,10 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
// Reflow the inline frame
+ nsLineLayout* lineLayout = aState.mLineLayout;
nsReflowStatus frameReflowStatus;
- nsresult rv = aState.mInlineReflow->ReflowFrame(aFrame, aState.IsAdjacentWithTop(),
- frameReflowStatus);
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &aState.mNextRCFrame,
+ frameReflowStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2822,8 +2690,8 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
{
- PRInt32 pushCount = aLine->ChildCount() -
- aState.mInlineReflow->GetCurrentFrameNum();
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ PRInt32 pushCount = aLine->ChildCount() - lineLayout->GetCurrentSpanCount();
//printf("BEFORE (pushCount=%d):\n", pushCount);
//aLine->List(stdout, 0);
if (0 != pushCount) {
@@ -2858,10 +2726,10 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
to->SetIsBlock(aLine->IsBlock());
aLine->mChildCount -= pushCount;
- // Let inline reflow know that some frames are no longer part of
- // its state.
+ // Let line layout know that some frames are no longer part of its
+ // state.
if (!aLine->IsBlock()) {
- aState.mInlineReflow->ChangeFrameCount(aLine->ChildCount());
+ lineLayout->SplitLineTo(aLine->ChildCount());
}
#ifdef DEBUG
VerifyFrameCount(mLines);
@@ -2927,18 +2795,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// method is used for placing a line of inline frames. If the rare
// case is happening then the worst that will happen is that the
// bullet frame will be reflowed twice.
- nsInlineReflow& ir = *aState.mInlineReflow;
+ nsLineLayout* lineLayout = aState.mLineLayout;
PRBool addedBullet = PR_FALSE;
- if (HaveOutsideBullet() && (aLine == mLines) && !ir.IsZeroHeight()) {
+ if (HaveOutsideBullet() && (aLine == mLines) &&
+ !lineLayout->IsZeroHeight()) {
nsHTMLReflowMetrics metrics(nsnull);
ReflowBullet(aState, metrics);
- ir.AddFrame(mBullet, metrics);
+ lineLayout->AddBulletFrame(mBullet, metrics);
addedBullet = PR_TRUE;
}
- nscoord a, d;
- ir.VerticalAlignFrames(aLine->mBounds, a, d);
+ nsSize maxElementSize;
+ lineLayout->VerticalAlignFrames(aLine->mBounds, maxElementSize);
if (addedBullet) {
- ir.RemoveFrame(mBullet);
+ lineLayout->RemoveBulletFrame(mBullet);
}
#ifdef DEBUG_kipp
NS_ASSERTION((aLine->mBounds.YMost()) < 200000 && (aLine->mBounds.y > -200000), "oy");
@@ -2955,14 +2824,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#else
PRBool allowJustify = PR_FALSE;
#endif
- ir.TrimTrailingWhiteSpace(aLine->mBounds);
- ir.HorizontalAlignFrames(aLine->mBounds, allowJustify);
- ir.RelativePositionFrames(aLine->mCombinedArea);
+ lineLayout->TrimTrailingWhiteSpace(aLine->mBounds);
+ lineLayout->HorizontalAlignFrames(aLine->mBounds, allowJustify);
+ lineLayout->RelativePositionFrames(aLine->mCombinedArea);
// Calculate the bottom margin for the line.
nscoord lineBottomMargin = 0;
if (0 == aLine->mBounds.height) {
- nsIFrame* brFrame = aState.mLineLayout->GetBRFrame();
+ // XXX I don't think that this is necessary anymore because of the
+ // way that min-line-height is applied in the vertical alignment
+ // code; since we always have a line-height, a BR on its own line
+ // will get at least the default line-height amount of vertical
+ // space.
+ nsIFrame* brFrame = lineLayout->GetBRFrame();
if (nsnull != brFrame) {
// If a line ends in a BR, and the line is empty of height, then
// we make sure that the line ends up with some height
@@ -2984,43 +2858,32 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
}
}
- else {
- aState.mRunInFromFrame = nsnull;
- aState.mRunInToFrame = nsnull;
- }
// Calculate the lines top and bottom margin values. The margin will
// come from an embedded block frame, not from inline
// frames. Because this is an "inline" line, the child margins are
// all effectively zero so we pass in nsMargin(0, 0, 0, 0).
nscoord topMargin, bottomMargin;
+ nscoord cotm = lineLayout->GetCarriedOutTopMargin();
+ nscoord cobm = lineLayout->GetCarriedOutBottomMargin();
nsBlockReflowContext::CollapseMargins(nsMargin(0, 0, 0, 0),
- ir.GetCarriedOutTopMargin(),
- ir.GetCarriedOutBottomMargin(),
+ cotm, cobm,
aLine->mBounds.height,
aState.mPrevBottomMargin,
topMargin, bottomMargin);
-#if XXX
-ListTag(stdout);
-printf(": ");
-((nsFrame*)(aLine->mFirstChild))->ListTag(stdout);
-printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
- aState.mY, ir.GetCarriedOutTopMargin(), ir.GetCarriedOutBottomMargin(),
- topMargin, bottomMargin, aState.mPrevBottomMargin,
- aState.ShouldApplyTopMargin() ? "yes" : "no");
-#endif
if (!aState.ShouldApplyTopMargin()) {
aState.mCarriedOutTopMargin = topMargin;
topMargin = 0;
}
+ lineLayout->EndLineReflow();
+#ifdef DEBUG
+ lineLayout = nsnull;
+#endif
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
nscoord newY = aLine->mBounds.YMost() + topMargin + lineBottomMargin;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
- newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
// follows to our next-in-flow
@@ -3037,8 +2900,8 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
return rv;
}
- aLine->mCarriedOutTopMargin = ir.GetCarriedOutTopMargin();
- aLine->mCarriedOutBottomMargin = ir.GetCarriedOutBottomMargin();
+ aLine->mCarriedOutTopMargin = cotm;
+ aLine->mCarriedOutBottomMargin = cobm;
aState.mPrevBottomMargin = bottomMargin;
if (0 != topMargin) {
// Apply collapsed top-margin value
@@ -3048,7 +2911,7 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
}
aState.mY = newY;
- PostPlaceLine(aState, aLine, ir.GetMaxElementSize());
+ PostPlaceLine(aState, aLine, maxElementSize);
// Any below current line floaters to place?
if (0 != aState.mPendingFloaters.Count()) {
@@ -3094,8 +2957,8 @@ nsBlockFrame::ComputeLineMaxElementSize(nsBlockReflowState& aState,
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- const nsSize& aMaxElementSize)
+ nsLineBox* aLine,
+ const nsSize& aMaxElementSize)
{
// Update max-element-size
if (aState.mComputeMaxElementSize) {
@@ -3355,7 +3218,6 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
if (nsnull != lastFrame) {
lastFrame->SetNextSibling(aNewFrame);
}
- nsresult rv;
// Make sure that new inlines go onto the end of the lastLine when
// the lastLine is mapping inline frames.
@@ -3371,19 +3233,7 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
for (nsIFrame* frame = aNewFrame; nsnull != frame;
frame->GetNextSibling(&frame)) {
// See if the child is a block or non-block
- const nsStyleDisplay* kidDisplay;
- rv = frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- const nsStylePosition* kidPosition;
- rv = frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) kidPosition);
- if (NS_OK != rv) {
- return rv;
- }
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(frame);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -3517,15 +3367,8 @@ nsBlockFrame::InsertNewFrames(nsIPresContext& aPresContext,
nsIFrame* next;
newFrame->GetNextSibling(&next);
newFrame->SetNextSibling(nsnull);
-
- const nsStyleDisplay* display;
- newFrame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- newFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
- nsLineLayout::TreatFrameAsBlock(display, position)
+ nsLineLayout::TreatFrameAsBlock(newFrame)
? LINE_IS_BLOCK
: 0;
@@ -4092,7 +3935,7 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
- if (0 == mLineLayout->GetPlacedFrames()) {
+ if (mLineLayout->LineIsEmpty()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
@@ -4118,11 +3961,11 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
- mLineLayout->UpdateInlines(mAvailSpaceRect.x + BorderPadding().left,
- mY,
- mAvailSpaceRect.width,
- mAvailSpaceRect.height,
- isLeftFloater);
+ mLineLayout->UpdateBand(mAvailSpaceRect.x + BorderPadding().left,
+ mY,
+ mAvailSpaceRect.width,
+ mAvailSpaceRect.height,
+ isLeftFloater);
// Restore coordinate system
mSpaceManager->Translate(dx, dy);
@@ -4797,9 +4640,9 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
- nsLineLayout textRunThingy(aPresContext, nsnull);
+ nsLineLayout textRunThingy(aPresContext);
- // Ask each child that implements nsIInlineReflow to find its text runs
+ // Ask each child to find its text runs
nsLineBox* line = mLines;
while (nsnull != line) {
if (!line->IsBlock()) {
@@ -4822,8 +4665,8 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
}
}
else {
- // A frame that doesn't implement nsIInlineReflow isn't text
- // therefore it will end an open text run.
+ // A block frame isn't text therefore it will end an open text
+ // run.
textRunThingy.EndTextRun();
}
line = line->mNext;
@@ -4835,39 +4678,6 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
return NS_OK;
}
-void
-nsBlockFrame::TakeRunInFrames(nsBlockFrame* aRunInFrame)
-{
- // Simply steal the run-in-frame's line list and make it our
- // own. XXX Very similar to the logic in DrainOverflowLines...
- nsLineBox* line = aRunInFrame->mLines;
-
- // Make all the frames on the mOverflowLines list mine
- nsIFrame* lastFrame = nsnull;
- nsIFrame* frame = line->mFirstChild;
- while (nsnull != frame) {
- frame->SetParent(this);
- lastFrame = frame;
- frame->GetNextSibling(&frame);
- }
-
- // Join the line lists
- if (nsnull == mLines) {
- mLines = line;
- }
- else {
- // Join the sibling lists together
- lastFrame->SetNextSibling(mLines->mFirstChild);
-
- // Place overflow lines at the front of our line list
- nsLineBox* lastLine = nsLineBox::LastLine(line);
- lastLine->mNext = mLines;
- mLines = line;
- }
-
- aRunInFrame->mLines = nsnull;
-}
-
//----------------------------------------------------------------------
nsresult
@@ -5065,29 +4875,6 @@ nsAnonymousBlockFrame::RemoveFramesFrom(nsIFrame* aFrame)
#endif
}
-#if 0
-nscoord
-nsBlockFrame::ComputeCollapsedTopMargin(const nsHTMLReflowState& aReflowState)
-{
- nscoord myTopMargin = aReflowState.computedMargin.top;
- nsLineBox* line = mLines;
- if (nsnull != line) {
- if (line->IsEmptyLine()) {
- line = line->mNext;
- if (nsnull == line) {
- return myTopMargin;
- }
- }
- if (1 == line->ChildCount()) {
- nsHTMLReflowState rs();
- nscoord topMargin = line->mFirstChild->ComputeCollapsedTopMargin(rs);
- return nsBlockReflowContext::MaxMargin(topMargin, myTopMargin);
- }
- }
- return myTopMargin;
-}
-#endif
-
#ifdef DEBUG
void
nsBlockFrame::VerifyFrameCount(nsLineBox* line)
diff --git a/mozilla/layout/generic/nsBulletFrame.cpp b/mozilla/layout/generic/nsBulletFrame.cpp
index 6556ddb693a..23e1ae86183 100644
--- a/mozilla/layout/generic/nsBulletFrame.cpp
+++ b/mozilla/layout/generic/nsBulletFrame.cpp
@@ -71,6 +71,7 @@ nsBulletFrame::Paint(nsIPresContext& aCX,
if (disp->mVisible) {
const nsStyleList* myList =
(const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List);
+ PRUint8 listStyleType = myList->mListStyleType;
if (myList->mListStyleImage.Length() > 0) {
nsIImage* image = mImageLoader.GetImage();
@@ -81,11 +82,14 @@ nsBulletFrame::Paint(nsIPresContext& aCX,
}
}
else {
- nsRect innerArea(mPadding.left, mPadding.top,
- mRect.width - (mPadding.left + mPadding.right),
- mRect.height - (mPadding.top + mPadding.bottom));
- aRenderingContext.DrawImage(image, innerArea);
- return NS_OK;
+ if (!mImageLoader.GetLoadImageFailed()) {
+ nsRect innerArea(mPadding.left, mPadding.top,
+ mRect.width - (mPadding.left + mPadding.right),
+ mRect.height - (mPadding.top + mPadding.bottom));
+ aRenderingContext.DrawImage(image, innerArea);
+ return NS_OK;
+ }
+ listStyleType = NS_STYLE_LIST_STYLE_DISC;
}
}
@@ -98,7 +102,7 @@ nsBulletFrame::Paint(nsIPresContext& aCX,
aRenderingContext.SetColor(myColor->mColor);
nsAutoString text;
- switch (myList->mListStyleType) {
+ switch (listStyleType) {
case NS_STYLE_LIST_STYLE_NONE:
break;
diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp
index 346e7a44e47..c539e0fa6f4 100644
--- a/mozilla/layout/generic/nsFrame.cpp
+++ b/mozilla/layout/generic/nsFrame.cpp
@@ -1048,17 +1048,6 @@ nsFrame::MoveInSpaceManager(nsIPresContext& aPresContext,
return NS_OK;
}
-NS_IMETHODIMP
-nsFrame::VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedRect)
-{
- aCombinedRect = mRect;
- return NS_OK;
-}
-
NS_IMETHODIMP
nsFrame::ContentChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h
index e2e93645efb..7bf0d2a163a 100644
--- a/mozilla/layout/generic/nsFrame.h
+++ b/mozilla/layout/generic/nsFrame.h
@@ -234,11 +234,6 @@ public:
NS_IMETHOD MoveInSpaceManager(nsIPresContext& aPresContext,
nsISpaceManager* aSpaceManager,
nscoord aDeltaX, nscoord aDeltaY);
- NS_IMETHOD VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedRect);
// Selection Methods
// XXX Doc me... (in nsIFrame.h puhleeze)
diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.cpp b/mozilla/layout/generic/nsHTMLContainerFrame.cpp
index 25e4695569b..66e78923f61 100644
--- a/mozilla/layout/generic/nsHTMLContainerFrame.cpp
+++ b/mozilla/layout/generic/nsHTMLContainerFrame.cpp
@@ -115,7 +115,7 @@ nsHTMLContainerFrame::CreateNextInFlow(nsIPresContext& aPresContext,
nextInFlow->SetNextSibling(nextFrame);
NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES,
- ("nsInlineReflow::MaybeCreateNextInFlow: frame=%p nextInFlow=%p",
+ ("nsHTMLContainerFrame::MaybeCreateNextInFlow: frame=%p nextInFlow=%p",
aFrame, nextInFlow));
aNextInFlowResult = nextInFlow;
diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp
index 66732bed96f..568cf6534a7 100644
--- a/mozilla/layout/generic/nsHTMLReflowState.cpp
+++ b/mozilla/layout/generic/nsHTMLReflowState.cpp
@@ -126,7 +126,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext& aPresContext,
void
nsHTMLReflowState::Init(nsIPresContext& aPresContext)
{
- mRunInFrame = nsnull;
mCompactMarginWidth = 0;
mAlignCharOffset = 0;
mUseAlignCharOffset = 0;
@@ -1119,25 +1118,23 @@ nsHTMLReflowState::CalcLineHeight(nsIPresContext& aPresContext,
sc->GetStyleData(eStyleStruct_Text);
if (nsnull != text) {
nsStyleUnit unit = text->mLineHeight.GetUnit();
- if (eStyleUnit_Enumerated == unit) {
- // Normal value; we use 1.0 for normal
- // XXX could come from somewhere else
+ if (eStyleUnit_Normal == unit) {
+ // Normal value; we use a factor of 1.0 for normal
+ lineHeight = elementFont->mFont.size;
#ifdef NOISY_VERTICAL_ALIGN
- printf(" line-height: normal\n");
+ printf(" line-height: normal result=%d\n", lineHeight);
#endif
break;
} else if (eStyleUnit_Factor == unit) {
- if (nsnull != elementFont) {
- // CSS2 spec says that the number is inherited, not the
- // computed value. Therefore use the font size of the
- // element times the inherited number.
- nscoord size = elementFont->mFont.size;
- lineHeight = nscoord(size * text->mLineHeight.GetFactorValue());
+ // CSS2 spec says that the number is inherited, not the
+ // computed value. Therefore use the font size of the
+ // element times the inherited number.
+ nscoord size = elementFont->mFont.size;
+ lineHeight = nscoord(size * text->mLineHeight.GetFactorValue());
#ifdef NOISY_VERTICAL_ALIGN
- printf(" line-height: factor=%g result=%d\n",
- text->mLineHeight.GetFactorValue(), lineHeight);
+ printf(" line-height: factor=%g result=%d\n",
+ text->mLineHeight.GetFactorValue(), lineHeight);
#endif
- }
break;
}
else if (eStyleUnit_Coord == unit) {
diff --git a/mozilla/layout/generic/nsImageMap.cpp b/mozilla/layout/generic/nsImageMap.cpp
index 4f794005e40..31850c74fd0 100644
--- a/mozilla/layout/generic/nsImageMap.cpp
+++ b/mozilla/layout/generic/nsImageMap.cpp
@@ -77,8 +77,8 @@ public:
nsString mAltText;
nscoord* mCoords;
PRInt32 mNumCoords;
- PRBool mHasURL;
PRBool mSuppressFeedback;
+ PRBool mHasURL;
};
Area::Area(const nsString& aBaseURL, const nsString& aHREF,
@@ -753,7 +753,7 @@ nsImageMap::UpdateAreas()
// Get rid of old area data
FreeAreas();
- nsresult rv;
+ nsresult rv = NS_OK;
nsIContent* child;
PRInt32 i, n;
PRBool containsBlock = PR_FALSE, containsArea = PR_FALSE;
diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp
index aa3fb212cc7..67e433c8bd6 100644
--- a/mozilla/layout/generic/nsInlineFrame.cpp
+++ b/mozilla/layout/generic/nsInlineFrame.cpp
@@ -20,7 +20,6 @@
#include "nsFrameList.h"
#include "nsBlockReflowContext.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsHTMLIIDs.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLParts.h"
@@ -28,6 +27,8 @@
#include "nsIStyleContext.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
+#include "nsIRenderingContext.h"
+#include "nsIFontMetrics.h"
// XXX TODO:
// append/insert/remove floater testing
@@ -35,7 +36,7 @@
// Theory of operation:
// XXX write this
-#ifdef NS_DEBUG
+#ifdef DEBUG
#undef NOISY_ANON_BLOCK
#else
#undef NOISY_ANON_BLOCK
@@ -89,17 +90,11 @@ public:
nsIRenderingContext& aRC,
nscoord& aDeltaWidth);
#endif
- NS_IMETHOD VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aParentReflowState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedArea);
protected:
// Additional reflow state used during our reflow methods
struct InlineReflowState {
nsIFrame* mNextRCFrame;
- nsInlineReflow* mInlineReflow;
nsIFrame* mPrevFrame;
nsInlineFrame* mNextInFlow;
};
@@ -1184,13 +1179,15 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
+ if (nsnull == aReflowState.lineLayout) {
+ return NS_ERROR_INVALID_ARG;
+ }
DrainOverflow();
// Set our own reflow state (additional state above and beyond
// aReflowState)
InlineReflowState irs;
irs.mPrevFrame = nsnull;
- irs.mInlineReflow = nsnull;
irs.mNextInFlow = (nsInlineFrame*) mNextInFlow;
if (eReflowReason_Incremental == aReflowState.reason) {
// Peel off the next frame in the path if this is an incremental
@@ -1228,8 +1225,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
}
if (HaveAnonymousBlock()) {
- if ((nsnull != aReflowState.lineLayout) &&
- (0 != aReflowState.lineLayout->GetPlacedFrames())) {
+ if (!aReflowState.lineLayout->LineIsEmpty()) {
// This inline frame cannot be placed on the current line
// because there already is an inline frame on this line (and we
// contain an anonymous block).
@@ -1239,30 +1235,27 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
else {
rv = ReflowBlockFrame(aPresContext, aReflowState, irs,
aMetrics, aStatus);
+
+ // If the combined area of our children exceeds our bounding box
+ // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear
+ // it.
+ if ((aMetrics.mCombinedArea.x < 0) ||
+ (aMetrics.mCombinedArea.y < 0) ||
+ (aMetrics.mCombinedArea.XMost() > aMetrics.width) ||
+ (aMetrics.mCombinedArea.YMost() > aMetrics.height)) {
+ mState |= NS_FRAME_OUTSIDE_CHILDREN;
+ }
+ else {
+ mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
+ }
}
}
else {
- if (nsnull != aReflowState.lineLayout) {
- rv = ReflowInlineFrames(aPresContext, aReflowState, irs,
- aMetrics, aStatus);
- }
- else {
- rv = NS_ERROR_NULL_POINTER;
- }
- }
-
- if (NS_SUCCEEDED(rv)) {
- // If the combined area of our children exceeds our bounding box
- // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it.
- if ((aMetrics.mCombinedArea.x < 0) ||
- (aMetrics.mCombinedArea.y < 0) ||
- (aMetrics.mCombinedArea.XMost() > aMetrics.width) ||
- (aMetrics.mCombinedArea.YMost() > aMetrics.height)) {
- mState |= NS_FRAME_OUTSIDE_CHILDREN;
- }
- else {
- mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
- }
+ rv = ReflowInlineFrames(aPresContext, aReflowState, irs,
+ aMetrics, aStatus);
+ // Note: when we are reflowing inline frames the line layout code
+ // will properly compute our NS_FRAME_OUTSIDE_CHILDREN state for
+ // us.
}
return rv;
@@ -1288,114 +1281,6 @@ nsInlineFrame::FindTextRuns(nsLineLayout& aLineLayout)
return NS_OK;
}
-// Perform pass2 vertical alignment on top/bottom aligned child frames
-// XXX relative positioning will need to be done *after* this
-NS_IMETHODIMP
-nsInlineFrame::VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aParentReflowState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedArea)
-{
- if (HaveAnonymousBlock()) {
- // This should be impossible - when we have an inline frame and it
- // contains an anonymous block, none of the blocks children or the
- // block itself will trigger a pass2 valign at this level.
- NS_NOTREACHED("can't get here");
- aCombinedArea = mRect;
- return NS_OK;
- }
-
- // topEdge is the y coordinate of the line's top, relative to this
- // frame (== in this frames local coordinate system).
- nscoord topEdge = -aDistanceFromTopEdge;
-
- nsRect bbox, childCombinedArea;
- nscoord x0 = 0;
- nscoord y0 = 0;
- nscoord x1 = mRect.width;
- nscoord y1 = mRect.height;
- nsIFrame* frame = mFrames.FirstChild();
- while (nsnull != frame) {
- const nsStyleText* textStyle;
- frame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
- nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
- frame->GetRect(bbox);
-
- if (eStyleUnit_Enumerated == verticalAlignUnit) {
- PRUint8 verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
- if (NS_STYLE_VERTICAL_ALIGN_TOP == verticalAlignEnum) {
- nsMargin margin;
- nsHTMLReflowState::ComputeMarginFor(frame, &aParentReflowState,
- margin);
- nsCSSFrameType frameType =
- nsHTMLReflowState::DetermineFrameType(frame);
- bbox.y = topEdge + margin.top;
- if (NS_CSS_FRAME_TYPE_INLINE == frameType) {
- nsMargin bp;
- nsHTMLReflowState::ComputeBorderPaddingFor(frame,
- &aParentReflowState, bp);
- bbox.y -= bp.top;
- }
- frame->SetRect(bbox);
- }
- else if (NS_STYLE_VERTICAL_ALIGN_BOTTOM == verticalAlignEnum) {
- nsMargin margin;
- nsHTMLReflowState::ComputeMarginFor(frame, &aParentReflowState,
- margin);
- nsCSSFrameType frameType =
- nsHTMLReflowState::DetermineFrameType(frame);
- bbox.y = topEdge + aLineHeight - bbox.height - margin.bottom;
- if (NS_CSS_FRAME_TYPE_INLINE == frameType) {
- nsMargin bp;
- nsHTMLReflowState::ComputeBorderPaddingFor(frame,
- &aParentReflowState, bp);
- bbox.y += bp.bottom;
- }
- frame->SetRect(bbox);
- }
- }
-
- // Perform pass2 vertical alignment for top/bottom aligned
- // frames that are not our direct descendants.
- nsIHTMLReflow* ihr;
- nsresult rv = frame->QueryInterface(kIHTMLReflowIID, (void**)&ihr);
- if (NS_SUCCEEDED(rv)) {
- nsSize availSize(0, 0);
- // XXX whacky: we should be passing in the childs reflow state, right?
- nsHTMLReflowState ourReflowState(aPresContext, aParentReflowState,
- this, availSize);
- nscoord distanceFromTopEdge = bbox.y - topEdge;
- ihr->VerticalAlignFrames(aPresContext, ourReflowState, aLineHeight,
- distanceFromTopEdge, childCombinedArea);
- nscoord x = childCombinedArea.x;
- if (x < x0) x0 = x;
- nscoord y = childCombinedArea.y;
- if (y < y0) y0 = y;
- nscoord xmost = childCombinedArea.XMost();
- if (xmost > x1) x1 = xmost;
- nscoord ymost = childCombinedArea.YMost();
- if (ymost > y1) y1 = ymost;
- }
-
- frame->GetNextSibling(&frame);
- }
-
- aCombinedArea.x = mRect.x + x0;
- aCombinedArea.y = mRect.y + y0;
- aCombinedArea.width = x1 - x0;
- aCombinedArea.height = y1 - y0;
-
- // Update our outside-children flag bit
- if ((x0 < 0) || (y0 < 0) || (x1 > mRect.width) || (y1 > mRect.height)) {
- mState |= NS_FRAME_OUTSIDE_CHILDREN;
- }
- else {
- mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
- }
- return NS_OK;
-}
-
void
nsInlineFrame::DrainOverflow()
{
@@ -1427,35 +1312,19 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
nsresult rv = NS_OK;
aStatus = NS_FRAME_COMPLETE;
- nsInlineReflow ir(*aReflowState.lineLayout, aReflowState, this, PR_FALSE,
- nsnull != aMetrics.maxElementSize);
- irs.mInlineReflow = &ir;
- ir.SetNextRCFrame(irs.mNextRCFrame);
- aReflowState.lineLayout->PushInline(&ir);
-
- // Compute available area
- nscoord x = aReflowState.mComputedBorderPadding.left;
+ nsLineLayout* lineLayout = aReflowState.lineLayout;
+ nscoord leftEdge = 0;
+ if (nsnull == mPrevInFlow) {
+ leftEdge = aReflowState.mComputedBorderPadding.left;
+ }
nscoord availableWidth = aReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availableWidth) {
- if (nsnull != mPrevInFlow) {
- x = 0;
- availableWidth -= aReflowState.mComputedBorderPadding.right +
- aReflowState.computedMargin.right;
- }
- else {
- availableWidth -= aReflowState.mComputedBorderPadding.left +
- aReflowState.computedMargin.left +
- aReflowState.mComputedBorderPadding.right +
- aReflowState.computedMargin.right;
- }
+ // Subtract off left and right border+padding from availableWidth
+ availableWidth -= leftEdge;
+ availableWidth -= aReflowState.mComputedBorderPadding.right;
}
- nscoord y = aReflowState.mComputedBorderPadding.top;
- nscoord availableHeight = aReflowState.availableHeight;
- if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
- availableHeight -= aReflowState.mComputedBorderPadding.top +
- aReflowState.mComputedBorderPadding.right;
- }
- ir.Init(x, y, availableWidth, availableHeight);
+ lineLayout->BeginSpan(this, &aReflowState,
+ leftEdge, leftEdge + availableWidth);
// First reflow our current children
nsIFrame* frame = mFrames.FirstChild();
@@ -1489,37 +1358,99 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
irs.mPrevFrame = frame;
}
}
-
- // Compute final metrics
- if (NS_SUCCEEDED(rv)) {
-#ifdef NS_DEBUG
- if (NS_FRAME_COMPLETE == aStatus) {
- // We can't be complete AND have overflow frames!
- NS_ASSERTION(mOverflowFrames.IsEmpty(), "whoops");
- }
+#ifdef DEBUG
+ if (NS_FRAME_COMPLETE == aStatus) {
+ // We can't be complete AND have overflow frames!
+ NS_ASSERTION(mOverflowFrames.IsEmpty(), "whoops");
+ }
#endif
- nsInlineReflow* ir = irs.mInlineReflow;
- nsRect bbox;
- ir->VerticalAlignFrames(bbox, aMetrics.ascent, aMetrics.descent);
- ir->RelativePositionFrames(aMetrics.mCombinedArea);
- aMetrics.width = bbox.XMost();
+
+ // If after reflowing our children they take up no area then make
+ // sure that we don't either.
+ nsSize size;
+ lineLayout->EndSpan(this, size, aMetrics.maxElementSize);
+ if ((0 == size.height) && (0 == size.width)) {
+ aMetrics.width = 0;
+ aMetrics.height = 0;
+ aMetrics.ascent = 0;
+ aMetrics.descent = 0;
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = 0;
+ aMetrics.maxElementSize->height = 0;
+ }
+ }
+ else {
+ // Compute final width
+ aMetrics.width = size.width;
+ if (nsnull == mPrevInFlow) {
+ aMetrics.width += aReflowState.mComputedBorderPadding.left;
+ }
if (NS_FRAME_IS_COMPLETE(aStatus)) {
aMetrics.width += aReflowState.mComputedBorderPadding.right;
}
- aMetrics.height = bbox.height + aReflowState.mComputedBorderPadding.top +
+
+ // Compute final height. The height of our box is the sum of our
+ // font size plus the top and bottom border and padding. The height
+ // of children do not affect our height.
+ //
+ // Note 2: we use the actual font height for sizing our selves instead
+ // of the computed font height. On systems where they disagree the
+ // actual font height is more appropriate.
+ const nsStyleFont* font;
+ GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)font);
+ aReflowState.rendContext->SetFont(font->mFont);
+ nsIFontMetrics* fm;
+ aReflowState.rendContext->GetFontMetrics(fm);
+ fm->GetMaxAscent(aMetrics.ascent);
+ fm->GetMaxDescent(aMetrics.descent);
+ fm->GetHeight(aMetrics.height);
+ aMetrics.ascent += aReflowState.mComputedBorderPadding.top;
+ aMetrics.descent += aReflowState.mComputedBorderPadding.bottom;
+ aMetrics.height += aReflowState.mComputedBorderPadding.top +
aReflowState.mComputedBorderPadding.bottom;
-#ifdef NOISY_FINAL_SIZE
- ListTag(stdout);
- printf(": metrics=%d,%d ascent=%d descent=%d\n",
- aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent);
-#endif
- aMetrics.mCarriedOutTopMargin = 0;
- aMetrics.mCarriedOutBottomMargin = 0;
- if (nsnull != aMetrics.maxElementSize) {
- *aMetrics.maxElementSize = ir->GetMaxElementSize();
+
+#if defined(DEBUG) && defined(XP_UNIX)
+ static PRBool useComputedHeight = PR_FALSE;
+ static PRBool firstTime = 1;
+ if (firstTime) {
+ if (getenv("GECKO_USE_COMPUTED_HEIGHT")) {
+ useComputedHeight = PR_TRUE;
+ }
}
+ if (useComputedHeight) {
+ // Special debug code that violates the above CSS2 spec
+ // clarification. Why? So that we can predictably compute the values
+ // for testing layout.
+ nscoord computedHeight = aReflowState.mComputedBorderPadding.top +
+ aReflowState.mComputedBorderPadding.bottom +
+ font->mFont.size;
+ if (computedHeight != aMetrics.height) {
+ if (0 == (mState & 0x80000000)) {
+ nsFrame::ListTag(stdout, this);
+ printf(": using computedHeight %d instead of actual height %d\n",
+ computedHeight, aMetrics.height);
+ mState |= 0x80000000;
+ }
+ aMetrics.height = computedHeight;
+ }
+ }
+#endif
+
+ NS_RELEASE(fm);
}
- aReflowState.lineLayout->PopInline();
+
+ // For now our combined area is zero. The real value will be
+ // computed during vertical alignment of the line we are on.
+ aMetrics.mCombinedArea.x = 0;
+ aMetrics.mCombinedArea.y = 0;
+ aMetrics.mCombinedArea.width = aMetrics.width;
+ aMetrics.mCombinedArea.height = aMetrics.height;
+
+#ifdef NOISY_FINAL_SIZE
+ ListTag(stdout);
+ printf(": metrics=%d,%d ascent=%d descent=%d\n",
+ aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent);
+#endif
return rv;
}
@@ -1543,8 +1474,8 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
return NS_OK;
}
- nsInlineReflow* ir = irs.mInlineReflow;
- nsresult rv = ir->ReflowFrame(aFrame, PR_FALSE/* XXX */, aStatus);
+ nsLineLayout* lineLayout = aReflowState.lineLayout;
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &irs.mNextRCFrame, aStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -1656,7 +1587,7 @@ nsInlineFrame::PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
{
NS_PRECONDITION(nsnull != aFromChild, "null pointer");
NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child");
-#ifdef NS_DEBUG
+#ifdef DEBUG
nsIFrame* prevNextSibling;
aPrevSibling->GetNextSibling(&prevNextSibling);
NS_PRECONDITION(prevNextSibling == aFromChild, "bad prev sibling");
diff --git a/mozilla/layout/generic/nsLineBox.cpp b/mozilla/layout/generic/nsLineBox.cpp
index 251458a8c4d..004c3820b71 100644
--- a/mozilla/layout/generic/nsLineBox.cpp
+++ b/mozilla/layout/generic/nsLineBox.cpp
@@ -46,16 +46,19 @@ nsLineBox::~nsLineBox()
static void
ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
{
+ nsAutoString frameName;
PRInt32 j, i, n = aFloaters->Count();
for (i = 0; i < n; i++) {
for (j = aIndent; --j >= 0; ) fputs(" ", out);
nsPlaceholderFrame* ph = (nsPlaceholderFrame*) aFloaters->ElementAt(i);
if (nsnull != ph) {
- fprintf(out, "placeholder@%p\n", ph);
+ fprintf(out, "placeholder@%p ", ph);
nsIFrame* frame = ph->GetAnchoredItem();
if (nsnull != frame) {
- frame->List(out, aIndent + 1);
+ frame->GetFrameName(frameName);
+ fputs(frameName, out);
}
+ fprintf(out, "\n");
}
}
}
@@ -277,14 +280,7 @@ nsLineBox::UnplaceFloaters(nsISpaceManager* aSpaceManager)
PRBool
nsLineBox::CheckIsBlock() const
{
- nsIFrame* frame = mFirstChild;
- const nsStyleDisplay* display;
- frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(mFirstChild);
return isBlock == IsBlock();
}
#endif
diff --git a/mozilla/layout/generic/nsLineLayout.cpp b/mozilla/layout/generic/nsLineLayout.cpp
index 9a7cb8d366f..274f605c6b8 100644
--- a/mozilla/layout/generic/nsLineLayout.cpp
+++ b/mozilla/layout/generic/nsLineLayout.cpp
@@ -16,12 +16,38 @@
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
+#include "nsCOMPtr.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsStyleConsts.h"
+#include "nsHTMLContainerFrame.h"
+#include "nsHTMLIIDs.h"
+#include "nsISpaceManager.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIFontMetrics.h"
+#include "nsIRenderingContext.h"
+
+#ifdef DEBUG
+#undef NOISY_HORIZONTAL_ALIGN
+#undef REALLY_NOISY_HORIZONTAL_ALIGN
+#undef NOISY_VERTICAL_ALIGN
+#undef REALLY_NOISY_VERTICAL_ALIGN
+#undef NOISY_REFLOW
+#undef REALLY_NOISY_REFLOW
+#undef NOISY_PUSHING
+#undef REALLY_NOISY_PUSHING
+#define DEBUG_ADD_TEXT
+#else
+#undef NOISY_HORIZONTAL_ALIGN
+#undef REALLY_NOISY_HORIZONTAL_ALIGN
+#undef NOISY_VERTICAL_ALIGN
+#undef REALLY_NOISY_VERTICAL_ALIGN
+#undef NOISY_REFLOW
+#undef REALLY_NOISY_REFLOW
+#undef NOISY_PUSHING
+#undef REALLY_NOISY_PUSHING
+#undef DEBUG_ADD_TEXT
+#endif
nsTextRun::nsTextRun()
{
@@ -44,96 +70,1716 @@ nsTextRun::List(FILE* out, PRInt32 aIndent)
nsAutoString tmp;
text->GetFrameName(tmp);
fputs(tmp, out);
- printf(" ");
+ printf("@%p ", text);
}
fputs(">\n", out);
}
//----------------------------------------------------------------------
+#define PLACED_LEFT 0x1
+#define PLACED_RIGHT 0x2
+
+#define NUM_SPAN_DATA (sizeof(mSpanDataBuf) / sizeof(mSpanDataBuf[0]))
+#define NUM_FRAME_DATA (sizeof(mFrameDataBuf) / sizeof(mFrameDataBuf[0]))
+
nsLineLayout::nsLineLayout(nsIPresContext& aPresContext,
- nsISpaceManager* aSpaceManager)
- : mPresContext(aPresContext)
+ nsISpaceManager* aSpaceManager,
+ const nsHTMLReflowState* aOuterReflowState,
+ PRBool aComputeMaxElementSize)
+ : mPresContext(aPresContext),
+ mSpaceManager(aSpaceManager),
+ mBlockReflowState(aOuterReflowState),
+ mComputeMaxElementSize(aComputeMaxElementSize)
{
- mSpaceManager = aSpaceManager;
- mListPositionOutside = PR_FALSE;
+ // Stash away some style data that we need
+ aOuterReflowState->frame->GetStyleData(eStyleStruct_Text,
+ (const nsStyleStruct*&) mStyleText);
+ mTextAlign = mStyleText->mTextAlign;
+ switch (mStyleText->mWhiteSpace) {
+ case NS_STYLE_WHITESPACE_PRE:
+ case NS_STYLE_WHITESPACE_NOWRAP:
+ mNoWrap = PR_TRUE;
+ break;
+ default:
+ mNoWrap = PR_FALSE;
+ break;
+ }
+ mDirection = aOuterReflowState->mStyleDisplay->mDirection;
+ mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
+ aOuterReflowState->frame);
+ mBRFrame = nsnull;
mLineNumber = 0;
mColumn = 0;
- mUnderstandsWhiteSpace = PR_FALSE;
mEndsInWhiteSpace = PR_TRUE;
+ mUnderstandsWhiteSpace = PR_FALSE;
+ mFirstLetterStyleOK = PR_FALSE;
+ mIsTopOfPage = PR_FALSE;
+ mWasInWord = PR_FALSE;
+ mCanBreakBeforeFrame = PR_FALSE;
+ mUpdatedBand = PR_FALSE;
+ mPlacedFloaters = 0;
+ mTotalPlacedFrames = 0;
+ mTopEdge = mBottomEdge = 0;
+ mReflowTextRuns = nsnull;
+ mTextRun = nsnull;
- mTextRuns = nsnull;
- ResetTextRuns();
-}
+ // XXX Do this on demand to avoid extra setup time
+ // Place the baked-in per-frame-data on the frame free list
+ PerFrameData** pfdp = &mFrameFreeList;
+ PerFrameData* pfd = mFrameDataBuf;
+ PerFrameData* endpfd = pfd + NUM_FRAME_DATA;
+ while (pfd < endpfd) {
+#ifdef DEBUG
+ nsCRT::memset(pfd, 0xEE, sizeof(*pfd));
+#endif
+ *pfdp = pfd;
+ pfdp = &pfd->mNext;
+ pfd++;
+ }
+ *pfdp = nsnull;
-nsLineLayout::~nsLineLayout()
-{
- nsTextRun::DeleteTextRuns(mTextRuns);
-}
+ // XXX Do this on demand to avoid extra setup time
+ // Place the baked-in per-span-data on the span free list
+ PerSpanData** psdp = &mSpanFreeList;
+ PerSpanData* psd = mSpanDataBuf;
+ PerSpanData* endpsd = psd + NUM_SPAN_DATA;
+ while (psd < endpsd) {
+#ifdef DEBUG
+ nsCRT::memset(psd, 0xEE, sizeof(*psd));
+#endif
+ *psdp = psd;
+ psdp = &psd->mNext;
+ psd++;
+ }
+ *psdp = nsnull;
+
+ mCurrentSpan = mRootSpan = mLastSpan = nsnull;
+ mSpanDepth = 0;
-void
-nsLineLayout::ResetTextRuns()
-{
- nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
mTextRunP = &mTextRuns;
mNewTextRun = nsnull;
}
-nsTextRun*
-nsLineLayout::TakeTextRuns()
+nsLineLayout::nsLineLayout(nsIPresContext& aPresContext)
+ : mPresContext(aPresContext)
{
- nsTextRun* result = mTextRuns;
mTextRuns = nsnull;
- ResetTextRuns();
- return result;
+ mTextRunP = &mTextRuns;
+ mNewTextRun = nsnull;
+ mRootSpan = nsnull;
+ mSpanFreeList = nsnull;
+ mFrameFreeList = nsnull;
+}
+
+nsLineLayout::~nsLineLayout()
+{
+ NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user");
+ nsTextRun::DeleteTextRuns(mTextRuns);
+
+ // Free up all of the per-span-data items that were allocated on the heap
+ PerSpanData* psd = mSpanFreeList;
+ while (nsnull != psd) {
+ PerSpanData* nextSpan = psd->mNext;
+ if ((psd < &mSpanDataBuf[0]) || (psd >= &mSpanDataBuf[NUM_SPAN_DATA])) {
+ delete psd;
+ }
+ psd = nextSpan;
+ }
+
+ // Free up all of the per-frame-data items that were allocated on the heap
+ PerFrameData* pfd = mFrameFreeList;
+ while (nsnull != pfd) {
+ PerFrameData* nextFrame = pfd->mNext;
+ if ((pfd < &mFrameDataBuf[0]) || (pfd >= &mFrameDataBuf[NUM_FRAME_DATA])) {
+ delete pfd;
+ }
+ pfd = nextFrame;
+ }
}
void
-nsLineLayout::EndTextRun()
+nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
+ nscoord aWidth, nscoord aHeight,
+ PRBool aIsTopOfPage)
{
- mNewTextRun = nsnull;
+ NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
+#ifdef DEBUG
+ if ((aWidth > 200000) && (aWidth != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": Init: bad caller: width WAS %d(0x%x)\n",
+ aWidth, aWidth);
+ aWidth = NS_UNCONSTRAINEDSIZE;
+ }
+ if ((aHeight > 200000) && (aHeight != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": Init: bad caller: height WAS %d(0x%x)\n",
+ aHeight, aHeight);
+ aHeight = NS_UNCONSTRAINEDSIZE;
+ }
+#endif
+#ifdef NOISY_REFLOW
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": BeginLineReflow: %d,%d,%d,%d %s\n",
+ aX, aY, aWidth, aHeight,
+ aIsTopOfPage ? "top-of-page" : "");
+#endif
+
+ mBRFrame = nsnull;
+ mColumn = 0;
+ mEndsInWhiteSpace = PR_TRUE;
+ mUnderstandsWhiteSpace = PR_FALSE;
+ mFirstLetterStyleOK = PR_FALSE;
+ mIsTopOfPage = aIsTopOfPage;
+ mCanBreakBeforeFrame = PR_FALSE;
+ mUpdatedBand = PR_FALSE;
+ mPlacedFloaters = 0;
+ mTotalPlacedFrames = 0;
+ mSpanDepth = 0;
+ mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
+
+ ForgetWordFrames();
+
+ PerSpanData* psd;
+ NewPerSpanData(&psd);
+ mCurrentSpan = mRootSpan = psd;
+ psd->mReflowState = mBlockReflowState;
+ psd->mLeftEdge = aX;
+ psd->mX = aX;
+ if (NS_UNCONSTRAINEDSIZE == aWidth) {
+ psd->mRightEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ psd->mRightEdge = aX + aWidth;
+ }
+
+ mTopEdge = aY;
+ if (NS_UNCONSTRAINEDSIZE == aHeight) {
+ mBottomEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ mBottomEdge = aY + aHeight;
+ }
+}
+
+void
+nsLineLayout::EndLineReflow()
+{
+#ifdef NOISY_REFLOW
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": EndLineReflow: width=%d\n", mRootSpan->mX - mRootSpan->mLeftEdge);
+#endif
+
+ PerSpanData* psd = mRootSpan;
+ while (nsnull != psd) {
+ // Put frames on free list
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ PerFrameData* nextFrame = pfd->mNext;
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ pfd = nextFrame;
+ }
+
+ // Put span on free list
+ PerSpanData* nextSpan = psd->mNext;
+ psd->mNext = mSpanFreeList;
+ mSpanFreeList = psd;
+ psd = nextSpan;
+ }
+ mCurrentSpan = mRootSpan = mLastSpan = nsnull;
+}
+
+void
+nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
+ nscoord aWidth, nscoord aHeight,
+ PRBool aPlacedLeftFloater)
+{
+ PerSpanData* psd = mRootSpan;
+ NS_PRECONDITION(psd->mX == psd->mLeftEdge, "update-band called late");
+#ifdef DEBUG
+ if ((aWidth > 200000) && (aWidth != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": UpdateBand: bad caller: width WAS %d(0x%x)\n",
+ aWidth, aWidth);
+ aWidth = NS_UNCONSTRAINEDSIZE;
+ }
+ if ((aHeight > 200000) && (aHeight != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": UpdateBand: bad caller: height WAS %d(0x%x)\n",
+ aHeight, aHeight);
+ aHeight = NS_UNCONSTRAINEDSIZE;
+ }
+#endif
+#ifdef NOISY_REFLOW
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": UpdateBand: %d,%d,%d,%d %s\n",
+ aX, aY, aWidth, aHeight,
+ aPlacedLeftFloater ? "placed-left-floater" : "");
+#endif
+
+ psd->mLeftEdge = aX;
+ psd->mX = aX;
+ if (NS_UNCONSTRAINEDSIZE == aWidth) {
+ psd->mRightEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ psd->mRightEdge = aX + aWidth;
+ }
+ mTopEdge = aY;
+ if (NS_UNCONSTRAINEDSIZE == aHeight) {
+ mBottomEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ mBottomEdge = aY + aHeight;
+ }
+ mUpdatedBand = PR_TRUE;
+ mPlacedFloaters |= (aPlacedLeftFloater ? PLACED_LEFT : PLACED_RIGHT);
+}
+
+void
+nsLineLayout::UpdateFrames()
+{
+ if (NS_STYLE_DIRECTION_LTR == mDirection) {
+ if (PLACED_LEFT & mPlacedFloaters) {
+ // Note: Only adjust the outermost frames (the ones that are
+ // direct children of the block), not the ones in the child
+ // spans. The reason is simple: the frames in the spans have
+ // coordinates local to their parent therefore they are moved
+ // when their parent span is moved.
+ PerSpanData* psd = mRootSpan;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ pfd->mBounds.x = psd->mX;
+ pfd = pfd->mNext;
+ }
+ }
+ }
+ else if (PLACED_RIGHT & mPlacedFloaters) {
+ // XXX handle DIR=right-to-left
+ }
}
nsresult
-nsLineLayout::AddText(nsIFrame* aTextFrame)
+nsLineLayout::NewPerSpanData(PerSpanData** aResult)
{
- if (nsnull == mNewTextRun) {
- mNewTextRun = new nsTextRun();
- if (nsnull == mNewTextRun) {
+ PerSpanData* psd = mSpanFreeList;
+ if (nsnull == psd) {
+ psd = new PerSpanData;
+ if (nsnull == psd) {
return NS_ERROR_OUT_OF_MEMORY;
}
- *mTextRunP = mNewTextRun;
- mTextRunP = &mNewTextRun->mNext;
}
- mNewTextRun->mArray.AppendElement(aTextFrame);
- return NS_OK;/* XXX */
+ else {
+ mSpanFreeList = psd->mNext;
+ }
+ psd->mParent = nsnull;
+ psd->mFrame = nsnull;
+ psd->mFirstFrame = nsnull;
+ psd->mLastFrame = nsnull;
+ psd->mNext = nsnull;
+
+ // Link new span to the end of the span list
+ if (nsnull == mLastSpan) {
+ psd->mPrev = nsnull;
+ }
+ else {
+ mLastSpan->mNext = psd;
+ psd->mPrev = mLastSpan;
+ }
+ mLastSpan = psd;
+
+ *aResult = psd;
+ return NS_OK;
}
-nsTextRun*
-nsLineLayout::FindTextRunFor(nsIFrame* aFrame)
+nsresult
+nsLineLayout::BeginSpan(nsIFrame* aFrame,
+ const nsHTMLReflowState* aSpanReflowState,
+ nscoord aLeftEdge,
+ nscoord aRightEdge)
{
- // Only the first-in-flows are present in the text run list so
- // backup from the argument frame to its first-in-flow.
- for (;;) {
- nsIFrame* prevInFlow;
- aFrame->GetPrevInFlow(&prevInFlow);
- if (nsnull == prevInFlow) {
- break;
+#ifdef NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth+1);
+ nsFrame::ListTag(stdout, aFrame);
+ printf(": BeginSpan leftEdge=%d rightEdge=%d\n", aLeftEdge, aRightEdge);
+#endif
+
+ PerSpanData* psd;
+ nsresult rv = NewPerSpanData(&psd);
+ if (NS_SUCCEEDED(rv)) {
+ // Link up span frame's pfd to point to its child span data
+ PerFrameData* pfd = mCurrentSpan->mLastFrame;
+ NS_ASSERTION(pfd->mFrame == aFrame, "huh?");
+ pfd->mSpan = psd;
+
+ // Init new span
+ psd->mFrame = pfd;
+ psd->mParent = mCurrentSpan;
+ psd->mReflowState = aSpanReflowState;
+ psd->mLeftEdge = aLeftEdge;
+ psd->mX = aLeftEdge;
+ psd->mRightEdge = aRightEdge;
+
+ // Switch to new span
+ mCurrentSpan = psd;
+ mSpanDepth++;
+ }
+ return rv;
+}
+
+void
+nsLineLayout::EndSpan(nsIFrame* aFrame,
+ nsSize& aSizeResult,
+ nsSize* aMaxElementSize)
+{
+ NS_ASSERTION(mSpanDepth > 0, "end-span without begin-span");
+#ifdef NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ nsFrame::ListTag(stdout, aFrame);
+ printf(": EndSpan width=%d\n", mCurrentSpan->mX - mCurrentSpan->mLeftEdge);
+#endif
+ PerSpanData* psd = mCurrentSpan;
+ nscoord width = 0;
+ nscoord maxHeight = 0;
+ nscoord maxElementWidth = 0;
+ nscoord maxElementHeight = 0;
+ if (nsnull != psd->mLastFrame) {
+ width = psd->mX - psd->mLeftEdge;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
+
+ // Compute max-element-size if necessary
+ if (aMaxElementSize) {
+ nscoord mw = pfd->mMaxElementSize.width +
+ pfd->mMargin.left + pfd->mMargin.right;
+ if (maxElementWidth < mw) {
+ maxElementWidth = mw;
+ }
+ nscoord mh = pfd->mMaxElementSize.height +
+ pfd->mMargin.top + pfd->mMargin.bottom;
+ if (maxElementHeight < mh) {
+ maxElementHeight = mh;
+ }
+ }
+ pfd = pfd->mNext;
}
- aFrame = prevInFlow;
+ }
+ aSizeResult.width = width;
+ aSizeResult.height = maxHeight;
+ if (aMaxElementSize) {
+ aMaxElementSize->width = maxElementWidth;
+ aMaxElementSize->height = maxElementHeight;
}
- // Now look for the frame in each run
- nsTextRun* run = mReflowTextRuns;
- while (nsnull != run) {
- PRInt32 ix = run->mArray.IndexOf(aFrame);
- if (ix >= 0) {
- return run;
- }
- run = run->mNext;
+ mSpanDepth--;
+ mCurrentSpan->mReflowState = nsnull; // no longer valid so null it out!
+ mCurrentSpan = mCurrentSpan->mParent;
+}
+
+PRInt32
+nsLineLayout::GetCurrentSpanCount() const
+{
+ NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
+ PRInt32 count = 0;
+ PerFrameData* pfd = mRootSpan->mFirstFrame;
+ while (nsnull != pfd) {
+ count++;
+ pfd = pfd->mNext;
+ }
+ return count;
+}
+
+void
+nsLineLayout::SplitLineTo(PRInt32 aNewCount)
+{
+ NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
+
+#ifdef REALLY_NOISY_PUSHING
+ printf("SplitLineTo %d (current count=%d); before:\n", aNewCount,
+ GetCurrentSpanCount());
+ DumpPerSpanData(mRootSpan, 1);
+#endif
+ PerSpanData* psd = mRootSpan;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (--aNewCount == 0) {
+ // Truncate list at pfd (we keep pfd, but anything following is freed)
+ PerFrameData* next = pfd->mNext;
+ pfd->mNext = nsnull;
+ psd->mLastFrame = pfd;
+
+ // Now release all of the frames following pfd
+ pfd = next;
+ while (nsnull != pfd) {
+ next = pfd->mNext;
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ if (nsnull != pfd->mSpan) {
+ FreeSpan(pfd->mSpan);
+ }
+ pfd = next;
+ }
+ break;
+ }
+ pfd = pfd->mNext;
+ }
+#ifdef NOISY_PUSHING
+ printf("SplitLineTo %d (current count=%d); after:\n", aNewCount,
+ GetCurrentSpanCount());
+ DumpPerSpanData(mRootSpan, 1);
+#endif
+}
+
+void
+nsLineLayout::PushFrame(nsIFrame* aFrame)
+{
+ PerSpanData* psd = mCurrentSpan;
+ NS_ASSERTION(psd->mLastFrame->mFrame == aFrame, "pushing non-last frame");
+
+#ifdef REALLY_NOISY_PUSHING
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("PushFrame %p, before:\n", psd);
+ DumpPerSpanData(psd, 1);
+#endif
+
+ // Take the last frame off of the span's frame list
+ PerFrameData* pfd = psd->mLastFrame;
+ if (pfd == psd->mFirstFrame) {
+ // We are pushing away the only frame...empty the list
+ psd->mFirstFrame = nsnull;
+ psd->mLastFrame = nsnull;
+ }
+ else {
+ PerFrameData* prevFrame = pfd->mPrev;
+ prevFrame->mNext = nsnull;
+ psd->mLastFrame = prevFrame;
+ }
+
+ // Now free it, and if it has a span, free that too
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ if (nsnull != pfd->mSpan) {
+ FreeSpan(pfd->mSpan);
+ }
+#ifdef NOISY_PUSHING
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("PushFrame: %p after:\n", psd);
+ DumpPerSpanData(psd, 1);
+#endif
+}
+
+void
+nsLineLayout::FreeSpan(PerSpanData* psd)
+{
+ // Take span out of the list
+ if (nsnull != psd->mNext) psd->mNext->mPrev = psd->mPrev;
+ if (nsnull != psd->mPrev) psd->mPrev->mNext = psd->mNext;
+
+ // Free its frames
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (nsnull != pfd->mSpan) {
+ FreeSpan(pfd->mSpan);
+ }
+ PerFrameData* next = pfd->mNext;
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ pfd = next;
+ }
+}
+
+PRBool
+nsLineLayout::IsZeroHeight()
+{
+ PerSpanData* psd = mCurrentSpan;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (0 != pfd->mBounds.height) {
+ return PR_FALSE;
+ }
+ pfd = pfd->mNext;
+ }
+ return PR_TRUE;
+}
+
+nsresult
+nsLineLayout::NewPerFrameData(PerFrameData** aResult)
+{
+ PerFrameData* pfd = mFrameFreeList;
+ if (nsnull == pfd) {
+ pfd = new PerFrameData;
+ if (nsnull == pfd) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ mFrameFreeList = pfd->mNext;
+ }
+ pfd->mSpan = nsnull;
+ pfd->mNext = nsnull;
+ *aResult = pfd;
+ return NS_OK;
+}
+
+nsresult
+nsLineLayout::ReflowFrame(nsIFrame* aFrame,
+ nsIFrame** aNextRCFrame,
+ nsReflowStatus& aReflowStatus)
+{
+ PerFrameData* pfd;
+ nsresult rv = NewPerFrameData(&pfd);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ PerSpanData* psd = mCurrentSpan;
+ psd->AppendFrame(pfd);
+
+#ifdef REALLY_NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("%p: Begin ReflowFrame pfd=%p ", psd, pfd);
+ nsFrame::ListTag(stdout, aFrame);
+ printf("\n");
+#endif
+
+ // Compute the available size for the frame. This available width
+ // includes room for the side margins and for the text-indent.
+ nsSize availSize;
+ if (NS_UNCONSTRAINEDSIZE == psd->mRightEdge) {
+ availSize.width = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.width = psd->mRightEdge - psd->mX;
+ if (mNoWrap) {
+ // XXX Shouldn't this use NS_UNCONSTRAINEDSIZE?
+ availSize.width = psd->mReflowState->availableWidth;
+ }
+ }
+ if (NS_UNCONSTRAINEDSIZE == mBottomEdge) {
+ availSize.height = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.height = mBottomEdge - mTopEdge;
+ }
+
+ // Get reflow reason set correctly. It's possible that a child was
+ // created and then it was decided that it could not be reflowed
+ // (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 reason = eReflowReason_Resize;
+ nsFrameState state;
+ aFrame->GetFrameState(&state);
+ if (NS_FRAME_FIRST_REFLOW & state) {
+ reason = eReflowReason_Initial;
+ }
+ else if (*aNextRCFrame == aFrame) {
+ reason = eReflowReason_Incremental;
+ // Make sure we only incrementally reflow once
+ *aNextRCFrame = nsnull;
+ }
+
+ // Setup reflow state for reflowing the frame
+ nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState, aFrame,
+ availSize, reason);
+ reflowState.lineLayout = this;
+ reflowState.isTopOfPage = mIsTopOfPage;
+ mUnderstandsWhiteSpace = PR_FALSE;
+ mCanBreakBeforeFrame = mTotalPlacedFrames > 0;
+
+ // Stash copies of some of the computed state away for later
+ // (vertical alignment, for example)
+ pfd->mFrame = aFrame;
+ pfd->mMargin = reflowState.computedMargin;
+ pfd->mBorderPadding = reflowState.mComputedBorderPadding;
+ pfd->mFrameType = reflowState.frameType;
+ pfd->mRelativePos =
+ reflowState.mStylePosition->mPosition == NS_STYLE_POSITION_RELATIVE;
+ if (pfd->mRelativePos) {
+ pfd->mOffsets = reflowState.computedOffsets;
+ }
+
+ // Capture this state *before* we reflow the frame in case it clears
+ // the state out. We need to know how to treat the current frame
+ // when breaking.
+ mWasInWord = InWord();
+
+ // Apply left margins (as appropriate) to the frame computing the
+ // new starting x,y coordinates for the frame.
+ ApplyLeftMargin(pfd, reflowState);
+
+ // Let frame know that are reflowing it
+ nscoord x = pfd->mBounds.x;
+ nscoord y = pfd->mBounds.y;
+ nsIHTMLReflow* htmlReflow;
+
+ aFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
+ htmlReflow->WillReflow(mPresContext);
+
+ // Adjust spacemanager coordinate system for the frame. The
+ // spacemanager coordinates are inside the current spans
+ // border+padding, but the x/y coordinates are not (recall that
+ // frame coordinates are relative to the parents origin and that the
+ // parents border/padding is inside the parent
+ // frame. Therefore we have to subtract out the parents
+ // border+padding before translating.
+ nsSize innerMaxElementSize;
+ nsHTMLReflowMetrics metrics(mComputeMaxElementSize
+ ? &innerMaxElementSize
+ : nsnull);
+#ifdef DEBUG
+ if (mComputeMaxElementSize) {
+ metrics.maxElementSize->width = nscoord(0xdeadbeef);
+ metrics.maxElementSize->height = nscoord(0xdeadbeef);
+ }
+#endif
+ nscoord tx = x - psd->mReflowState->mComputedBorderPadding.left;
+ nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
+ mSpaceManager->Translate(tx, ty);
+ htmlReflow->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
+ mSpaceManager->Translate(-tx, -ty);
+
+#ifdef DEBUG_kipp
+ NS_ASSERTION((metrics.width > -200000) && (metrics.width < 200000), "oy");
+ NS_ASSERTION((metrics.height > -200000) && (metrics.height < 200000), "oy");
+#endif
+#ifdef DEBUG
+ if (mComputeMaxElementSize &&
+ ((nscoord(0xdeadbeef) == metrics.maxElementSize->width) ||
+ (nscoord(0xdeadbeef) == metrics.maxElementSize->height))) {
+ printf("nsLineLayout: ");
+ nsFrame::ListTag(stdout, aFrame);
+ printf(" didn't set max-element-size!\n");
+ metrics.maxElementSize->width = 0;
+ metrics.maxElementSize->height = 0;
+ }
+#endif
+
+ aFrame->GetFrameState(&state);
+ if (NS_FRAME_OUTSIDE_CHILDREN & state) {
+ pfd->mCombinedArea = metrics.mCombinedArea;
+ }
+ else {
+ pfd->mCombinedArea.x = 0;
+ pfd->mCombinedArea.y = 0;
+ pfd->mCombinedArea.width = metrics.width;
+ pfd->mCombinedArea.height = metrics.height;
+ }
+ pfd->mBounds.width = metrics.width;
+ pfd->mBounds.height = metrics.height;
+ if (mComputeMaxElementSize) {
+ pfd->mMaxElementSize = *metrics.maxElementSize;
+ }
+
+ // Now that frame has been reflowed at least one time make sure that
+ // the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an
+ // initial reflow reason again.
+ if (eReflowReason_Initial == reason) {
+ aFrame->GetFrameState(&state);
+ aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
+ }
+
+ if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
+ // If frame is complete and has a next-in-flow, we need to delete
+ // them now. Do not do this when a break-before is signaled because
+ // the frame is going to get reflowed again (and may end up wanting
+ // a next-in-flow where it ends up).
+ if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
+ nsIFrame* kidNextInFlow;
+ aFrame->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)
+ nsHTMLContainerFrame* parent;
+ aFrame->GetParent((nsIFrame**) &parent);
+ parent->DeleteChildsNextInFlow(mPresContext, aFrame);
+ }
+ }
+
+ // See if we can place the frame. If we can't fit it, then we
+ // return now.
+ if (CanPlaceFrame(pfd, reflowState, metrics, aReflowStatus)) {
+ // Place the frame, updating aBounds with the final size and
+ // location. Then apply the bottom+right margins (as
+ // appropriate) to the frame.
+ PlaceFrame(pfd, metrics);
+ PerSpanData* span = pfd->mSpan;
+ if (span) {
+ // The frame we just finished reflowing is an inline
+ // container. It needs its child frames vertically aligned,
+ // so do most of it now.
+ VerticalAlignFrames(span);
+ }
+ }
+ else {
+ PushFrame(aFrame);
+ }
+ }
+ else {
+ PushFrame(aFrame);
+ }
+
+#ifdef REALLY_NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("End ReflowFrame ");
+ nsFrame::ListTag(stdout, aFrame);
+ printf(" status=%x\n", aReflowStatus);
+#endif
+ return rv;
+}
+
+void
+nsLineLayout::ApplyLeftMargin(PerFrameData* pfd,
+ nsHTMLReflowState& aReflowState)
+{
+ // If this is the first frame in the block, and its the first line
+ // of a block then see if the text-indent property amounts to
+ // anything.
+ nscoord indent = 0;
+ if (InBlockContext() && (0 == mLineNumber) &&
+ (0 == mTotalPlacedFrames)) {
+ nsStyleUnit unit = mStyleText->mTextIndent.GetUnit();
+ if (eStyleUnit_Coord == unit) {
+ indent = mStyleText->mTextIndent.GetCoordValue();
+ }
+ else if (eStyleUnit_Percent == unit) {
+ nscoord width =
+ nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState->parentReflowState);
+ if (0 != width) {
+ indent = nscoord(mStyleText->mTextIndent.GetPercentValue() * width);
+ }
+ }
+ }
+
+ // Adjust available width to account for the indent and the margins
+ aReflowState.availableWidth -= indent + pfd->mMargin.left +
+ pfd->mMargin.right;
+
+ // NOTE: While the x coordinate remains relative to the parent span,
+ // the y coordinate is fixed at the top edge for the line. During
+ // VerticalAlignFrames we will repair this so that the y coordinate
+ // is properly set and relative to the appropriate span.
+ PerSpanData* psd = mCurrentSpan;
+ pfd->mBounds.x = psd->mX + indent;
+ pfd->mBounds.y = mTopEdge;
+
+ // Compute left margin
+ nsIFrame* prevInFlow;
+ switch (aReflowState.mStyleDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ case NS_STYLE_FLOAT_RIGHT:
+ // When something is floated, its margins are applied there
+ // not here.
+ break;
+
+ case NS_STYLE_FLOAT_NONE:
+ // Only apply left-margin on the first-in flow for inline frames
+ pfd->mFrame->GetPrevInFlow(&prevInFlow);
+ if (nsnull != prevInFlow) {
+ // Zero this out so that when we compute the max-element-size
+ // of the frame we will properly avoid adding in the left
+ // margin.
+ pfd->mMargin.left = 0;
+ }
+ pfd->mBounds.x += pfd->mMargin.left;
+ break;
+ }
+}
+
+/**
+ * See if the frame can be placed now that we know it's desired size.
+ * We can always place the frame if the line is empty. Note that we
+ * know that the reflow-status is not a break-before because if it was
+ * ReflowFrame above would have returned false, preventing this method
+ * from being called. The logic in this method assumes that.
+ *
+ * Note that there is no check against the Y coordinate because we
+ * assume that the caller will take care of that.
+ */
+PRBool
+nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
+ const nsHTMLReflowState& aReflowState,
+ nsHTMLReflowMetrics& aMetrics,
+ nsReflowStatus& aStatus)
+{
+ // Compute right margin to use
+ nscoord rightMargin = 0;
+ if (0 != pfd->mBounds.width) {
+ switch (aReflowState.mStyleDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ case NS_STYLE_FLOAT_RIGHT:
+ // When something is floated, its margins are applied there
+ // not here.
+ break;
+
+ case NS_STYLE_FLOAT_NONE:
+ // Only apply right margin for the last-in-flow
+ if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
+ // Zero this out so that when we compute the
+ // max-element-size of the frame we will properly avoid
+ // adding in the right margin.
+ pfd->mMargin.right = 0;
+ }
+ rightMargin = pfd->mMargin.right;
+ break;
+ }
+ }
+ pfd->mMargin.right = rightMargin;
+
+ // Set outside to PR_TRUE if the result of the reflow leads to the
+ // frame sticking outside of our available area.
+ PerSpanData* psd = mCurrentSpan;
+ PRBool outside = pfd->mBounds.XMost() + rightMargin > psd->mRightEdge;
+
+ // There are several special conditions that exist which allow us to
+ // ignore outside. If they are true then we can place frame and
+ // return PR_TRUE.
+ if (!mCanBreakBeforeFrame || mWasInWord || mNoWrap) {
+ return PR_TRUE;
+ }
+
+ if (0 == pfd->mMargin.left + pfd->mBounds.width + rightMargin) {
+ // Empty frames always fit right where they are
+ return PR_TRUE;
+ }
+
+ if (pfd == mCurrentSpan->mFirstFrame) {
+ return PR_TRUE;
+ }
+
+ if (outside) {
+ aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/**
+ * Place the frame. Update running counters.
+ */
+void
+nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
+{
+ // If frame is zero width then do not apply its left and right margins.
+ PerSpanData* psd = mCurrentSpan;
+ PRBool emptyFrame = PR_FALSE;
+ if ((0 == pfd->mBounds.width) && (0 == pfd->mBounds.height)) {
+ pfd->mBounds.x = psd->mX;
+ pfd->mBounds.y = mTopEdge;
+ emptyFrame = PR_TRUE;
+ }
+
+ // Record ascent and update max-ascent and max-descent values
+ pfd->mAscent = aMetrics.ascent;
+ pfd->mDescent = aMetrics.descent;
+ pfd->mCarriedOutTopMargin = aMetrics.mCarriedOutTopMargin;
+ pfd->mCarriedOutBottomMargin = aMetrics.mCarriedOutBottomMargin;
+
+ // If the band was updated during the reflow of that frame then we
+ // need to adjust any prior frames that were reflowed.
+ if (mUpdatedBand && InBlockContext()) {
+ UpdateFrames();
+ mUpdatedBand = PR_FALSE;
+ }
+
+ // Advance to next X coordinate
+ psd->mX = pfd->mBounds.XMost() + pfd->mMargin.right;
+
+ // If the frame is a not aware of white-space and it takes up some
+ // area, disable leading white-space compression for the next frame
+ // to be reflowed.
+ if (!mUnderstandsWhiteSpace && !emptyFrame) {
+ mEndsInWhiteSpace = PR_FALSE;
+ }
+
+ // Compute the bottom margin to apply. Note that the margin only
+ // applies if the frame ends up with a non-zero height.
+ if (!emptyFrame) {
+ // Inform line layout that we have placed a non-empty frame
+ mTotalPlacedFrames++;
+ }
+}
+
+nsresult
+nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
+ const nsHTMLReflowMetrics& aMetrics)
+{
+ NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
+
+ PerFrameData* pfd;
+ nsresult rv = NewPerFrameData(&pfd);
+ if (NS_SUCCEEDED(rv)) {
+ mRootSpan->AppendFrame(pfd);
+ pfd->mFrame = aFrame;
+ pfd->mMargin.SizeTo(0, 0, 0, 0);
+ pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
+ pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
+ pfd->mRelativePos = PR_FALSE;
+ pfd->mAscent = aMetrics.ascent;
+ pfd->mDescent = aMetrics.descent;
+ aFrame->GetRect(pfd->mBounds); // y value is irrelevant
+ pfd->mCombinedArea = aMetrics.mCombinedArea;
+ if (mComputeMaxElementSize) {
+ pfd->mMaxElementSize.SizeTo(aMetrics.width, aMetrics.height);
+ }
+ }
+ return rv;
+}
+
+#ifdef DEBUG
+void
+nsLineLayout::DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent)
+{
+ nsFrame::IndentBy(stdout, aIndent);
+ printf("%p: left=%d x=%d right=%d prev/next=%p/%p\n", psd, psd->mLeftEdge,
+ psd->mX, psd->mRightEdge, psd->mPrev, psd->mNext);
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ nsFrame::IndentBy(stdout, aIndent+1);
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(" %d,%d,%d,%d\n", pfd->mBounds.x, pfd->mBounds.y,
+ pfd->mBounds.width, pfd->mBounds.height);
+ if (pfd->mSpan) {
+ DumpPerSpanData(pfd->mSpan, aIndent + 1);
+ }
+ pfd = pfd->mNext;
+ }
+}
+#endif
+
+#define VALIGN_OTHER 0
+#define VALIGN_TOP 1
+#define VALIGN_BOTTOM 2
+
+void
+nsLineLayout::VerticalAlignFrames(nsRect& aLineBoxResult,
+ nsSize& aMaxElementSizeResult)
+{
+ // Synthesize a PerFrameData for the block frame
+ PerFrameData rootPFD;
+ rootPFD.mFrame = mBlockReflowState->frame;
+ rootPFD.mFrameType = mBlockReflowState->frameType;
+ rootPFD.mAscent = 0;
+ rootPFD.mDescent = 0;
+ mRootSpan->mFrame = &rootPFD;
+
+ // Partially place the children of the block frame. The baseline for
+ // this operation is set to zero so that the y coordinates for all
+ // of the placed children will be relative to there.
+ PerSpanData* psd = mRootSpan;
+ VerticalAlignFrames(psd);
+
+ // Compute the line-height. The line-height will be the larger of:
+ //
+ // [1] maxY - minY (the distance between the highest childs top edge
+ // and the lowest childs bottom edge)
+ //
+ // [2] the maximum logical box height (since not every frame may have
+ // participated in #1; for example: top/bottom aligned frames)
+ //
+ // [3] the minimum line height (line-height property set on the
+ // block frame)
+ nscoord lineHeight = psd->mMaxY - psd->mMinY;
+
+ // Now that the line-height is computed, we need to know where the
+ // baseline is in the line. Position baseline so that mMinY is just
+ // inside the top of the line box.
+ nscoord baselineY;
+ if (psd->mMinY < 0) {
+ baselineY = mTopEdge - psd->mMinY;
+ }
+ else {
+ baselineY = mTopEdge;
+ }
+
+ // It's possible that the line-height isn't tall enough because of
+ // the blocks minimum line-height.
+ if (0 != lineHeight) {
+ // If line contains nothing but empty boxes that have no height
+ // then don't apply the min-line-height.
+ //
+ // Note: This is how we hide lines that contain nothing but
+ // compressed whitespace.
+ if (lineHeight < mMinLineHeight) {
+ // Apply half of the extra space to the top of the line as top
+ // leading
+ nscoord extra = mMinLineHeight - lineHeight;
+ baselineY += extra / 2;
+ lineHeight = mMinLineHeight;
+ }
+ }
+
+ // It's also possible that the line-height isn't tall enough because
+ // of top/bottom aligned elements that were not accounted for in
+ // min/max Y.
+ //
+ // The CSS2 spec doesn't really say what happens when to the
+ // baseline in this situations. What we do is if the largest top
+ // aligned box height is greater than the line-height then we leave
+ // the baseline alone. If the largest bottom aligned box is greater
+ // than the line-height then we slide the baseline down by the extra
+ // amount.
+ //
+ // Navigator 4 gives precedence to the first top/bottom aligned
+ // object. We just let bottom aligned objects win.
+ if (lineHeight < mMaxBottomBoxHeight) {
+ // When the line is shorter than the maximum top aligned box
+ nscoord extra = mMaxBottomBoxHeight - lineHeight;
+ baselineY += extra;
+ lineHeight = mMaxBottomBoxHeight;
+ }
+ if (lineHeight < mMaxTopBoxHeight) {
+ lineHeight = mMaxTopBoxHeight;
+ }
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ==> lineHeight=%d baselineY=%d\n", lineHeight, baselineY);
+#endif
+
+ // Now position all of the frames in the root span. We will also
+ // recurse over the child spans and place any top/bottom aligned
+ // frames we find.
+ // XXX PERFORMANCE: set a bit per-span to avoid the extra work
+ // (propogate it upward too)
+ PerFrameData* pfd = psd->mFirstFrame;
+ nscoord maxElementWidth = 0;
+ nscoord maxElementHeight = 0;
+ while (nsnull != pfd) {
+ // Compute max-element-size if necessary
+ if (mComputeMaxElementSize) {
+ nscoord mw = pfd->mMaxElementSize.width +
+ pfd->mMargin.left + pfd->mMargin.right;
+ if (maxElementWidth < mw) {
+ maxElementWidth = mw;
+ }
+ nscoord mh = pfd->mMaxElementSize.height +
+ pfd->mMargin.top + pfd->mMargin.bottom;
+ if (maxElementHeight < mh) {
+ maxElementHeight = mh;
+ }
+ }
+ PerSpanData* span = pfd->mSpan;
+ switch (pfd->mVerticalAlign) {
+ case VALIGN_TOP:
+ if (span) {
+ pfd->mBounds.y = mTopEdge - pfd->mBorderPadding.top +
+ span->mTopLeading;
+ }
+ else {
+ pfd->mBounds.y = mTopEdge + pfd->mMargin.top;
+ }
+ break;
+ case VALIGN_BOTTOM:
+ if (span) {
+ // Compute bottom leading
+ pfd->mBounds.y = mTopEdge + lineHeight -
+ pfd->mBounds.height + pfd->mBorderPadding.bottom -
+ span->mBottomLeading;
+ }
+ else {
+ pfd->mBounds.y = mTopEdge + lineHeight - pfd->mMargin.bottom -
+ pfd->mBounds.height;
+ }
+ break;
+ case VALIGN_OTHER:
+ pfd->mBounds.y += baselineY;
+ break;
+ }
+ pfd->mFrame->SetRect(pfd->mBounds);
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(": y=%d\n", pfd->mBounds.y);
+#endif
+ if (span) {
+ nscoord distanceFromTop = pfd->mBounds.y - mTopEdge;
+ PlaceTopBottomFrames(span, distanceFromTop, lineHeight);
+ }
+ pfd = pfd->mNext;
+ }
+
+ // Fill in returned line-box and max-element-size data
+ aLineBoxResult.x = psd->mLeftEdge;
+ aLineBoxResult.y = mTopEdge;
+ aLineBoxResult.width = psd->mX - psd->mLeftEdge;
+ aLineBoxResult.height = lineHeight;
+ aMaxElementSizeResult.width = maxElementWidth;
+ aMaxElementSizeResult.height = maxElementHeight;
+
+ // Undo root-span mFrame pointer to prevent brane damage later on...
+ mRootSpan->mFrame = nsnull;
+}
+
+void
+nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd,
+ nscoord aDistanceFromTop,
+ nscoord aLineHeight)
+{
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ PerSpanData* span = pfd->mSpan;
+ switch (pfd->mVerticalAlign) {
+ case VALIGN_TOP:
+ if (span) {
+ pfd->mBounds.y = -aDistanceFromTop - pfd->mBorderPadding.top +
+ span->mTopLeading;
+ }
+ else {
+ pfd->mBounds.y = -aDistanceFromTop + pfd->mMargin.top;
+ }
+ pfd->mFrame->SetRect(pfd->mBounds);
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(": y=%d dTop=%d [bp.top=%d topLeading=%d]\n",
+ pfd->mBounds.y, aDistanceFromTop,
+ span ? pfd->mBorderPadding.top : 0,
+ span ? span->mTopLeading : 0);
+#endif
+ break;
+ case VALIGN_BOTTOM:
+ if (span) {
+ // Compute bottom leading
+ pfd->mBounds.y = -aDistanceFromTop + aLineHeight -
+ pfd->mBounds.height + pfd->mBorderPadding.bottom -
+ span->mBottomLeading;
+ }
+ else {
+ pfd->mBounds.y = -aDistanceFromTop + aLineHeight -
+ pfd->mMargin.bottom - pfd->mBounds.height;
+ }
+ pfd->mFrame->SetRect(pfd->mBounds);
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(": y=%d\n", pfd->mBounds.y);
+#endif
+ break;
+ }
+ if (span) {
+ nscoord distanceFromTop = distanceFromTop + pfd->mBounds.y;
+ PlaceTopBottomFrames(span, distanceFromTop, aLineHeight);
+ }
+ pfd = pfd->mNext;
+ }
+}
+
+// Vertically place frames within a given span. Note: this doesn't
+// place top/bottom aligned frames as those have to wait until the
+// entire line box height is known. This is called after the span
+// frame has finished being reflowed so that we know its height.
+void
+nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
+{
+ // Get parent frame info
+ PerFrameData* parentPFD = psd->mFrame;
+ nsIFrame* parentFrame = parentPFD->mFrame;
+
+ // Get the parent frame's font for all of the frames in this span
+ const nsStyleFont* parentFont;
+ parentFrame->GetStyleData(eStyleStruct_Font,
+ (const nsStyleStruct*&)parentFont);
+ nsIRenderingContext* rc = mBlockReflowState->rendContext;
+ rc->SetFont(parentFont->mFont);
+ nsIFontMetrics* fm;
+ rc->GetFontMetrics(fm);
+
+
+ // Setup baselineY, minY, and maxY
+ nscoord baselineY, minY, maxY;
+ if (psd == mRootSpan) {
+ // Use a zero baselineY since we don't yet know where the baseline
+ // will be (until we know how tall the line is; then we will
+ // know). In addition, use extreme values for the minY and maxY
+ // values so that only the child frames will impact their values
+ // (since these are children of the block, there is no span box to
+ // provide initial values).
+ baselineY = 0;
+ minY = 0;
+ maxY = 0;
+#ifdef NOISY_VERTICAL_ALIGN
+ nsFrame::ListTag(stdout, parentFrame);
+ printf(": pass1 valign frames: topEdge=%d minLineHeight=%d\n",
+ mTopEdge, mMinLineHeight);
+#endif
+ }
+ else if (0 != parentPFD->mBounds.height) {
+ // Compute the logical height for this span. Also compute the top
+ // leading.
+ nscoord logicalHeight =
+ nsHTMLReflowState::CalcLineHeight(mPresContext, parentFrame);
+ nscoord contentHeight = parentPFD->mBounds.height -
+ parentPFD->mBorderPadding.top - parentPFD->mBorderPadding.bottom;
+ nscoord leading = logicalHeight - contentHeight;
+ psd->mTopLeading = leading / 2;
+ psd->mBottomLeading = leading - psd->mTopLeading;
+ psd->mLogicalHeight = logicalHeight;
+
+ // The initial values for the min and max Y values are in the spans
+ // coordinate space, and cover the logical height of the span. If
+ // there are child frames in this span that stick out of this area
+ // then the minY and maxY are updated by the amount of logical
+ // height that is outside this range.
+ minY = parentPFD->mBorderPadding.top - psd->mTopLeading;
+ maxY = minY + psd->mLogicalHeight;
+
+ // This is the distance from the top edge of the parents visual
+ // box to the baseline.
+ nscoord parentAscent;
+ fm->GetMaxAscent(parentAscent);
+ baselineY = parentAscent + parentPFD->mBorderPadding.top;
+#ifdef NOISY_VERTICAL_ALIGN
+ nsFrame::ListTag(stdout, parentFrame);
+ printf(": baseLine=%d logicalHeight=%d topLeading=%d h=%d bp=%d,%d\n",
+ baselineY, logicalHeight, psd->mTopLeading,
+ parentPFD->mBounds.height,
+ parentPFD->mBorderPadding.top, parentPFD->mBorderPadding.bottom);
+#endif
+ }
+ else {
+ // When a span container is zero height it means that all of its
+ // kids are zero height as well.
+ psd->mMinY = 0;
+ psd->mMaxY = 0;
+ psd->mTopLeading = 0;
+ psd->mBottomLeading = 0;
+ psd->mLogicalHeight = 0;
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ==> [empty line]\n");
+#endif
+ return;
+ }
+
+ nscoord maxTopBoxHeight = 0;
+ nscoord maxBottomBoxHeight = 0;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ nsIFrame* frame = pfd->mFrame;
+
+ // Compute the logical height of the frame
+ nscoord logicalHeight;
+ nscoord topLeading;
+ PerSpanData* frameSpan = pfd->mSpan;
+ if (frameSpan) {
+ // For span frames the logical-height and top-leading was
+ // pre-computed when the span was reflowed.
+ logicalHeight = frameSpan->mLogicalHeight;
+ topLeading = frameSpan->mTopLeading;
+ }
+ else {
+ // For other elements the logical height is the same as the
+ // frames height plus its margins.
+ logicalHeight = pfd->mBounds.height + pfd->mMargin.top +
+ pfd->mMargin.bottom;
+ topLeading = 0;
+ }
+
+ // Get vertical-align property
+ const nsStyleText* textStyle;
+ frame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
+ nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
+ if (eStyleUnit_Inherit == verticalAlignUnit) {
+ printf("XXX: vertical-align: inherit not implemented for ");
+ nsFrame::ListTag(stdout, frame);
+ printf("\n");
+ }
+ PRUint8 verticalAlignEnum;
+ nscoord parentAscent, parentDescent, parentXHeight;
+ nscoord parentSuperscript, parentSubscript;
+ nscoord coordOffset, percentOffset, elementLineHeight;
+ nscoord revisedBaselineY;
+ switch (verticalAlignUnit) {
+ case eStyleUnit_Enumerated:
+ default:
+ if (eStyleUnit_Enumerated == verticalAlignUnit) {
+ verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
+ }
+ else {
+ verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_BASELINE;
+ }
+ switch (verticalAlignEnum) {
+ default:
+ case NS_STYLE_VERTICAL_ALIGN_BASELINE:
+ // The elements baseline is aligned with the baseline of
+ // the parent.
+ if (frameSpan) {
+ // XXX explain
+ pfd->mBounds.y = baselineY - pfd->mAscent;
+ }
+ else {
+ // For non-span elements the borders, padding and
+ // margins are significant. Use the visual box height
+ // and the bottom margin as the distance off of the
+ // baseline.
+ pfd->mBounds.y = baselineY - pfd->mAscent - pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_SUB:
+ // Lower the baseline of the box to the subscript offset
+ // of the parent's box. This is identical to the baseline
+ // alignment except for the addition of the subscript
+ // offset to the baseline Y.
+ fm->GetSubscriptOffset(parentSubscript);
+ revisedBaselineY = baselineY + parentSubscript;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_SUPER:
+ // Raise the baseline of the box to the superscript offset
+ // of the parent's box. This is identical to the baseline
+ // alignment except for the subtraction of the superscript
+ // offset to the baseline Y.
+ fm->GetSuperscriptOffset(parentSuperscript);
+ revisedBaselineY = baselineY - parentSuperscript;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_TOP:
+ pfd->mVerticalAlign = VALIGN_TOP;
+ if (logicalHeight > maxTopBoxHeight) {
+ maxTopBoxHeight = logicalHeight;
+ }
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
+ pfd->mVerticalAlign = VALIGN_BOTTOM;
+ if (logicalHeight > maxBottomBoxHeight) {
+ maxBottomBoxHeight = logicalHeight;
+ }
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
+ // Align the midpoint of the frame with 1/2 the parents
+ // x-height above the baseline.
+ fm->GetXHeight(parentXHeight);
+ if (frameSpan) {
+ pfd->mBounds.y = baselineY -
+ (parentXHeight + pfd->mBounds.height)/2;
+ }
+ else {
+ pfd->mBounds.y = baselineY - (parentXHeight + logicalHeight)/2 +
+ pfd->mMargin.top;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
+ // The top of the logical box is aligned with the top of
+ // the parent elements text.
+ fm->GetMaxAscent(parentAscent);
+ if (frameSpan) {
+ pfd->mBounds.y = baselineY - parentAscent -
+ pfd->mBorderPadding.top + frameSpan->mTopLeading;
+ }
+ else {
+ pfd->mBounds.y = baselineY - parentAscent + pfd->mMargin.top;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
+ // The bottom of the logical box is aligned with the
+ // bottom of the parent elements text.
+ fm->GetMaxDescent(parentDescent);
+ if (frameSpan) {
+ pfd->mBounds.y = baselineY + parentDescent -
+ pfd->mBounds.height + pfd->mBorderPadding.bottom -
+ frameSpan->mBottomLeading;
+ }
+ else {
+ pfd->mBounds.y = baselineY + parentDescent -
+ pfd->mBounds.height - pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+ }
+ break;
+
+ case eStyleUnit_Coord:
+ // According to the CSS2 spec (10.8.1), a positive value
+ // "raises" the box by the given distance while a negative value
+ // "lowers" the box by the given distance (with zero being the
+ // baseline). Since Y coordinates increase towards the bottom of
+ // the screen we reverse the sign.
+ coordOffset = textStyle->mVerticalAlign.GetCoordValue();
+ revisedBaselineY = baselineY - coordOffset;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case eStyleUnit_Percent:
+ // Similar to a length value (eStyleUnit_Coord) except that the
+ // percentage is a function of the elements line-height value.
+ elementLineHeight =
+ nsHTMLReflowState::CalcLineHeight(mPresContext, frame);
+ percentOffset = nscoord(
+ textStyle->mVerticalAlign.GetPercentValue() * elementLineHeight
+ );
+ revisedBaselineY = baselineY - percentOffset;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+ }
+
+ // Update minY/maxY for frames that we just placed
+ if (pfd->mVerticalAlign == VALIGN_OTHER) {
+ nscoord yTop, yBottom;
+ if (frameSpan) {
+ // For spans that were are now placing, use their position
+ // plus their already computed min-Y and max-Y values for
+ // computing yTop and yBottom.
+ yTop = pfd->mBounds.y + frameSpan->mMinY;
+ yBottom = pfd->mBounds.y + frameSpan->mMaxY;
+ }
+ else {
+ yTop = pfd->mBounds.y - pfd->mMargin.top;
+ yBottom = yTop + logicalHeight;
+ }
+ if (yTop < minY) minY = yTop;
+ if (yBottom > maxY) maxY = yBottom;
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, frame);
+ printf(": raw: a=%d d=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minY=%d maxY=%d\n",
+ pfd->mAscent, pfd->mDescent, pfd->mBounds.height,
+ pfd->mBorderPadding.top, pfd->mBorderPadding.bottom,
+ logicalHeight,
+ pfd->mSpan ? topLeading : 0,
+ pfd->mBounds.y, minY, maxY);
+#endif
+ if (psd != mRootSpan) {
+ frame->SetRect(pfd->mBounds);
+ }
+ }
+ pfd = pfd->mNext;
+ }
+ NS_RELEASE(fm);
+ psd->mMinY = minY;
+ psd->mMaxY = maxY;
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ==> minY=%d maxY=%d delta=%d maxBoxHeight=%d\n",
+ minY, maxY, maxY - minY, maxBoxHeight);
+#endif
+ if (maxTopBoxHeight > mMaxTopBoxHeight) {
+ mMaxTopBoxHeight = maxTopBoxHeight;
+ }
+ if (maxBottomBoxHeight > mMaxBottomBoxHeight) {
+ mMaxBottomBoxHeight = maxBottomBoxHeight;
+ }
+}
+
+void
+nsLineLayout::TrimTrailingWhiteSpace(nsRect& aLineBounds)
+{
+}
+
+void
+nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds, PRBool aAllowJustify)
+{
+ PerSpanData* psd = mRootSpan;
+ nscoord availWidth = psd->mRightEdge;
+ if (NS_UNCONSTRAINEDSIZE == availWidth) {
+ // Don't bother horizontal aligning on pass1 table reflow
+#ifdef REALLY_NOISY_HORIZONTAL_ALIGN
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": skipping horizontal alignment in pass1 table reflow\n");
+#endif
+ return;
+ }
+ availWidth -= psd->mLeftEdge;
+ nscoord remainingWidth = availWidth - aLineBounds.width;
+#ifdef REALLY_NOISY_HORIZONTAL_ALIGN
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": availWidth=%d lineWidth=%d delta=%d\n",
+ availWidth, aLineBounds.width, remainingWidth);
+#endif
+ if (remainingWidth > 0) {
+ nscoord dx = 0;
+ switch (mTextAlign) {
+ case NS_STYLE_TEXT_ALIGN_DEFAULT:
+ if (NS_STYLE_DIRECTION_LTR == mDirection) {
+ // default alignment for left-to-right is left so do nothing
+ break;
+ }
+ // Fall through to align right case for default alignment
+ // used when the direction is right-to-left.
+
+ case NS_STYLE_TEXT_ALIGN_RIGHT:
+ dx = remainingWidth;
+ break;
+
+ case NS_STYLE_TEXT_ALIGN_LEFT:
+ break;
+
+ case NS_STYLE_TEXT_ALIGN_JUSTIFY:
+ // If this is not the last line then go ahead and justify the
+ // frames in the line. If it is the last line then if the
+ // direction is right-to-left then we right-align the frames.
+ if (aAllowJustify) {
+ break;
+ }
+ else if (NS_STYLE_DIRECTION_RTL == mDirection) {
+ // right align the frames
+ dx = remainingWidth;;
+ }
+ break;
+
+ case NS_STYLE_TEXT_ALIGN_CENTER:
+ dx = remainingWidth / 2;
+ break;
+ }
+ if (0 != dx) {
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ pfd->mBounds.x += dx;
+ pfd->mFrame->SetRect(pfd->mBounds);
+ pfd = pfd->mNext;
+ }
+ }
+ }
+}
+
+void
+nsLineLayout::RelativePositionFrames(nsRect& aCombinedArea)
+{
+ RelativePositionFrames(mRootSpan, aCombinedArea);
+}
+
+void
+nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
+{
+ nsPoint origin;
+ nsRect spanCombinedArea;
+ PerFrameData* pfd;
+
+ nscoord x0, y0, x1, y1;
+ if (nsnull != psd->mFrame) {
+ // The minimum combined area for the frames in a span covers the
+ // entire span frame.
+ pfd = psd->mFrame;
+ x0 = 0;
+ y0 = 0;
+ x1 = pfd->mBounds.width;
+ y1 = pfd->mBounds.height;
+ }
+ else {
+ // The minimum combined area for the frames that are direct
+ // children of the block starts at the upper left corner of the
+ // line but has no width or height.
+ x1 = x0 = psd->mLeftEdge;
+ y1 = y0 = mTopEdge;
+ }
+
+ pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ nscoord x = pfd->mBounds.x;
+ nscoord y = pfd->mBounds.y;
+
+ // Adjust the origin of the frame
+ if (pfd->mRelativePos) {
+ nsIFrame* frame = pfd->mFrame;
+ frame->GetOrigin(origin);
+ // XXX what about right and bottom?
+ nscoord dx = pfd->mOffsets.left;
+ nscoord dy = pfd->mOffsets.top;
+ frame->MoveTo(origin.x + dx, origin.y + dy);
+ x += dx;
+ y += dy;
+ }
+
+ // Note: the combined area of a child is in its coordinate
+ // system. We adjust the childs combined area into our coordinate
+ // system before computing the aggregated value by adding in
+ // x and y which were computed above.
+ nsRect* r = &pfd->mCombinedArea;
+ if (pfd->mSpan) {
+ // Compute a new combined area for the child span before
+ // aggregating it into our combined area.
+ r = &spanCombinedArea;
+ RelativePositionFrames(pfd->mSpan, spanCombinedArea);
+ }
+
+ nscoord xl = x + r->x;
+ nscoord xr = x + r->XMost();
+ if (xl < x0) x0 = xl;
+ if (xr > x1) x1 = xr;
+ nscoord yt = y + r->y;
+ nscoord yb = y + r->YMost();
+ if (yt < y0) y0 = yt;
+ if (yb > y1) y1 = yb;
+
+ pfd = pfd->mNext;
+ }
+
+ // Compute aggregated combined area
+ aCombinedArea.x = x0;
+ aCombinedArea.y = y0;
+ aCombinedArea.width = x1 - x0;
+ aCombinedArea.height = y1 - y0;
+
+ // If we just computed a spans combined area, we need to update its
+ // NS_FRAME_OUTSIDE_CHILDREN bit..
+ if (nsnull != psd->mFrame) {
+ pfd = psd->mFrame;
+ nsIFrame* frame = pfd->mFrame;
+ nsFrameState oldState;
+ frame->GetFrameState(&oldState);
+ nsFrameState newState = oldState & ~NS_FRAME_OUTSIDE_CHILDREN;
+ if ((x0 < 0) || (y0 < 0) ||
+ (x1 > pfd->mBounds.width) || (y1 > pfd->mBounds.height)) {
+ newState |= NS_FRAME_OUTSIDE_CHILDREN;
+ }
+ if (newState != oldState) {
+ frame->SetFrameState(newState);
+ }
+ }
+}
+
+void
+nsLineLayout::ForgetWordFrame(nsIFrame* aFrame)
+{
+ NS_ASSERTION((void*)aFrame == mWordFrames[0], "forget-word-frame");
+ if (0 != mWordFrames.Count()) {
+ mWordFrames.RemoveElementAt(0);
}
- return nsnull;
}
nsIFrame*
@@ -164,56 +1810,41 @@ nsLineLayout::FindNextText(nsIFrame* aFrame)
return nsnull;
}
-PRBool
-nsLineLayout::IsNextWordFrame(nsIFrame* aFrame)
+nsresult
+nsLineLayout::AddText(nsIFrame* aTextFrame)
{
- if (0 != mWordFrames.Count()) {
- nsIFrame* next = (nsIFrame*) mWordFrames[0];
- return next == aFrame;
+ if (nsnull == mNewTextRun) {
+ mNewTextRun = new nsTextRun();
+ if (nsnull == mNewTextRun) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *mTextRunP = mNewTextRun;
+ mTextRunP = &mNewTextRun->mNext;
}
- return PR_FALSE;
-}
-
-PRBool
-nsLineLayout::IsLastWordFrame(nsIFrame* aFrame)
-{
- PRInt32 n = mWordFrames.Count();
- if (0 != n) {
- nsIFrame* next = (nsIFrame*) mWordFrames[0];
- return (next == aFrame) && (1 == n);
+ mNewTextRun->mArray.AppendElement(aTextFrame);
+#ifdef DEBUG_ADD_TEXT
+ PRInt32 n = mNewTextRun->mArray.Count();
+ for (PRInt32 i = 0; i < n - 1; i++) {
+ NS_ASSERTION(mNewTextRun->mArray[i] != (void*)aTextFrame, "yikes");
}
- return PR_FALSE;
+#endif
+ return NS_OK;/* XXX */
}
void
-nsLineLayout::ForgetWordFrame(nsIFrame* aFrame)
+nsLineLayout::EndTextRun()
{
- NS_ASSERTION((void*)aFrame == mWordFrames[0], "forget-word-frame");
- if (0 != mWordFrames.Count()) {
- mWordFrames.RemoveElementAt(0);
- }
+ mNewTextRun = nsnull;
}
-// XXX move this somewhere else!!!
-PRBool
-nsLineLayout::TreatFrameAsBlock(const nsStyleDisplay* aDisplay,
- const nsStylePosition* aPosition)
+nsTextRun*
+nsLineLayout::TakeTextRuns()
{
- if (NS_STYLE_POSITION_ABSOLUTE == aPosition->mPosition) {
- return PR_FALSE;
- }
- if (NS_STYLE_FLOAT_NONE != aDisplay->mFloats) {
- return PR_FALSE;
- }
- switch (aDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- case NS_STYLE_DISPLAY_RUN_IN:
- case NS_STYLE_DISPLAY_COMPACT:
- case NS_STYLE_DISPLAY_TABLE:
- return PR_TRUE;
- }
- return PR_FALSE;
+ nsTextRun* result = mTextRuns;
+ mTextRuns = nsnull;
+ mTextRunP = &mTextRuns;
+ mNewTextRun = nsnull;
+ return result;
}
PRBool
@@ -223,24 +1854,19 @@ nsLineLayout::TreatFrameAsBlock(nsIFrame* aFrame)
const nsStylePosition* position;
aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aFrame->GetStyleData(eStyleStruct_Position,(const nsStyleStruct*&) position);
- return TreatFrameAsBlock(display, position);
-}
-
-void
-nsLineLayout::UpdateInlines(nscoord aX, nscoord aY,
- nscoord aWidth, nscoord aHeight,
- PRBool aIsLeftFloater)
-{
- PRInt32 i, n = mInlineStack.Count();
- for (i = 0; i < n; i++) {
- nsInlineReflow* ir = (nsInlineReflow*) mInlineStack[i];
- ir->UpdateBand(aX, aY, aWidth, aHeight, aIsLeftFloater);
-
- // After the first inline is updated the remainder are relative to
- // their parent therefore zap the x,y coordinates.
-
- // XXX border/padding adjustments need to be re-applied for inlines
- aX = 0;
- aY = 0;
+ if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) {
+ return PR_FALSE;
}
+ if (NS_STYLE_FLOAT_NONE != display->mFloats) {
+ return PR_FALSE;
+ }
+ switch (display->mDisplay) {
+ case NS_STYLE_DISPLAY_BLOCK:
+ case NS_STYLE_DISPLAY_LIST_ITEM:
+ case NS_STYLE_DISPLAY_RUN_IN:
+ case NS_STYLE_DISPLAY_COMPACT:
+ case NS_STYLE_DISPLAY_TABLE:
+ return PR_TRUE;
+ }
+ return PR_FALSE;
}
diff --git a/mozilla/layout/generic/nsLineLayout.h b/mozilla/layout/generic/nsLineLayout.h
index 3e16f842d76..1542bcd7dd5 100644
--- a/mozilla/layout/generic/nsLineLayout.h
+++ b/mozilla/layout/generic/nsLineLayout.h
@@ -19,132 +19,28 @@
#ifndef nsLineLayout_h___
#define nsLineLayout_h___
-#include "nsIFrame.h"
+#include "nsFrame.h"
#include "nsVoidArray.h"
#include "nsTextReflow.h"
+class nsISpaceManager;
class nsBlockReflowState;
-class nsInlineReflow;
class nsPlaceholderFrame;
-struct nsStyleDisplay;
-struct nsStylePosition;
-struct nsStyleSpacing;
-
-// XXX rename to nsLineReflow
-
-//----------------------------------------------------------------------
+struct nsStyleText;
class nsLineLayout {
public:
nsLineLayout(nsIPresContext& aPresContext,
- nsISpaceManager* aSpaceManager);
+ nsISpaceManager* aSpaceManager,
+ const nsHTMLReflowState* aOuterReflowState,
+ PRBool aComputeMaxElementSize);
+ nsLineLayout(nsIPresContext& aPresContext);
~nsLineLayout();
- void Init(nsBlockReflowState* aReflowState) {/* XXX ctor arg really */
- mBlockReflowState = aReflowState;
+ void Init(nsBlockReflowState* aState) {
+ mBlockRS = aState;
}
- // Prepare this line-layout for the reflow of a new line
- void Reset() {
- mTotalPlacedFrames = 0;
- mColumn = 0;
- mEndsInWhiteSpace = PR_TRUE;
- mUnderstandsWhiteSpace = PR_FALSE;
- mBRFrame = nsnull;
- mPlacedFrames.Clear();
- ForgetWordFrames();
- mFirstLetterStyleOK = PR_FALSE;
- mPass2VAlignCount = 0;
- }
-
- // Record the prescence of a frame that needs pass2 vertical-align
- // handling.
- void RecordPass2VAlignFrame() {
- mPass2VAlignCount++;
- }
-
- PRBool NeedPass2VAlign() const {
- return 0 != mPass2VAlignCount;
- }
-
- // Add to the placed-frame count
- void AddPlacedFrame(nsIFrame* aFrame) {
- mTotalPlacedFrames++;
- mPlacedFrames.AppendElement(aFrame);
- }
-
- // Get the placed-frame count
- PRInt32 GetPlacedFrames() const {
- return mTotalPlacedFrames;
- }
-
- const nsVoidArray& PlacedFrames() const {
- return mPlacedFrames;
- }
-
- void SetBRFrame(nsIFrame* aFrame) {
- mBRFrame = aFrame;
- }
-
- nsIFrame* GetBRFrame() const {
- return mBRFrame;
- }
-
- void PushInline(nsInlineReflow* aInlineReflow) {
- mInlineStack.AppendElement(aInlineReflow);
- }
-
- void PopInline() {
- PRInt32 n = mInlineStack.Count();
- if (n > 0) {
- mInlineStack.RemoveElementAt(n - 1);
- }
- }
-
- void UpdateInlines(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
- PRBool aPlacedLeftFloater);
-
- // Reset the text-run information in preparation for a FindTextRuns
- void ResetTextRuns();
-
- // Add another piece of text to a text-run during FindTextRuns.
- // Note: continuation frames must NOT add themselves; just the
- // first-in-flow
- nsresult AddText(nsIFrame* aTextFrame);
-
- // Close out a text-run during FindTextRuns.
- void EndTextRun();
-
- // This returns the first nsTextRun found during a
- // FindTextRuns. The internal text-run state is reset.
- nsTextRun* TakeTextRuns();
-
- void SetReflowTextRuns(nsTextRun* aTextRuns) {
- mReflowTextRuns = aTextRuns;
- }
-
- nsIFrame* FindNextText(nsIFrame* aFrame);
-
- nsTextRun* FindTextRunFor(nsIFrame* aFrame);
-
- void RecordWordFrame(nsIFrame* aWordFrame) {
- mWordFrames.AppendElement(aWordFrame);
- }
-
- void ForgetWordFrames() {
- mWordFrames.Clear();
- }
-
- PRBool IsNextWordFrame(nsIFrame* aFrame);
-
- PRBool InWord() {
- return 0 != mWordFrames.Count();
- }
-
- PRBool IsLastWordFrame(nsIFrame* aFrame);
-
- void ForgetWordFrame(nsIFrame* aFrame);
-
PRInt32 GetColumn() {
return mColumn;
}
@@ -153,7 +49,7 @@ public:
mColumn = aNewColumn;
}
- void NextLine() {
+ void AdvanceToNextLine() {
mLineNumber++;
}
@@ -161,33 +57,63 @@ public:
return mLineNumber;
}
- static PRBool TreatFrameAsBlock(const nsStyleDisplay* aDisplay,
- const nsStylePosition* aPosition);
+ void BeginLineReflow(nscoord aX, nscoord aY,
+ nscoord aWidth, nscoord aHeight,
+ PRBool aIsTopOfPage);
- static PRBool TreatFrameAsBlock(nsIFrame* aFrame);
+ void EndLineReflow();
- // --------------------------------------------------
+ void UpdateBand(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
+ PRBool aPlacedLeftFloater);
- void InitFloater(nsPlaceholderFrame* aFrame);
+ nsresult BeginSpan(nsIFrame* aFrame,
+ const nsHTMLReflowState* aSpanReflowState,
+ nscoord aLeftEdge,
+ nscoord aRightEdge);
- void AddFloater(nsPlaceholderFrame* aFrame);
+ void EndSpan(nsIFrame* aFrame, nsSize& aSizeResult,
+ nsSize* aMaxElementSize);
- nsIPresContext& mPresContext;
- nsISpaceManager* mSpaceManager;
- nsBlockReflowState* mBlockReflowState;
+ PRInt32 GetCurrentSpanCount() const;
- PRBool mListPositionOutside;
- PRInt32 mLineNumber;
- PRInt32 mColumn;
-
- void SetUnderstandsWhiteSpace(PRBool aSetting) {
- mUnderstandsWhiteSpace = aSetting;
+ void SplitLineTo(PRInt32 aNewCount);
+
+ PRBool IsZeroHeight();
+
+ nsresult ReflowFrame(nsIFrame* aFrame,
+ nsIFrame** aNextRCFrame,
+ nsReflowStatus& aReflowStatus);
+
+
+ nscoord GetCarriedOutTopMargin() const {
+ return mCurrentSpan->mLastFrame->mCarriedOutTopMargin;
}
- PRBool GetUnderstandsWhiteSpace() const {
- return mUnderstandsWhiteSpace;
+ nscoord GetCarriedOutBottomMargin() const {
+ return mCurrentSpan->mLastFrame->mCarriedOutBottomMargin;
}
+ nsresult AddBulletFrame(nsIFrame* aFrame,
+ const nsHTMLReflowMetrics& aMetrics);
+
+ void RemoveBulletFrame(nsIFrame* aFrame) {
+ PushFrame(aFrame);
+ }
+
+ void VerticalAlignFrames(nsRect& aLineBoxResult,
+ nsSize& aMaxElementSizeResult);
+
+ void TrimTrailingWhiteSpace(nsRect& aLineBounds);
+
+ void HorizontalAlignFrames(nsRect& aLineBounds, PRBool aAllowJustify);
+
+ void RelativePositionFrames(nsRect& aCombinedArea);
+
+ //----------------------------------------
+
+ // Support methods for white-space compression and word-wrapping
+ // during line reflow
+
void SetEndsInWhiteSpace(PRBool aState) {
mEndsInWhiteSpace = aState;
}
@@ -196,6 +122,51 @@ public:
return mEndsInWhiteSpace;
}
+ void SetUnderstandsWhiteSpace(PRBool aSetting) {
+ mUnderstandsWhiteSpace = aSetting;
+ }
+
+ void RecordWordFrame(nsIFrame* aWordFrame) {
+ mWordFrames.AppendElement(aWordFrame);
+ }
+
+ PRBool InWord() const {
+ return 0 != mWordFrames.Count();
+ }
+
+ void ForgetWordFrame(nsIFrame* aFrame);
+
+ void ForgetWordFrames() {
+ mWordFrames.Clear();
+ }
+
+ nsIFrame* FindNextText(nsIFrame* aFrame);
+
+ PRBool LineIsEmpty() const {
+ return 0 == mTotalPlacedFrames;
+ }
+
+ //----------------------------------------
+
+ // Inform the line-layout engine about the presence of a BR frame
+ // XXX get rid of this: use get-frame-type?
+ void SetBRFrame(nsIFrame* aFrame) {
+ mBRFrame = aFrame;
+ }
+
+ // Return the line's BR frame if any
+ nsIFrame* GetBRFrame() const {
+ return mBRFrame;
+ }
+
+ //----------------------------------------
+ // Inform the line-layout about the presence of a floating frame
+ // XXX get rid of this: use get-frame-type?
+ void InitFloater(nsPlaceholderFrame* aFrame);
+ void AddFloater(nsPlaceholderFrame* aFrame);
+
+ //----------------------------------------
+
PRBool GetFirstLetterStyleOK() const {
return mFirstLetterStyleOK;
}
@@ -204,29 +175,185 @@ public:
mFirstLetterStyleOK = aSetting;
}
-protected:
- nsIFrame* mBRFrame;
+ //----------------------------------------
+ // Text run usage methods. These methods are using during reflow to
+ // track the current text run and to advance through text runs.
+ void SetReflowTextRuns(nsTextRun* aTextRuns) {
+ mReflowTextRuns = aTextRuns;
+ }
+
+ //----------------------------------------
+
+ static PRBool TreatFrameAsBlock(nsIFrame* aFrame);
+
+ //----------------------------------------
+
+ // XXX Move this out of line-layout; make some little interface to
+ // deal with it...
+
+ // Add another piece of text to a text-run during FindTextRuns.
+ // Note: continuation frames must NOT add themselves; just the
+ // first-in-flow
+ nsresult AddText(nsIFrame* aTextFrame);
+
+ // Close out a text-run during FindTextRuns.
+ void EndTextRun();
+
+ // This returns the first nsTextRun found during a FindTextRuns. The
+ // internal text-run state is reset.
+ nsTextRun* TakeTextRuns();
+
+ nsIPresContext& mPresContext;
+
+protected:
+ // This state is constant for a given block frame doing line layout
+ nsISpaceManager* mSpaceManager;
+ const nsStyleText* mStyleText;
+ const nsHTMLReflowState* mBlockReflowState;
+ nsBlockReflowState* mBlockRS;/* XXX hack! */
+ nscoord mMinLineHeight;
+ PRBool mComputeMaxElementSize;
+ PRBool mNoWrap;
+ PRUint8 mTextAlign;
+ PRUint8 mDirection;
+
+ // This state varies during the reflow of a line
+ nsIFrame* mBRFrame;
+ PRInt32 mLineNumber;
+ PRInt32 mColumn;
PRBool mEndsInWhiteSpace;
PRBool mUnderstandsWhiteSpace;
PRBool mFirstLetterStyleOK;
- PRInt32 mPass2VAlignCount;
-
+ PRBool mIsTopOfPage;
+ PRBool mWasInWord;
+ PRBool mCanBreakBeforeFrame;
+ PRBool mUpdatedBand;
+ PRUint8 mPlacedFloaters;
PRInt32 mTotalPlacedFrames;
- nsVoidArray mPlacedFrames;
-
nsVoidArray mWordFrames;
- nsVoidArray mInlineStack;
+ nscoord mTopEdge;
+ nscoord mBottomEdge;
+ nscoord mMaxTopBoxHeight;
+ nscoord mMaxBottomBoxHeight;
- // These slots are used during FindTextRuns
+ nsTextRun* mReflowTextRuns;
+ nsTextRun* mTextRun;
+
+ // Per-frame data recorded by the line-layout reflow logic. This
+ // state is the state needed to post-process the line after reflow
+ // has completed (vertical alignment, horizontal alignment,
+ // justification and relative positioning).
+ struct PerSpanData;
+ struct PerFrameData {
+ // link to next/prev frame in same span
+ PerFrameData* mNext;
+ PerFrameData* mPrev;
+
+ // pointer to child span data if this is an inline container frame
+ PerSpanData* mSpan;
+
+ // The frame and its type
+ nsIFrame* mFrame;
+ nsCSSFrameType mFrameType;
+
+ // From metrics
+ nscoord mAscent, mDescent;
+ nsRect mBounds;
+ nsSize mMaxElementSize;
+ nsRect mCombinedArea;
+ nscoord mCarriedOutTopMargin;
+ nscoord mCarriedOutBottomMargin;
+
+ // From reflow-state
+ nsMargin mMargin;
+ nsMargin mBorderPadding;
+ nsMargin mOffsets;
+ PRBool mRelativePos;
+
+ // Other state we use
+ PRUint8 mVerticalAlign;
+ };
+ PerFrameData mFrameDataBuf[20];
+ PerFrameData* mFrameFreeList;
+
+ struct PerSpanData {
+ PerSpanData* mNext;
+ PerSpanData* mPrev;
+ PerSpanData* mParent;
+ PerFrameData* mFrame;
+ PerFrameData* mFirstFrame;
+ PerFrameData* mLastFrame;
+
+ const nsHTMLReflowState* mReflowState;
+ nscoord mLeftEdge;
+ nscoord mX;
+ nscoord mRightEdge;
+
+ nscoord mTopLeading, mBottomLeading;
+ nscoord mLogicalHeight;
+ nscoord mMinY, mMaxY;
+
+ void AppendFrame(PerFrameData* pfd) {
+ if (nsnull == mLastFrame) {
+ mFirstFrame = pfd;
+ }
+ else {
+ mLastFrame->mNext = pfd;
+ pfd->mPrev = mLastFrame;
+ }
+ mLastFrame = pfd;
+ }
+ };
+ PerSpanData mSpanDataBuf[20];
+ PerSpanData* mSpanFreeList;
+ PerSpanData* mRootSpan;
+ PerSpanData* mLastSpan;
+ PerSpanData* mCurrentSpan;
+ PRInt32 mSpanDepth;
+
+ // XXX These slots are used ONLY during FindTextRuns
nsTextRun* mTextRuns;
nsTextRun** mTextRunP;
nsTextRun* mNewTextRun;
- // These slots are used during InlineReflow
- nsTextRun* mReflowTextRuns;
- nsTextRun* mTextRun;
+ nsresult NewPerFrameData(PerFrameData** aResult);
+
+ nsresult NewPerSpanData(PerSpanData** aResult);
+
+ void FreeSpan(PerSpanData* psd);
+
+ PRBool InBlockContext() const {
+ return mSpanDepth == 0;
+ }
+
+ void PushFrame(nsIFrame* aFrame);
+
+ void ApplyLeftMargin(PerFrameData* pfd,
+ nsHTMLReflowState& aReflowState);
+
+ PRBool CanPlaceFrame(PerFrameData* pfd,
+ const nsHTMLReflowState& aReflowState,
+ nsHTMLReflowMetrics& aMetrics,
+ nsReflowStatus& aStatus);
+
+ void PlaceFrame(PerFrameData* pfd,
+ nsHTMLReflowMetrics& aMetrics);
+
+ void UpdateFrames();
+
+ void VerticalAlignFrames(PerSpanData* psd);
+
+ void PlaceTopBottomFrames(PerSpanData* psd,
+ nscoord aDistanceFromTop,
+ nscoord aLineHeight);
+
+ void RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea);
+
+#ifdef DEBUG
+ void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
+#endif
};
#endif /* nsLineLayout_h___ */
diff --git a/mozilla/layout/html/base/src/Makefile.in b/mozilla/layout/html/base/src/Makefile.in
index 3a042cd9010..054b114c6ec 100644
--- a/mozilla/layout/html/base/src/Makefile.in
+++ b/mozilla/layout/html/base/src/Makefile.in
@@ -44,7 +44,6 @@ CPPSRCS= \
nsImageFrame.cpp \
nsImageMap.cpp \
nsInlineFrame.cpp \
- nsInlineReflow.cpp \
nsLeafFrame.cpp \
nsLineBox.cpp \
nsLineLayout.cpp \
diff --git a/mozilla/layout/html/base/src/makefile.win b/mozilla/layout/html/base/src/makefile.win
index 7f74ad745cf..58b52969139 100644
--- a/mozilla/layout/html/base/src/makefile.win
+++ b/mozilla/layout/html/base/src/makefile.win
@@ -44,7 +44,6 @@ CPPSRCS= \
nsImageFrame.cpp \
nsImageMap.cpp \
nsInlineFrame.cpp \
- nsInlineReflow.cpp \
nsLeafFrame.cpp \
nsLineBox.cpp \
nsLineLayout.cpp \
@@ -81,7 +80,6 @@ CPP_OBJS= \
.\$(OBJDIR)\nsImageFrame.obj \
.\$(OBJDIR)\nsImageMap.obj \
.\$(OBJDIR)\nsInlineFrame.obj \
- .\$(OBJDIR)\nsInlineReflow.obj \
.\$(OBJDIR)\nsLeafFrame.obj \
.\$(OBJDIR)\nsLineBox.obj \
.\$(OBJDIR)\nsLineLayout.obj \
diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp
index ac46b59140a..017a7055e5b 100644
--- a/mozilla/layout/html/base/src/nsBlockFrame.cpp
+++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp
@@ -23,7 +23,6 @@
#include "nsLineBox.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
@@ -64,7 +63,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -75,7 +73,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -210,7 +207,6 @@ public:
const nsHTMLReflowState& mReflowState;
nsLineLayout* mLineLayout;
- nsInlineReflow* mInlineReflow;
nsISpaceManager* mSpaceManager;
nscoord mSpaceManagerX, mSpaceManagerY;
@@ -219,9 +215,6 @@ public:
nsReflowStatus mReflowStatus;
- nsBlockFrame* mRunInFromFrame;
- nsBlockFrame* mRunInToFrame;
-
nscoord mBottomEdge; // maximum Y
PRBool mUnconstrainedWidth;
@@ -275,12 +268,12 @@ public:
void
nsLineLayout::InitFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->InitFloater(aFrame);
+ mBlockRS->InitFloater(aFrame);
}
void
nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->AddFloater(aFrame, PR_FALSE);
+ mBlockRS->AddFloater(aFrame, PR_FALSE);
}
//----------------------------------------------------------------------
@@ -298,8 +291,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mIsMarginRoot(PR_FALSE),
mCarriedOutTopMargin(0)
{
- mInlineReflow = nsnull;
-
mLineLayout = aLineLayout;
mSpaceManager = aReflowState.spaceManager;
@@ -316,30 +307,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mBlock->GetNextInFlow((nsIFrame**)&mNextInFlow);
mKidXMost = 0;
- mRunInFromFrame = nsnull;
- mRunInToFrame = nsnull;
-
-#if 0
- // Compute "content area"
- mUnconstrainedWidth = aReflowState.computedWidth == NS_UNCONSTRAINEDSIZE;
- mUnconstrainedHeight = aReflowState.computedHeight == NS_UNCONSTRAINEDSIZE;
-#ifdef NS_DEBUG
- if ((!mUnconstrainedWidth && (aReflowState.computedWidth > 200000)) ||
- (!mUnconstrainedHeight && (aReflowState.computedHeight > 200000))) {
- mBlock->ListTag(stdout);
- printf(": bad parent: computed size is %d(0x%x),%d(0x%x)\n",
- aReflowState.computedWidth, aReflowState.computedWidth,
- aReflowState.computedHeight, aReflowState.computedHeight);
- if (aReflowState.computedWidth > 200000) {
- mUnconstrainedWidth = PR_TRUE;
- }
- if (aReflowState.computedHeight > 200000) {
- mUnconstrainedHeight = PR_TRUE;
- }
- }
-#endif
-#endif
-
// Compute content area width (the content area is inside the border
// and padding)
mUnconstrainedWidth = PR_FALSE;
@@ -893,30 +860,14 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- // Replace parent provided reflow state with our own significantly
- // more extensive version.
- nsLineLayout ll(aPresContext, aReflowState.spaceManager);
- nsLineLayout* lineLayout = ≪
+ nsLineLayout lineLayout(aPresContext, aReflowState.spaceManager,
+ &aReflowState, nsnull != aMetrics.maxElementSize);
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
- lineLayout);
+ &lineLayout);
+ lineLayout.Init(&state);
if (NS_BLOCK_MARGIN_ROOT & mFlags) {
state.mIsMarginRoot = PR_TRUE;
}
- lineLayout->Init(&state);
-
- // Prepare inline-reflow engine. Note that we will almost always use
- // the inline reflow engine so this setup is not wasted work:
- // because most content has compressed white-space in it, we will
- // use the inline reflow engine to get rid of it.
- nsInlineReflow inlineReflow(ll, aReflowState, this, PR_TRUE,
- state.mComputeMaxElementSize);
- state.mInlineReflow = &inlineReflow;
- lineLayout->PushInline(&inlineReflow);
-
- // Compute the blocks minimum line-height the first time that its
- // needed (which is now).
- nscoord minLineHeight = nsHTMLReflowState::CalcLineHeight(aPresContext, this);
- inlineReflow.SetMinLineHeight(minLineHeight);
if (eReflowReason_Resize != aReflowState.reason) {
RenumberLists();
@@ -956,7 +907,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
else {
// Get next frame in reflow command chain
aReflowState.reflowCommand->GetNext(state.mNextRCFrame);
- inlineReflow.SetNextRCFrame(state.mNextRCFrame);
// Now do the reflow
rv = PrepareChildIncrementalReflow(state);
@@ -989,7 +939,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
- lineLayout->PopInline();
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
@@ -1044,6 +993,20 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
borderPadding.right;
computedWidth = maxWidth;
}
+ else if (aState.mComputeMaxElementSize) {
+ // See if our max-element-size width is larger than our
+ // computed-width. This happens when we are impacted by a
+ // floater. When this does happen, our desired size needs to
+ // include room for the floater.
+ if (computedWidth < aMetrics.maxElementSize->width) {
+#ifdef DEBUG_kipp
+ ListTag(stdout);
+ printf(": adjusting width from %d to %d\n", computedWidth,
+ aMetrics.maxElementSize->width);
+#endif
+ computedWidth = aMetrics.maxElementSize->width;
+ }
+ }
aMetrics.width = computedWidth;
}
#ifdef DEBUG_kipp
@@ -1093,6 +1056,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
(0 == aState.mY - borderPadding.top))) {
aMetrics.width = 0;
aMetrics.height = 0;
+ aMetrics.mCarriedOutTopMargin = 0;
+ aMetrics.mCarriedOutBottomMargin = 0;
emptyFrame = PR_TRUE;
}
@@ -1218,17 +1183,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsresult
nsBlockFrame::PrepareInitialReflow(nsBlockReflowState& aState)
{
- if ((nsnull == mPrevInFlow) && (nsnull != aState.mReflowState.mRunInFrame)) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": run-in from: ");
- aState.mReflowState.mRunInFrame->ListTag(stdout);
- printf("\n");
-#endif
- // Take frames away from the run-in frame
- TakeRunInFrames(aState.mReflowState.mRunInFrame);
- }
-
PrepareResizeReflow(aState);
return NS_OK;
}
@@ -1598,7 +1552,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
// Pull data from a next-in-flow if we can
@@ -1663,7 +1617,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
}
@@ -1719,8 +1673,8 @@ nsBlockFrame::WillReflowLine(nsBlockReflowState& aState,
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- PRBool* aKeepReflowGoing)
+ nsLineBox* aLine,
+ PRBool* aKeepReflowGoing)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBlockFrame::ReflowLine: line=%p", aLine));
@@ -1748,7 +1702,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
}
// Setup the line-layout for the new line
- aState.mLineLayout->Reset();
aState.mCurrentLine = aLine;
aLine->ClearDirty();
aLine->SetNeedDidReflow();
@@ -1758,37 +1711,22 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
// When reflowing a block frame we always get the available space
aState.GetAvailableSpace();
-#if XXX_dead_code
- if ((nsnull != aState.lineLayout) &&
- (0 != aState.lineLayout->GetPlacedFrames())) {
- // Blocks are not allowed on the same line as anything else
- aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
- *aKeepReflowGoing = PR_FALSE;
- }
- else
-#endif
- {
- // Notify observers that we are about to reflow the line
- WillReflowLine(aState, aLine);
+ // Notify observers that we are about to reflow the line
+ WillReflowLine(aState, aLine);
- rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
+ if (NS_FAILED(rv)) {
+ return rv;
}
}
else {
- // When this class is an inline frame and we are reflowing inline
- // frames then there is no point in getting available space.
- nscoord x, availWidth, availHeight;
- aState.GetAvailableSpace();
-
// Setup initial coordinate system for reflowing the inline frames
// into.
+ aState.GetAvailableSpace();
const nsMargin& borderPadding = aState.BorderPadding();
- x = aState.mAvailSpaceRect.x + borderPadding.left;
- availWidth = aState.mAvailSpaceRect.width;
-
+ nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
+ nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord availHeight;
if (aState.mUnconstrainedHeight) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
@@ -1796,7 +1734,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
/* XXX get the height right! */
availHeight = aState.mAvailSpaceRect.height;
}
- aState.mInlineReflow->Init(x, aState.mY, availWidth, availHeight);
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ lineLayout->BeginLineReflow(x, aState.mY, availWidth, availHeight,
+ PR_FALSE /*XXX isTopOfPage*/);
// Notify observers that we are about to reflow the line
WillReflowLine(aState, aLine);
@@ -1863,6 +1803,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
rv = PlaceLine(aState, aLine, aKeepReflowGoing);
}
+ else {
+ lineLayout->EndLineReflow();
+ }
}
return rv;
@@ -2192,14 +2135,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": frame: ");
- nsFrame::ListTag(stdout, aFrame);
- printf(" followed by: ");
- nsFrame::ListTag(stdout, nextFrame);
- printf("\n");
-#endif
followingBlockFrame = (nsBlockFrame*) nextFrame;
break;
}
@@ -2217,30 +2152,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
return followingBlockFrame;
}
-#if XXX
-void
-nsBlockFrame::WillReflowFrame(nsBlockReflowState& aState,
- nsLineBox* aLine,
- nsIFrame* aFrame)
-{
- nsIStyleContext* kidSC;
- aFrame->GetStyleContext(kidSC);
- if (nsnull != kidSC) {
- nsIStyleContext* kidParentSC;
- kidParentSC = kidSC->GetParent();
- if (nsnull != kidParentSC) {
- if (kidParentSC != mStyleContext) {
- // The frame has changed situations so re-resolve its style
- // context in the new situation.
- aFrame->ReResolveStyleContext(&aState.mPresContext, mStyleContext);
- }
- NS_RELEASE(kidParentSC);
- }
- NS_RELEASE(kidSC);
- }
-}
-#endif
-
// XXX This should be a no-op when there is no first-line/letter style
// in force!
void
@@ -2305,15 +2216,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing)
{
NS_PRECONDITION(*aKeepReflowGoing, "bad caller");
- NS_PRECONDITION(0 == aState.mLineLayout->GetPlacedFrames(),
- "non-empty line with a block");
nsresult rv = NS_OK;
nsIFrame* frame = aLine->mFirstChild;
// Prepare the inline reflow engine
-//XXX nsBlockFrame* runInToFrame;
nsBlockFrame* compactWithFrame;
nscoord compactMarginWidth = 0;
PRBool isCompactFrame = PR_FALSE;
@@ -2321,38 +2229,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
switch (display->mDisplay) {
-#if XXX_runin
- case NS_STYLE_DISPLAY_RUN_IN:
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": trying to see if ");
- aFrame->ListTag(stdout);
- printf(" is a run-in candidate\n");
-#endif
- runInToFrame = FindFollowingBlockFrame(frame);
- if (nsnull != runInToFrame) {
-// XXX run-in frame should be pushed to the next-in-flow too if the
-// run-in-to frame is pushed.
- nsRect r(0, aState.mY, 0, 0);
- aLine->mBounds = r;
- aLine->mCombinedArea = r;
- aLine->mCarriedOutTopMargin = 0;
- aLine->mCarriedOutBottomMargin = 0;
- aLine->SetMarginFlags(0);
-#if XXX_need_line_outside_children
- aLine->ClearOutsideChildren();
-#endif
- aLine->mBreakType = NS_STYLE_CLEAR_NONE;
-//XXX aFrame->WillReflow(aState.mPresContext);
- frame->SetRect(r);
- aState.mPrevChild = frame;
- aState.mRunInToFrame = runInToFrame;
- aState.mRunInFrame = (nsBlockFrame*) frame;
- return rv;
- }
- break;
-#endif
-
case NS_STYLE_DISPLAY_COMPACT:
compactWithFrame = FindFollowingBlockFrame(frame);
if (nsnull != compactWithFrame) {
@@ -2392,15 +2268,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
}
-#if XXX_runin
- // Set run-in frame if this is the run-in-to frame. That way the
- // target block frame knows to pick up the children from the run-in
- // frame.
- if (frame == aState.mRunInToFrame) {
- brc.SetRunInFrame(aState.mRunInFrame);
- }
-#endif
-
// Compute the available space for the block
nscoord availHeight = aState.mUnconstrainedHeight
? NS_UNCONSTRAINEDSIZE
@@ -2655,9 +2522,10 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
// Reflow the inline frame
+ nsLineLayout* lineLayout = aState.mLineLayout;
nsReflowStatus frameReflowStatus;
- nsresult rv = aState.mInlineReflow->ReflowFrame(aFrame, aState.IsAdjacentWithTop(),
- frameReflowStatus);
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &aState.mNextRCFrame,
+ frameReflowStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2822,8 +2690,8 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
{
- PRInt32 pushCount = aLine->ChildCount() -
- aState.mInlineReflow->GetCurrentFrameNum();
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ PRInt32 pushCount = aLine->ChildCount() - lineLayout->GetCurrentSpanCount();
//printf("BEFORE (pushCount=%d):\n", pushCount);
//aLine->List(stdout, 0);
if (0 != pushCount) {
@@ -2858,10 +2726,10 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
to->SetIsBlock(aLine->IsBlock());
aLine->mChildCount -= pushCount;
- // Let inline reflow know that some frames are no longer part of
- // its state.
+ // Let line layout know that some frames are no longer part of its
+ // state.
if (!aLine->IsBlock()) {
- aState.mInlineReflow->ChangeFrameCount(aLine->ChildCount());
+ lineLayout->SplitLineTo(aLine->ChildCount());
}
#ifdef DEBUG
VerifyFrameCount(mLines);
@@ -2927,18 +2795,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// method is used for placing a line of inline frames. If the rare
// case is happening then the worst that will happen is that the
// bullet frame will be reflowed twice.
- nsInlineReflow& ir = *aState.mInlineReflow;
+ nsLineLayout* lineLayout = aState.mLineLayout;
PRBool addedBullet = PR_FALSE;
- if (HaveOutsideBullet() && (aLine == mLines) && !ir.IsZeroHeight()) {
+ if (HaveOutsideBullet() && (aLine == mLines) &&
+ !lineLayout->IsZeroHeight()) {
nsHTMLReflowMetrics metrics(nsnull);
ReflowBullet(aState, metrics);
- ir.AddFrame(mBullet, metrics);
+ lineLayout->AddBulletFrame(mBullet, metrics);
addedBullet = PR_TRUE;
}
- nscoord a, d;
- ir.VerticalAlignFrames(aLine->mBounds, a, d);
+ nsSize maxElementSize;
+ lineLayout->VerticalAlignFrames(aLine->mBounds, maxElementSize);
if (addedBullet) {
- ir.RemoveFrame(mBullet);
+ lineLayout->RemoveBulletFrame(mBullet);
}
#ifdef DEBUG_kipp
NS_ASSERTION((aLine->mBounds.YMost()) < 200000 && (aLine->mBounds.y > -200000), "oy");
@@ -2955,14 +2824,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#else
PRBool allowJustify = PR_FALSE;
#endif
- ir.TrimTrailingWhiteSpace(aLine->mBounds);
- ir.HorizontalAlignFrames(aLine->mBounds, allowJustify);
- ir.RelativePositionFrames(aLine->mCombinedArea);
+ lineLayout->TrimTrailingWhiteSpace(aLine->mBounds);
+ lineLayout->HorizontalAlignFrames(aLine->mBounds, allowJustify);
+ lineLayout->RelativePositionFrames(aLine->mCombinedArea);
// Calculate the bottom margin for the line.
nscoord lineBottomMargin = 0;
if (0 == aLine->mBounds.height) {
- nsIFrame* brFrame = aState.mLineLayout->GetBRFrame();
+ // XXX I don't think that this is necessary anymore because of the
+ // way that min-line-height is applied in the vertical alignment
+ // code; since we always have a line-height, a BR on its own line
+ // will get at least the default line-height amount of vertical
+ // space.
+ nsIFrame* brFrame = lineLayout->GetBRFrame();
if (nsnull != brFrame) {
// If a line ends in a BR, and the line is empty of height, then
// we make sure that the line ends up with some height
@@ -2984,43 +2858,32 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
}
}
- else {
- aState.mRunInFromFrame = nsnull;
- aState.mRunInToFrame = nsnull;
- }
// Calculate the lines top and bottom margin values. The margin will
// come from an embedded block frame, not from inline
// frames. Because this is an "inline" line, the child margins are
// all effectively zero so we pass in nsMargin(0, 0, 0, 0).
nscoord topMargin, bottomMargin;
+ nscoord cotm = lineLayout->GetCarriedOutTopMargin();
+ nscoord cobm = lineLayout->GetCarriedOutBottomMargin();
nsBlockReflowContext::CollapseMargins(nsMargin(0, 0, 0, 0),
- ir.GetCarriedOutTopMargin(),
- ir.GetCarriedOutBottomMargin(),
+ cotm, cobm,
aLine->mBounds.height,
aState.mPrevBottomMargin,
topMargin, bottomMargin);
-#if XXX
-ListTag(stdout);
-printf(": ");
-((nsFrame*)(aLine->mFirstChild))->ListTag(stdout);
-printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
- aState.mY, ir.GetCarriedOutTopMargin(), ir.GetCarriedOutBottomMargin(),
- topMargin, bottomMargin, aState.mPrevBottomMargin,
- aState.ShouldApplyTopMargin() ? "yes" : "no");
-#endif
if (!aState.ShouldApplyTopMargin()) {
aState.mCarriedOutTopMargin = topMargin;
topMargin = 0;
}
+ lineLayout->EndLineReflow();
+#ifdef DEBUG
+ lineLayout = nsnull;
+#endif
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
nscoord newY = aLine->mBounds.YMost() + topMargin + lineBottomMargin;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
- newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
// follows to our next-in-flow
@@ -3037,8 +2900,8 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
return rv;
}
- aLine->mCarriedOutTopMargin = ir.GetCarriedOutTopMargin();
- aLine->mCarriedOutBottomMargin = ir.GetCarriedOutBottomMargin();
+ aLine->mCarriedOutTopMargin = cotm;
+ aLine->mCarriedOutBottomMargin = cobm;
aState.mPrevBottomMargin = bottomMargin;
if (0 != topMargin) {
// Apply collapsed top-margin value
@@ -3048,7 +2911,7 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
}
aState.mY = newY;
- PostPlaceLine(aState, aLine, ir.GetMaxElementSize());
+ PostPlaceLine(aState, aLine, maxElementSize);
// Any below current line floaters to place?
if (0 != aState.mPendingFloaters.Count()) {
@@ -3094,8 +2957,8 @@ nsBlockFrame::ComputeLineMaxElementSize(nsBlockReflowState& aState,
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- const nsSize& aMaxElementSize)
+ nsLineBox* aLine,
+ const nsSize& aMaxElementSize)
{
// Update max-element-size
if (aState.mComputeMaxElementSize) {
@@ -3355,7 +3218,6 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
if (nsnull != lastFrame) {
lastFrame->SetNextSibling(aNewFrame);
}
- nsresult rv;
// Make sure that new inlines go onto the end of the lastLine when
// the lastLine is mapping inline frames.
@@ -3371,19 +3233,7 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
for (nsIFrame* frame = aNewFrame; nsnull != frame;
frame->GetNextSibling(&frame)) {
// See if the child is a block or non-block
- const nsStyleDisplay* kidDisplay;
- rv = frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- const nsStylePosition* kidPosition;
- rv = frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) kidPosition);
- if (NS_OK != rv) {
- return rv;
- }
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(frame);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -3517,15 +3367,8 @@ nsBlockFrame::InsertNewFrames(nsIPresContext& aPresContext,
nsIFrame* next;
newFrame->GetNextSibling(&next);
newFrame->SetNextSibling(nsnull);
-
- const nsStyleDisplay* display;
- newFrame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- newFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
- nsLineLayout::TreatFrameAsBlock(display, position)
+ nsLineLayout::TreatFrameAsBlock(newFrame)
? LINE_IS_BLOCK
: 0;
@@ -4092,7 +3935,7 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
- if (0 == mLineLayout->GetPlacedFrames()) {
+ if (mLineLayout->LineIsEmpty()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
@@ -4118,11 +3961,11 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
- mLineLayout->UpdateInlines(mAvailSpaceRect.x + BorderPadding().left,
- mY,
- mAvailSpaceRect.width,
- mAvailSpaceRect.height,
- isLeftFloater);
+ mLineLayout->UpdateBand(mAvailSpaceRect.x + BorderPadding().left,
+ mY,
+ mAvailSpaceRect.width,
+ mAvailSpaceRect.height,
+ isLeftFloater);
// Restore coordinate system
mSpaceManager->Translate(dx, dy);
@@ -4797,9 +4640,9 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
- nsLineLayout textRunThingy(aPresContext, nsnull);
+ nsLineLayout textRunThingy(aPresContext);
- // Ask each child that implements nsIInlineReflow to find its text runs
+ // Ask each child to find its text runs
nsLineBox* line = mLines;
while (nsnull != line) {
if (!line->IsBlock()) {
@@ -4822,8 +4665,8 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
}
}
else {
- // A frame that doesn't implement nsIInlineReflow isn't text
- // therefore it will end an open text run.
+ // A block frame isn't text therefore it will end an open text
+ // run.
textRunThingy.EndTextRun();
}
line = line->mNext;
@@ -4835,39 +4678,6 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
return NS_OK;
}
-void
-nsBlockFrame::TakeRunInFrames(nsBlockFrame* aRunInFrame)
-{
- // Simply steal the run-in-frame's line list and make it our
- // own. XXX Very similar to the logic in DrainOverflowLines...
- nsLineBox* line = aRunInFrame->mLines;
-
- // Make all the frames on the mOverflowLines list mine
- nsIFrame* lastFrame = nsnull;
- nsIFrame* frame = line->mFirstChild;
- while (nsnull != frame) {
- frame->SetParent(this);
- lastFrame = frame;
- frame->GetNextSibling(&frame);
- }
-
- // Join the line lists
- if (nsnull == mLines) {
- mLines = line;
- }
- else {
- // Join the sibling lists together
- lastFrame->SetNextSibling(mLines->mFirstChild);
-
- // Place overflow lines at the front of our line list
- nsLineBox* lastLine = nsLineBox::LastLine(line);
- lastLine->mNext = mLines;
- mLines = line;
- }
-
- aRunInFrame->mLines = nsnull;
-}
-
//----------------------------------------------------------------------
nsresult
@@ -5065,29 +4875,6 @@ nsAnonymousBlockFrame::RemoveFramesFrom(nsIFrame* aFrame)
#endif
}
-#if 0
-nscoord
-nsBlockFrame::ComputeCollapsedTopMargin(const nsHTMLReflowState& aReflowState)
-{
- nscoord myTopMargin = aReflowState.computedMargin.top;
- nsLineBox* line = mLines;
- if (nsnull != line) {
- if (line->IsEmptyLine()) {
- line = line->mNext;
- if (nsnull == line) {
- return myTopMargin;
- }
- }
- if (1 == line->ChildCount()) {
- nsHTMLReflowState rs();
- nscoord topMargin = line->mFirstChild->ComputeCollapsedTopMargin(rs);
- return nsBlockReflowContext::MaxMargin(topMargin, myTopMargin);
- }
- }
- return myTopMargin;
-}
-#endif
-
#ifdef DEBUG
void
nsBlockFrame::VerifyFrameCount(nsLineBox* line)
diff --git a/mozilla/layout/html/base/src/nsBlockFrame.h b/mozilla/layout/html/base/src/nsBlockFrame.h
index dd9ca8b5067..0ea613b8178 100644
--- a/mozilla/layout/html/base/src/nsBlockFrame.h
+++ b/mozilla/layout/html/base/src/nsBlockFrame.h
@@ -277,8 +277,6 @@ protected:
nsLineBox* aLine,
nscoord aDeltaY);
- void TakeRunInFrames(nsBlockFrame* aRunInFrame);
-
nsresult ComputeTextRuns(nsIPresContext& aPresContext);
void BuildFloaterList();
diff --git a/mozilla/layout/html/base/src/nsBlockReflowContext.cpp b/mozilla/layout/html/base/src/nsBlockReflowContext.cpp
index 5ccb35f8d69..ac11c762211 100644
--- a/mozilla/layout/html/base/src/nsBlockReflowContext.cpp
+++ b/mozilla/layout/html/base/src/nsBlockReflowContext.cpp
@@ -38,7 +38,6 @@ nsBlockReflowContext::nsBlockReflowContext(nsIPresContext& aPresContext,
mOuterReflowState(aParentRS),
mMetrics(aComputeMaxElementSize ? &mMaxElementSize : nsnull)
{
- mRunInFrame = nsnull;
mCompactMarginWidth = 0;
mStyleSpacing = nsnull;
}
@@ -102,7 +101,6 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
availSpace, reason);
aComputedOffsets = reflowState.computedOffsets;
reflowState.lineLayout = nsnull;
- reflowState.mRunInFrame = mRunInFrame;
reflowState.mCompactMarginWidth = mCompactMarginWidth;
if (!aIsAdjacentWithTop) {
reflowState.isTopOfPage = PR_FALSE; // make sure this is cleared
@@ -312,6 +310,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
mFrame->SetRect(r);
aInFlowBounds = r;
aCombinedRect = mMetrics.mCombinedArea;
+ mTopMargin = 0;
+ mBottomMargin = 0;
fits = PR_TRUE;
}
else {
diff --git a/mozilla/layout/html/base/src/nsBlockReflowContext.h b/mozilla/layout/html/base/src/nsBlockReflowContext.h
index b3104e91802..f8835ddc398 100644
--- a/mozilla/layout/html/base/src/nsBlockReflowContext.h
+++ b/mozilla/layout/html/base/src/nsBlockReflowContext.h
@@ -40,10 +40,6 @@ public:
PRBool aComputeMaxElementSize);
~nsBlockReflowContext() { }
- void SetRunInFrame(nsBlockFrame* aRunInFrame) {
- mRunInFrame = aRunInFrame;
- }
-
void SetCompactMarginWidth(nscoord aCompactMarginWidth) {
mCompactMarginWidth = aCompactMarginWidth;
}
@@ -132,7 +128,6 @@ protected:
const nsHTMLReflowState& mOuterReflowState;
nsIFrame* mFrame;
- nsBlockFrame* mRunInFrame;
nscoord mCompactMarginWidth;
nsRect mSpace;
nsIFrame* mNextRCFrame;
diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp
index ac46b59140a..017a7055e5b 100644
--- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp
+++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp
@@ -23,7 +23,6 @@
#include "nsLineBox.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
@@ -64,7 +63,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -75,7 +73,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -210,7 +207,6 @@ public:
const nsHTMLReflowState& mReflowState;
nsLineLayout* mLineLayout;
- nsInlineReflow* mInlineReflow;
nsISpaceManager* mSpaceManager;
nscoord mSpaceManagerX, mSpaceManagerY;
@@ -219,9 +215,6 @@ public:
nsReflowStatus mReflowStatus;
- nsBlockFrame* mRunInFromFrame;
- nsBlockFrame* mRunInToFrame;
-
nscoord mBottomEdge; // maximum Y
PRBool mUnconstrainedWidth;
@@ -275,12 +268,12 @@ public:
void
nsLineLayout::InitFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->InitFloater(aFrame);
+ mBlockRS->InitFloater(aFrame);
}
void
nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->AddFloater(aFrame, PR_FALSE);
+ mBlockRS->AddFloater(aFrame, PR_FALSE);
}
//----------------------------------------------------------------------
@@ -298,8 +291,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mIsMarginRoot(PR_FALSE),
mCarriedOutTopMargin(0)
{
- mInlineReflow = nsnull;
-
mLineLayout = aLineLayout;
mSpaceManager = aReflowState.spaceManager;
@@ -316,30 +307,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mBlock->GetNextInFlow((nsIFrame**)&mNextInFlow);
mKidXMost = 0;
- mRunInFromFrame = nsnull;
- mRunInToFrame = nsnull;
-
-#if 0
- // Compute "content area"
- mUnconstrainedWidth = aReflowState.computedWidth == NS_UNCONSTRAINEDSIZE;
- mUnconstrainedHeight = aReflowState.computedHeight == NS_UNCONSTRAINEDSIZE;
-#ifdef NS_DEBUG
- if ((!mUnconstrainedWidth && (aReflowState.computedWidth > 200000)) ||
- (!mUnconstrainedHeight && (aReflowState.computedHeight > 200000))) {
- mBlock->ListTag(stdout);
- printf(": bad parent: computed size is %d(0x%x),%d(0x%x)\n",
- aReflowState.computedWidth, aReflowState.computedWidth,
- aReflowState.computedHeight, aReflowState.computedHeight);
- if (aReflowState.computedWidth > 200000) {
- mUnconstrainedWidth = PR_TRUE;
- }
- if (aReflowState.computedHeight > 200000) {
- mUnconstrainedHeight = PR_TRUE;
- }
- }
-#endif
-#endif
-
// Compute content area width (the content area is inside the border
// and padding)
mUnconstrainedWidth = PR_FALSE;
@@ -893,30 +860,14 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- // Replace parent provided reflow state with our own significantly
- // more extensive version.
- nsLineLayout ll(aPresContext, aReflowState.spaceManager);
- nsLineLayout* lineLayout = ≪
+ nsLineLayout lineLayout(aPresContext, aReflowState.spaceManager,
+ &aReflowState, nsnull != aMetrics.maxElementSize);
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
- lineLayout);
+ &lineLayout);
+ lineLayout.Init(&state);
if (NS_BLOCK_MARGIN_ROOT & mFlags) {
state.mIsMarginRoot = PR_TRUE;
}
- lineLayout->Init(&state);
-
- // Prepare inline-reflow engine. Note that we will almost always use
- // the inline reflow engine so this setup is not wasted work:
- // because most content has compressed white-space in it, we will
- // use the inline reflow engine to get rid of it.
- nsInlineReflow inlineReflow(ll, aReflowState, this, PR_TRUE,
- state.mComputeMaxElementSize);
- state.mInlineReflow = &inlineReflow;
- lineLayout->PushInline(&inlineReflow);
-
- // Compute the blocks minimum line-height the first time that its
- // needed (which is now).
- nscoord minLineHeight = nsHTMLReflowState::CalcLineHeight(aPresContext, this);
- inlineReflow.SetMinLineHeight(minLineHeight);
if (eReflowReason_Resize != aReflowState.reason) {
RenumberLists();
@@ -956,7 +907,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
else {
// Get next frame in reflow command chain
aReflowState.reflowCommand->GetNext(state.mNextRCFrame);
- inlineReflow.SetNextRCFrame(state.mNextRCFrame);
// Now do the reflow
rv = PrepareChildIncrementalReflow(state);
@@ -989,7 +939,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
- lineLayout->PopInline();
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
@@ -1044,6 +993,20 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
borderPadding.right;
computedWidth = maxWidth;
}
+ else if (aState.mComputeMaxElementSize) {
+ // See if our max-element-size width is larger than our
+ // computed-width. This happens when we are impacted by a
+ // floater. When this does happen, our desired size needs to
+ // include room for the floater.
+ if (computedWidth < aMetrics.maxElementSize->width) {
+#ifdef DEBUG_kipp
+ ListTag(stdout);
+ printf(": adjusting width from %d to %d\n", computedWidth,
+ aMetrics.maxElementSize->width);
+#endif
+ computedWidth = aMetrics.maxElementSize->width;
+ }
+ }
aMetrics.width = computedWidth;
}
#ifdef DEBUG_kipp
@@ -1093,6 +1056,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
(0 == aState.mY - borderPadding.top))) {
aMetrics.width = 0;
aMetrics.height = 0;
+ aMetrics.mCarriedOutTopMargin = 0;
+ aMetrics.mCarriedOutBottomMargin = 0;
emptyFrame = PR_TRUE;
}
@@ -1218,17 +1183,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsresult
nsBlockFrame::PrepareInitialReflow(nsBlockReflowState& aState)
{
- if ((nsnull == mPrevInFlow) && (nsnull != aState.mReflowState.mRunInFrame)) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": run-in from: ");
- aState.mReflowState.mRunInFrame->ListTag(stdout);
- printf("\n");
-#endif
- // Take frames away from the run-in frame
- TakeRunInFrames(aState.mReflowState.mRunInFrame);
- }
-
PrepareResizeReflow(aState);
return NS_OK;
}
@@ -1598,7 +1552,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
// Pull data from a next-in-flow if we can
@@ -1663,7 +1617,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
}
@@ -1719,8 +1673,8 @@ nsBlockFrame::WillReflowLine(nsBlockReflowState& aState,
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- PRBool* aKeepReflowGoing)
+ nsLineBox* aLine,
+ PRBool* aKeepReflowGoing)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBlockFrame::ReflowLine: line=%p", aLine));
@@ -1748,7 +1702,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
}
// Setup the line-layout for the new line
- aState.mLineLayout->Reset();
aState.mCurrentLine = aLine;
aLine->ClearDirty();
aLine->SetNeedDidReflow();
@@ -1758,37 +1711,22 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
// When reflowing a block frame we always get the available space
aState.GetAvailableSpace();
-#if XXX_dead_code
- if ((nsnull != aState.lineLayout) &&
- (0 != aState.lineLayout->GetPlacedFrames())) {
- // Blocks are not allowed on the same line as anything else
- aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
- *aKeepReflowGoing = PR_FALSE;
- }
- else
-#endif
- {
- // Notify observers that we are about to reflow the line
- WillReflowLine(aState, aLine);
+ // Notify observers that we are about to reflow the line
+ WillReflowLine(aState, aLine);
- rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
+ if (NS_FAILED(rv)) {
+ return rv;
}
}
else {
- // When this class is an inline frame and we are reflowing inline
- // frames then there is no point in getting available space.
- nscoord x, availWidth, availHeight;
- aState.GetAvailableSpace();
-
// Setup initial coordinate system for reflowing the inline frames
// into.
+ aState.GetAvailableSpace();
const nsMargin& borderPadding = aState.BorderPadding();
- x = aState.mAvailSpaceRect.x + borderPadding.left;
- availWidth = aState.mAvailSpaceRect.width;
-
+ nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
+ nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord availHeight;
if (aState.mUnconstrainedHeight) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
@@ -1796,7 +1734,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
/* XXX get the height right! */
availHeight = aState.mAvailSpaceRect.height;
}
- aState.mInlineReflow->Init(x, aState.mY, availWidth, availHeight);
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ lineLayout->BeginLineReflow(x, aState.mY, availWidth, availHeight,
+ PR_FALSE /*XXX isTopOfPage*/);
// Notify observers that we are about to reflow the line
WillReflowLine(aState, aLine);
@@ -1863,6 +1803,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
rv = PlaceLine(aState, aLine, aKeepReflowGoing);
}
+ else {
+ lineLayout->EndLineReflow();
+ }
}
return rv;
@@ -2192,14 +2135,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": frame: ");
- nsFrame::ListTag(stdout, aFrame);
- printf(" followed by: ");
- nsFrame::ListTag(stdout, nextFrame);
- printf("\n");
-#endif
followingBlockFrame = (nsBlockFrame*) nextFrame;
break;
}
@@ -2217,30 +2152,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
return followingBlockFrame;
}
-#if XXX
-void
-nsBlockFrame::WillReflowFrame(nsBlockReflowState& aState,
- nsLineBox* aLine,
- nsIFrame* aFrame)
-{
- nsIStyleContext* kidSC;
- aFrame->GetStyleContext(kidSC);
- if (nsnull != kidSC) {
- nsIStyleContext* kidParentSC;
- kidParentSC = kidSC->GetParent();
- if (nsnull != kidParentSC) {
- if (kidParentSC != mStyleContext) {
- // The frame has changed situations so re-resolve its style
- // context in the new situation.
- aFrame->ReResolveStyleContext(&aState.mPresContext, mStyleContext);
- }
- NS_RELEASE(kidParentSC);
- }
- NS_RELEASE(kidSC);
- }
-}
-#endif
-
// XXX This should be a no-op when there is no first-line/letter style
// in force!
void
@@ -2305,15 +2216,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing)
{
NS_PRECONDITION(*aKeepReflowGoing, "bad caller");
- NS_PRECONDITION(0 == aState.mLineLayout->GetPlacedFrames(),
- "non-empty line with a block");
nsresult rv = NS_OK;
nsIFrame* frame = aLine->mFirstChild;
// Prepare the inline reflow engine
-//XXX nsBlockFrame* runInToFrame;
nsBlockFrame* compactWithFrame;
nscoord compactMarginWidth = 0;
PRBool isCompactFrame = PR_FALSE;
@@ -2321,38 +2229,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
switch (display->mDisplay) {
-#if XXX_runin
- case NS_STYLE_DISPLAY_RUN_IN:
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": trying to see if ");
- aFrame->ListTag(stdout);
- printf(" is a run-in candidate\n");
-#endif
- runInToFrame = FindFollowingBlockFrame(frame);
- if (nsnull != runInToFrame) {
-// XXX run-in frame should be pushed to the next-in-flow too if the
-// run-in-to frame is pushed.
- nsRect r(0, aState.mY, 0, 0);
- aLine->mBounds = r;
- aLine->mCombinedArea = r;
- aLine->mCarriedOutTopMargin = 0;
- aLine->mCarriedOutBottomMargin = 0;
- aLine->SetMarginFlags(0);
-#if XXX_need_line_outside_children
- aLine->ClearOutsideChildren();
-#endif
- aLine->mBreakType = NS_STYLE_CLEAR_NONE;
-//XXX aFrame->WillReflow(aState.mPresContext);
- frame->SetRect(r);
- aState.mPrevChild = frame;
- aState.mRunInToFrame = runInToFrame;
- aState.mRunInFrame = (nsBlockFrame*) frame;
- return rv;
- }
- break;
-#endif
-
case NS_STYLE_DISPLAY_COMPACT:
compactWithFrame = FindFollowingBlockFrame(frame);
if (nsnull != compactWithFrame) {
@@ -2392,15 +2268,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
}
-#if XXX_runin
- // Set run-in frame if this is the run-in-to frame. That way the
- // target block frame knows to pick up the children from the run-in
- // frame.
- if (frame == aState.mRunInToFrame) {
- brc.SetRunInFrame(aState.mRunInFrame);
- }
-#endif
-
// Compute the available space for the block
nscoord availHeight = aState.mUnconstrainedHeight
? NS_UNCONSTRAINEDSIZE
@@ -2655,9 +2522,10 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
// Reflow the inline frame
+ nsLineLayout* lineLayout = aState.mLineLayout;
nsReflowStatus frameReflowStatus;
- nsresult rv = aState.mInlineReflow->ReflowFrame(aFrame, aState.IsAdjacentWithTop(),
- frameReflowStatus);
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &aState.mNextRCFrame,
+ frameReflowStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2822,8 +2690,8 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
{
- PRInt32 pushCount = aLine->ChildCount() -
- aState.mInlineReflow->GetCurrentFrameNum();
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ PRInt32 pushCount = aLine->ChildCount() - lineLayout->GetCurrentSpanCount();
//printf("BEFORE (pushCount=%d):\n", pushCount);
//aLine->List(stdout, 0);
if (0 != pushCount) {
@@ -2858,10 +2726,10 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
to->SetIsBlock(aLine->IsBlock());
aLine->mChildCount -= pushCount;
- // Let inline reflow know that some frames are no longer part of
- // its state.
+ // Let line layout know that some frames are no longer part of its
+ // state.
if (!aLine->IsBlock()) {
- aState.mInlineReflow->ChangeFrameCount(aLine->ChildCount());
+ lineLayout->SplitLineTo(aLine->ChildCount());
}
#ifdef DEBUG
VerifyFrameCount(mLines);
@@ -2927,18 +2795,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// method is used for placing a line of inline frames. If the rare
// case is happening then the worst that will happen is that the
// bullet frame will be reflowed twice.
- nsInlineReflow& ir = *aState.mInlineReflow;
+ nsLineLayout* lineLayout = aState.mLineLayout;
PRBool addedBullet = PR_FALSE;
- if (HaveOutsideBullet() && (aLine == mLines) && !ir.IsZeroHeight()) {
+ if (HaveOutsideBullet() && (aLine == mLines) &&
+ !lineLayout->IsZeroHeight()) {
nsHTMLReflowMetrics metrics(nsnull);
ReflowBullet(aState, metrics);
- ir.AddFrame(mBullet, metrics);
+ lineLayout->AddBulletFrame(mBullet, metrics);
addedBullet = PR_TRUE;
}
- nscoord a, d;
- ir.VerticalAlignFrames(aLine->mBounds, a, d);
+ nsSize maxElementSize;
+ lineLayout->VerticalAlignFrames(aLine->mBounds, maxElementSize);
if (addedBullet) {
- ir.RemoveFrame(mBullet);
+ lineLayout->RemoveBulletFrame(mBullet);
}
#ifdef DEBUG_kipp
NS_ASSERTION((aLine->mBounds.YMost()) < 200000 && (aLine->mBounds.y > -200000), "oy");
@@ -2955,14 +2824,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#else
PRBool allowJustify = PR_FALSE;
#endif
- ir.TrimTrailingWhiteSpace(aLine->mBounds);
- ir.HorizontalAlignFrames(aLine->mBounds, allowJustify);
- ir.RelativePositionFrames(aLine->mCombinedArea);
+ lineLayout->TrimTrailingWhiteSpace(aLine->mBounds);
+ lineLayout->HorizontalAlignFrames(aLine->mBounds, allowJustify);
+ lineLayout->RelativePositionFrames(aLine->mCombinedArea);
// Calculate the bottom margin for the line.
nscoord lineBottomMargin = 0;
if (0 == aLine->mBounds.height) {
- nsIFrame* brFrame = aState.mLineLayout->GetBRFrame();
+ // XXX I don't think that this is necessary anymore because of the
+ // way that min-line-height is applied in the vertical alignment
+ // code; since we always have a line-height, a BR on its own line
+ // will get at least the default line-height amount of vertical
+ // space.
+ nsIFrame* brFrame = lineLayout->GetBRFrame();
if (nsnull != brFrame) {
// If a line ends in a BR, and the line is empty of height, then
// we make sure that the line ends up with some height
@@ -2984,43 +2858,32 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
}
}
- else {
- aState.mRunInFromFrame = nsnull;
- aState.mRunInToFrame = nsnull;
- }
// Calculate the lines top and bottom margin values. The margin will
// come from an embedded block frame, not from inline
// frames. Because this is an "inline" line, the child margins are
// all effectively zero so we pass in nsMargin(0, 0, 0, 0).
nscoord topMargin, bottomMargin;
+ nscoord cotm = lineLayout->GetCarriedOutTopMargin();
+ nscoord cobm = lineLayout->GetCarriedOutBottomMargin();
nsBlockReflowContext::CollapseMargins(nsMargin(0, 0, 0, 0),
- ir.GetCarriedOutTopMargin(),
- ir.GetCarriedOutBottomMargin(),
+ cotm, cobm,
aLine->mBounds.height,
aState.mPrevBottomMargin,
topMargin, bottomMargin);
-#if XXX
-ListTag(stdout);
-printf(": ");
-((nsFrame*)(aLine->mFirstChild))->ListTag(stdout);
-printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
- aState.mY, ir.GetCarriedOutTopMargin(), ir.GetCarriedOutBottomMargin(),
- topMargin, bottomMargin, aState.mPrevBottomMargin,
- aState.ShouldApplyTopMargin() ? "yes" : "no");
-#endif
if (!aState.ShouldApplyTopMargin()) {
aState.mCarriedOutTopMargin = topMargin;
topMargin = 0;
}
+ lineLayout->EndLineReflow();
+#ifdef DEBUG
+ lineLayout = nsnull;
+#endif
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
nscoord newY = aLine->mBounds.YMost() + topMargin + lineBottomMargin;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
- newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
// follows to our next-in-flow
@@ -3037,8 +2900,8 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
return rv;
}
- aLine->mCarriedOutTopMargin = ir.GetCarriedOutTopMargin();
- aLine->mCarriedOutBottomMargin = ir.GetCarriedOutBottomMargin();
+ aLine->mCarriedOutTopMargin = cotm;
+ aLine->mCarriedOutBottomMargin = cobm;
aState.mPrevBottomMargin = bottomMargin;
if (0 != topMargin) {
// Apply collapsed top-margin value
@@ -3048,7 +2911,7 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
}
aState.mY = newY;
- PostPlaceLine(aState, aLine, ir.GetMaxElementSize());
+ PostPlaceLine(aState, aLine, maxElementSize);
// Any below current line floaters to place?
if (0 != aState.mPendingFloaters.Count()) {
@@ -3094,8 +2957,8 @@ nsBlockFrame::ComputeLineMaxElementSize(nsBlockReflowState& aState,
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- const nsSize& aMaxElementSize)
+ nsLineBox* aLine,
+ const nsSize& aMaxElementSize)
{
// Update max-element-size
if (aState.mComputeMaxElementSize) {
@@ -3355,7 +3218,6 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
if (nsnull != lastFrame) {
lastFrame->SetNextSibling(aNewFrame);
}
- nsresult rv;
// Make sure that new inlines go onto the end of the lastLine when
// the lastLine is mapping inline frames.
@@ -3371,19 +3233,7 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
for (nsIFrame* frame = aNewFrame; nsnull != frame;
frame->GetNextSibling(&frame)) {
// See if the child is a block or non-block
- const nsStyleDisplay* kidDisplay;
- rv = frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- const nsStylePosition* kidPosition;
- rv = frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) kidPosition);
- if (NS_OK != rv) {
- return rv;
- }
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(frame);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -3517,15 +3367,8 @@ nsBlockFrame::InsertNewFrames(nsIPresContext& aPresContext,
nsIFrame* next;
newFrame->GetNextSibling(&next);
newFrame->SetNextSibling(nsnull);
-
- const nsStyleDisplay* display;
- newFrame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- newFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
- nsLineLayout::TreatFrameAsBlock(display, position)
+ nsLineLayout::TreatFrameAsBlock(newFrame)
? LINE_IS_BLOCK
: 0;
@@ -4092,7 +3935,7 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
- if (0 == mLineLayout->GetPlacedFrames()) {
+ if (mLineLayout->LineIsEmpty()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
@@ -4118,11 +3961,11 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
- mLineLayout->UpdateInlines(mAvailSpaceRect.x + BorderPadding().left,
- mY,
- mAvailSpaceRect.width,
- mAvailSpaceRect.height,
- isLeftFloater);
+ mLineLayout->UpdateBand(mAvailSpaceRect.x + BorderPadding().left,
+ mY,
+ mAvailSpaceRect.width,
+ mAvailSpaceRect.height,
+ isLeftFloater);
// Restore coordinate system
mSpaceManager->Translate(dx, dy);
@@ -4797,9 +4640,9 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
- nsLineLayout textRunThingy(aPresContext, nsnull);
+ nsLineLayout textRunThingy(aPresContext);
- // Ask each child that implements nsIInlineReflow to find its text runs
+ // Ask each child to find its text runs
nsLineBox* line = mLines;
while (nsnull != line) {
if (!line->IsBlock()) {
@@ -4822,8 +4665,8 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
}
}
else {
- // A frame that doesn't implement nsIInlineReflow isn't text
- // therefore it will end an open text run.
+ // A block frame isn't text therefore it will end an open text
+ // run.
textRunThingy.EndTextRun();
}
line = line->mNext;
@@ -4835,39 +4678,6 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
return NS_OK;
}
-void
-nsBlockFrame::TakeRunInFrames(nsBlockFrame* aRunInFrame)
-{
- // Simply steal the run-in-frame's line list and make it our
- // own. XXX Very similar to the logic in DrainOverflowLines...
- nsLineBox* line = aRunInFrame->mLines;
-
- // Make all the frames on the mOverflowLines list mine
- nsIFrame* lastFrame = nsnull;
- nsIFrame* frame = line->mFirstChild;
- while (nsnull != frame) {
- frame->SetParent(this);
- lastFrame = frame;
- frame->GetNextSibling(&frame);
- }
-
- // Join the line lists
- if (nsnull == mLines) {
- mLines = line;
- }
- else {
- // Join the sibling lists together
- lastFrame->SetNextSibling(mLines->mFirstChild);
-
- // Place overflow lines at the front of our line list
- nsLineBox* lastLine = nsLineBox::LastLine(line);
- lastLine->mNext = mLines;
- mLines = line;
- }
-
- aRunInFrame->mLines = nsnull;
-}
-
//----------------------------------------------------------------------
nsresult
@@ -5065,29 +4875,6 @@ nsAnonymousBlockFrame::RemoveFramesFrom(nsIFrame* aFrame)
#endif
}
-#if 0
-nscoord
-nsBlockFrame::ComputeCollapsedTopMargin(const nsHTMLReflowState& aReflowState)
-{
- nscoord myTopMargin = aReflowState.computedMargin.top;
- nsLineBox* line = mLines;
- if (nsnull != line) {
- if (line->IsEmptyLine()) {
- line = line->mNext;
- if (nsnull == line) {
- return myTopMargin;
- }
- }
- if (1 == line->ChildCount()) {
- nsHTMLReflowState rs();
- nscoord topMargin = line->mFirstChild->ComputeCollapsedTopMargin(rs);
- return nsBlockReflowContext::MaxMargin(topMargin, myTopMargin);
- }
- }
- return myTopMargin;
-}
-#endif
-
#ifdef DEBUG
void
nsBlockFrame::VerifyFrameCount(nsLineBox* line)
diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h
index ac46b59140a..017a7055e5b 100644
--- a/mozilla/layout/html/base/src/nsBlockReflowState.h
+++ b/mozilla/layout/html/base/src/nsBlockReflowState.h
@@ -23,7 +23,6 @@
#include "nsLineBox.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
@@ -64,7 +63,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -75,7 +73,6 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
#undef REALLY_NOISY_FIRST_LINE
#undef NOISY_FIRST_LETTER
#undef NOISY_MAX_ELEMENT_SIZE
-#undef NOISY_RUNIN
#undef NOISY_FLOATER_CLEARING
#undef NOISY_INCREMENTAL_REFLOW
#undef REFLOW_STATUS_COVERAGE
@@ -210,7 +207,6 @@ public:
const nsHTMLReflowState& mReflowState;
nsLineLayout* mLineLayout;
- nsInlineReflow* mInlineReflow;
nsISpaceManager* mSpaceManager;
nscoord mSpaceManagerX, mSpaceManagerY;
@@ -219,9 +215,6 @@ public:
nsReflowStatus mReflowStatus;
- nsBlockFrame* mRunInFromFrame;
- nsBlockFrame* mRunInToFrame;
-
nscoord mBottomEdge; // maximum Y
PRBool mUnconstrainedWidth;
@@ -275,12 +268,12 @@ public:
void
nsLineLayout::InitFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->InitFloater(aFrame);
+ mBlockRS->InitFloater(aFrame);
}
void
nsLineLayout::AddFloater(nsPlaceholderFrame* aFrame)
{
- mBlockReflowState->AddFloater(aFrame, PR_FALSE);
+ mBlockRS->AddFloater(aFrame, PR_FALSE);
}
//----------------------------------------------------------------------
@@ -298,8 +291,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mIsMarginRoot(PR_FALSE),
mCarriedOutTopMargin(0)
{
- mInlineReflow = nsnull;
-
mLineLayout = aLineLayout;
mSpaceManager = aReflowState.spaceManager;
@@ -316,30 +307,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mBlock->GetNextInFlow((nsIFrame**)&mNextInFlow);
mKidXMost = 0;
- mRunInFromFrame = nsnull;
- mRunInToFrame = nsnull;
-
-#if 0
- // Compute "content area"
- mUnconstrainedWidth = aReflowState.computedWidth == NS_UNCONSTRAINEDSIZE;
- mUnconstrainedHeight = aReflowState.computedHeight == NS_UNCONSTRAINEDSIZE;
-#ifdef NS_DEBUG
- if ((!mUnconstrainedWidth && (aReflowState.computedWidth > 200000)) ||
- (!mUnconstrainedHeight && (aReflowState.computedHeight > 200000))) {
- mBlock->ListTag(stdout);
- printf(": bad parent: computed size is %d(0x%x),%d(0x%x)\n",
- aReflowState.computedWidth, aReflowState.computedWidth,
- aReflowState.computedHeight, aReflowState.computedHeight);
- if (aReflowState.computedWidth > 200000) {
- mUnconstrainedWidth = PR_TRUE;
- }
- if (aReflowState.computedHeight > 200000) {
- mUnconstrainedHeight = PR_TRUE;
- }
- }
-#endif
-#endif
-
// Compute content area width (the content area is inside the border
// and padding)
mUnconstrainedWidth = PR_FALSE;
@@ -893,30 +860,14 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
- // Replace parent provided reflow state with our own significantly
- // more extensive version.
- nsLineLayout ll(aPresContext, aReflowState.spaceManager);
- nsLineLayout* lineLayout = ≪
+ nsLineLayout lineLayout(aPresContext, aReflowState.spaceManager,
+ &aReflowState, nsnull != aMetrics.maxElementSize);
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
- lineLayout);
+ &lineLayout);
+ lineLayout.Init(&state);
if (NS_BLOCK_MARGIN_ROOT & mFlags) {
state.mIsMarginRoot = PR_TRUE;
}
- lineLayout->Init(&state);
-
- // Prepare inline-reflow engine. Note that we will almost always use
- // the inline reflow engine so this setup is not wasted work:
- // because most content has compressed white-space in it, we will
- // use the inline reflow engine to get rid of it.
- nsInlineReflow inlineReflow(ll, aReflowState, this, PR_TRUE,
- state.mComputeMaxElementSize);
- state.mInlineReflow = &inlineReflow;
- lineLayout->PushInline(&inlineReflow);
-
- // Compute the blocks minimum line-height the first time that its
- // needed (which is now).
- nscoord minLineHeight = nsHTMLReflowState::CalcLineHeight(aPresContext, this);
- inlineReflow.SetMinLineHeight(minLineHeight);
if (eReflowReason_Resize != aReflowState.reason) {
RenumberLists();
@@ -956,7 +907,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
else {
// Get next frame in reflow command chain
aReflowState.reflowCommand->GetNext(state.mNextRCFrame);
- inlineReflow.SetNextRCFrame(state.mNextRCFrame);
// Now do the reflow
rv = PrepareChildIncrementalReflow(state);
@@ -989,7 +939,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
// Compute our final size
ComputeFinalSize(aReflowState, state, aMetrics);
- lineLayout->PopInline();
#ifdef NOISY_FINAL_SIZE
ListTag(stdout);
@@ -1044,6 +993,20 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
borderPadding.right;
computedWidth = maxWidth;
}
+ else if (aState.mComputeMaxElementSize) {
+ // See if our max-element-size width is larger than our
+ // computed-width. This happens when we are impacted by a
+ // floater. When this does happen, our desired size needs to
+ // include room for the floater.
+ if (computedWidth < aMetrics.maxElementSize->width) {
+#ifdef DEBUG_kipp
+ ListTag(stdout);
+ printf(": adjusting width from %d to %d\n", computedWidth,
+ aMetrics.maxElementSize->width);
+#endif
+ computedWidth = aMetrics.maxElementSize->width;
+ }
+ }
aMetrics.width = computedWidth;
}
#ifdef DEBUG_kipp
@@ -1093,6 +1056,8 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
(0 == aState.mY - borderPadding.top))) {
aMetrics.width = 0;
aMetrics.height = 0;
+ aMetrics.mCarriedOutTopMargin = 0;
+ aMetrics.mCarriedOutBottomMargin = 0;
emptyFrame = PR_TRUE;
}
@@ -1218,17 +1183,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsresult
nsBlockFrame::PrepareInitialReflow(nsBlockReflowState& aState)
{
- if ((nsnull == mPrevInFlow) && (nsnull != aState.mReflowState.mRunInFrame)) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": run-in from: ");
- aState.mReflowState.mRunInFrame->ListTag(stdout);
- printf("\n");
-#endif
- // Take frames away from the run-in frame
- TakeRunInFrames(aState.mReflowState.mRunInFrame);
- }
-
PrepareResizeReflow(aState);
return NS_OK;
}
@@ -1598,7 +1552,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
// Pull data from a next-in-flow if we can
@@ -1663,7 +1617,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If this is an inline frame then its time to stop
aState.mPrevLine = line;
line = line->mNext;
- aState.mLineLayout->NextLine();
+ aState.mLineLayout->AdvanceToNextLine();
}
}
@@ -1719,8 +1673,8 @@ nsBlockFrame::WillReflowLine(nsBlockReflowState& aState,
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- PRBool* aKeepReflowGoing)
+ nsLineBox* aLine,
+ PRBool* aKeepReflowGoing)
{
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBlockFrame::ReflowLine: line=%p", aLine));
@@ -1748,7 +1702,6 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
}
// Setup the line-layout for the new line
- aState.mLineLayout->Reset();
aState.mCurrentLine = aLine;
aLine->ClearDirty();
aLine->SetNeedDidReflow();
@@ -1758,37 +1711,22 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
// When reflowing a block frame we always get the available space
aState.GetAvailableSpace();
-#if XXX_dead_code
- if ((nsnull != aState.lineLayout) &&
- (0 != aState.lineLayout->GetPlacedFrames())) {
- // Blocks are not allowed on the same line as anything else
- aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
- *aKeepReflowGoing = PR_FALSE;
- }
- else
-#endif
- {
- // Notify observers that we are about to reflow the line
- WillReflowLine(aState, aLine);
+ // Notify observers that we are about to reflow the line
+ WillReflowLine(aState, aLine);
- rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = ReflowBlockFrame(aState, aLine, aKeepReflowGoing);
+ if (NS_FAILED(rv)) {
+ return rv;
}
}
else {
- // When this class is an inline frame and we are reflowing inline
- // frames then there is no point in getting available space.
- nscoord x, availWidth, availHeight;
- aState.GetAvailableSpace();
-
// Setup initial coordinate system for reflowing the inline frames
// into.
+ aState.GetAvailableSpace();
const nsMargin& borderPadding = aState.BorderPadding();
- x = aState.mAvailSpaceRect.x + borderPadding.left;
- availWidth = aState.mAvailSpaceRect.width;
-
+ nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
+ nscoord availWidth = aState.mAvailSpaceRect.width;
+ nscoord availHeight;
if (aState.mUnconstrainedHeight) {
availHeight = NS_UNCONSTRAINEDSIZE;
}
@@ -1796,7 +1734,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
/* XXX get the height right! */
availHeight = aState.mAvailSpaceRect.height;
}
- aState.mInlineReflow->Init(x, aState.mY, availWidth, availHeight);
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ lineLayout->BeginLineReflow(x, aState.mY, availWidth, availHeight,
+ PR_FALSE /*XXX isTopOfPage*/);
// Notify observers that we are about to reflow the line
WillReflowLine(aState, aLine);
@@ -1863,6 +1803,9 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
rv = PlaceLine(aState, aLine, aKeepReflowGoing);
}
+ else {
+ lineLayout->EndLineReflow();
+ }
}
return rv;
@@ -2192,14 +2135,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_BLOCK == display->mDisplay) {
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": frame: ");
- nsFrame::ListTag(stdout, aFrame);
- printf(" followed by: ");
- nsFrame::ListTag(stdout, nextFrame);
- printf("\n");
-#endif
followingBlockFrame = (nsBlockFrame*) nextFrame;
break;
}
@@ -2217,30 +2152,6 @@ nsBlockFrame::FindFollowingBlockFrame(nsIFrame* aFrame)
return followingBlockFrame;
}
-#if XXX
-void
-nsBlockFrame::WillReflowFrame(nsBlockReflowState& aState,
- nsLineBox* aLine,
- nsIFrame* aFrame)
-{
- nsIStyleContext* kidSC;
- aFrame->GetStyleContext(kidSC);
- if (nsnull != kidSC) {
- nsIStyleContext* kidParentSC;
- kidParentSC = kidSC->GetParent();
- if (nsnull != kidParentSC) {
- if (kidParentSC != mStyleContext) {
- // The frame has changed situations so re-resolve its style
- // context in the new situation.
- aFrame->ReResolveStyleContext(&aState.mPresContext, mStyleContext);
- }
- NS_RELEASE(kidParentSC);
- }
- NS_RELEASE(kidSC);
- }
-}
-#endif
-
// XXX This should be a no-op when there is no first-line/letter style
// in force!
void
@@ -2305,15 +2216,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing)
{
NS_PRECONDITION(*aKeepReflowGoing, "bad caller");
- NS_PRECONDITION(0 == aState.mLineLayout->GetPlacedFrames(),
- "non-empty line with a block");
nsresult rv = NS_OK;
nsIFrame* frame = aLine->mFirstChild;
// Prepare the inline reflow engine
-//XXX nsBlockFrame* runInToFrame;
nsBlockFrame* compactWithFrame;
nscoord compactMarginWidth = 0;
PRBool isCompactFrame = PR_FALSE;
@@ -2321,38 +2229,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
switch (display->mDisplay) {
-#if XXX_runin
- case NS_STYLE_DISPLAY_RUN_IN:
-#ifdef NOISY_RUNIN
- ListTag(stdout);
- printf(": trying to see if ");
- aFrame->ListTag(stdout);
- printf(" is a run-in candidate\n");
-#endif
- runInToFrame = FindFollowingBlockFrame(frame);
- if (nsnull != runInToFrame) {
-// XXX run-in frame should be pushed to the next-in-flow too if the
-// run-in-to frame is pushed.
- nsRect r(0, aState.mY, 0, 0);
- aLine->mBounds = r;
- aLine->mCombinedArea = r;
- aLine->mCarriedOutTopMargin = 0;
- aLine->mCarriedOutBottomMargin = 0;
- aLine->SetMarginFlags(0);
-#if XXX_need_line_outside_children
- aLine->ClearOutsideChildren();
-#endif
- aLine->mBreakType = NS_STYLE_CLEAR_NONE;
-//XXX aFrame->WillReflow(aState.mPresContext);
- frame->SetRect(r);
- aState.mPrevChild = frame;
- aState.mRunInToFrame = runInToFrame;
- aState.mRunInFrame = (nsBlockFrame*) frame;
- return rv;
- }
- break;
-#endif
-
case NS_STYLE_DISPLAY_COMPACT:
compactWithFrame = FindFollowingBlockFrame(frame);
if (nsnull != compactWithFrame) {
@@ -2392,15 +2268,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
}
-#if XXX_runin
- // Set run-in frame if this is the run-in-to frame. That way the
- // target block frame knows to pick up the children from the run-in
- // frame.
- if (frame == aState.mRunInToFrame) {
- brc.SetRunInFrame(aState.mRunInFrame);
- }
-#endif
-
// Compute the available space for the block
nscoord availHeight = aState.mUnconstrainedHeight
? NS_UNCONSTRAINEDSIZE
@@ -2655,9 +2522,10 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
// Reflow the inline frame
+ nsLineLayout* lineLayout = aState.mLineLayout;
nsReflowStatus frameReflowStatus;
- nsresult rv = aState.mInlineReflow->ReflowFrame(aFrame, aState.IsAdjacentWithTop(),
- frameReflowStatus);
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &aState.mNextRCFrame,
+ frameReflowStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2822,8 +2690,8 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame)
{
- PRInt32 pushCount = aLine->ChildCount() -
- aState.mInlineReflow->GetCurrentFrameNum();
+ nsLineLayout* lineLayout = aState.mLineLayout;
+ PRInt32 pushCount = aLine->ChildCount() - lineLayout->GetCurrentSpanCount();
//printf("BEFORE (pushCount=%d):\n", pushCount);
//aLine->List(stdout, 0);
if (0 != pushCount) {
@@ -2858,10 +2726,10 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
to->SetIsBlock(aLine->IsBlock());
aLine->mChildCount -= pushCount;
- // Let inline reflow know that some frames are no longer part of
- // its state.
+ // Let line layout know that some frames are no longer part of its
+ // state.
if (!aLine->IsBlock()) {
- aState.mInlineReflow->ChangeFrameCount(aLine->ChildCount());
+ lineLayout->SplitLineTo(aLine->ChildCount());
}
#ifdef DEBUG
VerifyFrameCount(mLines);
@@ -2927,18 +2795,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// method is used for placing a line of inline frames. If the rare
// case is happening then the worst that will happen is that the
// bullet frame will be reflowed twice.
- nsInlineReflow& ir = *aState.mInlineReflow;
+ nsLineLayout* lineLayout = aState.mLineLayout;
PRBool addedBullet = PR_FALSE;
- if (HaveOutsideBullet() && (aLine == mLines) && !ir.IsZeroHeight()) {
+ if (HaveOutsideBullet() && (aLine == mLines) &&
+ !lineLayout->IsZeroHeight()) {
nsHTMLReflowMetrics metrics(nsnull);
ReflowBullet(aState, metrics);
- ir.AddFrame(mBullet, metrics);
+ lineLayout->AddBulletFrame(mBullet, metrics);
addedBullet = PR_TRUE;
}
- nscoord a, d;
- ir.VerticalAlignFrames(aLine->mBounds, a, d);
+ nsSize maxElementSize;
+ lineLayout->VerticalAlignFrames(aLine->mBounds, maxElementSize);
if (addedBullet) {
- ir.RemoveFrame(mBullet);
+ lineLayout->RemoveBulletFrame(mBullet);
}
#ifdef DEBUG_kipp
NS_ASSERTION((aLine->mBounds.YMost()) < 200000 && (aLine->mBounds.y > -200000), "oy");
@@ -2955,14 +2824,19 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#else
PRBool allowJustify = PR_FALSE;
#endif
- ir.TrimTrailingWhiteSpace(aLine->mBounds);
- ir.HorizontalAlignFrames(aLine->mBounds, allowJustify);
- ir.RelativePositionFrames(aLine->mCombinedArea);
+ lineLayout->TrimTrailingWhiteSpace(aLine->mBounds);
+ lineLayout->HorizontalAlignFrames(aLine->mBounds, allowJustify);
+ lineLayout->RelativePositionFrames(aLine->mCombinedArea);
// Calculate the bottom margin for the line.
nscoord lineBottomMargin = 0;
if (0 == aLine->mBounds.height) {
- nsIFrame* brFrame = aState.mLineLayout->GetBRFrame();
+ // XXX I don't think that this is necessary anymore because of the
+ // way that min-line-height is applied in the vertical alignment
+ // code; since we always have a line-height, a BR on its own line
+ // will get at least the default line-height amount of vertical
+ // space.
+ nsIFrame* brFrame = lineLayout->GetBRFrame();
if (nsnull != brFrame) {
// If a line ends in a BR, and the line is empty of height, then
// we make sure that the line ends up with some height
@@ -2984,43 +2858,32 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
}
}
- else {
- aState.mRunInFromFrame = nsnull;
- aState.mRunInToFrame = nsnull;
- }
// Calculate the lines top and bottom margin values. The margin will
// come from an embedded block frame, not from inline
// frames. Because this is an "inline" line, the child margins are
// all effectively zero so we pass in nsMargin(0, 0, 0, 0).
nscoord topMargin, bottomMargin;
+ nscoord cotm = lineLayout->GetCarriedOutTopMargin();
+ nscoord cobm = lineLayout->GetCarriedOutBottomMargin();
nsBlockReflowContext::CollapseMargins(nsMargin(0, 0, 0, 0),
- ir.GetCarriedOutTopMargin(),
- ir.GetCarriedOutBottomMargin(),
+ cotm, cobm,
aLine->mBounds.height,
aState.mPrevBottomMargin,
topMargin, bottomMargin);
-#if XXX
-ListTag(stdout);
-printf(": ");
-((nsFrame*)(aLine->mFirstChild))->ListTag(stdout);
-printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
- aState.mY, ir.GetCarriedOutTopMargin(), ir.GetCarriedOutBottomMargin(),
- topMargin, bottomMargin, aState.mPrevBottomMargin,
- aState.ShouldApplyTopMargin() ? "yes" : "no");
-#endif
if (!aState.ShouldApplyTopMargin()) {
aState.mCarriedOutTopMargin = topMargin;
topMargin = 0;
}
+ lineLayout->EndLineReflow();
+#ifdef DEBUG
+ lineLayout = nsnull;
+#endif
// See if the line fit. If it doesn't we need to push it. Our first
// line will always fit.
nscoord newY = aLine->mBounds.YMost() + topMargin + lineBottomMargin;
- NS_FRAME_TRACE(NS_FRAME_TRACE_CHILD_REFLOW,
- ("nsBlockFrame::PlaceLine: newY=%d limit=%d lineHeight=%d",
- newY, aState.mBottomEdge, aLine->mBounds.height));
if ((mLines != aLine) && (newY > aState.mBottomEdge)) {
// Push this line and all of it's children and anything else that
// follows to our next-in-flow
@@ -3037,8 +2900,8 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
return rv;
}
- aLine->mCarriedOutTopMargin = ir.GetCarriedOutTopMargin();
- aLine->mCarriedOutBottomMargin = ir.GetCarriedOutBottomMargin();
+ aLine->mCarriedOutTopMargin = cotm;
+ aLine->mCarriedOutBottomMargin = cobm;
aState.mPrevBottomMargin = bottomMargin;
if (0 != topMargin) {
// Apply collapsed top-margin value
@@ -3048,7 +2911,7 @@ printf(" mY=%d carried=%d,%d top=%d bottom=%d prev=%d shouldApply=%s\n",
}
aState.mY = newY;
- PostPlaceLine(aState, aLine, ir.GetMaxElementSize());
+ PostPlaceLine(aState, aLine, maxElementSize);
// Any below current line floaters to place?
if (0 != aState.mPendingFloaters.Count()) {
@@ -3094,8 +2957,8 @@ nsBlockFrame::ComputeLineMaxElementSize(nsBlockReflowState& aState,
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
- nsLineBox* aLine,
- const nsSize& aMaxElementSize)
+ nsLineBox* aLine,
+ const nsSize& aMaxElementSize)
{
// Update max-element-size
if (aState.mComputeMaxElementSize) {
@@ -3355,7 +3218,6 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
if (nsnull != lastFrame) {
lastFrame->SetNextSibling(aNewFrame);
}
- nsresult rv;
// Make sure that new inlines go onto the end of the lastLine when
// the lastLine is mapping inline frames.
@@ -3371,19 +3233,7 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext,
for (nsIFrame* frame = aNewFrame; nsnull != frame;
frame->GetNextSibling(&frame)) {
// See if the child is a block or non-block
- const nsStyleDisplay* kidDisplay;
- rv = frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) kidDisplay);
- if (NS_OK != rv) {
- return rv;
- }
- const nsStylePosition* kidPosition;
- rv = frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) kidPosition);
- if (NS_OK != rv) {
- return rv;
- }
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(frame);
// If the child is an inline then add it to the lastLine (if it's
// an inline line, otherwise make a new line). If the child is a
@@ -3517,15 +3367,8 @@ nsBlockFrame::InsertNewFrames(nsIPresContext& aPresContext,
nsIFrame* next;
newFrame->GetNextSibling(&next);
newFrame->SetNextSibling(nsnull);
-
- const nsStyleDisplay* display;
- newFrame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- newFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
PRUint16 newFrameIsBlock =
- nsLineLayout::TreatFrameAsBlock(display, position)
+ nsLineLayout::TreatFrameAsBlock(newFrame)
? LINE_IS_BLOCK
: 0;
@@ -4092,7 +3935,7 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
- if (0 == mLineLayout->GetPlacedFrames()) {
+ if (mLineLayout->LineIsEmpty()) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsBlockReflowState::AddFloater: IsLeftMostChild, placeHolder=%p",
aPlaceholder));
@@ -4118,11 +3961,11 @@ nsBlockReflowState::AddFloater(nsPlaceholderFrame* aPlaceholder,
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
- mLineLayout->UpdateInlines(mAvailSpaceRect.x + BorderPadding().left,
- mY,
- mAvailSpaceRect.width,
- mAvailSpaceRect.height,
- isLeftFloater);
+ mLineLayout->UpdateBand(mAvailSpaceRect.x + BorderPadding().left,
+ mY,
+ mAvailSpaceRect.width,
+ mAvailSpaceRect.height,
+ isLeftFloater);
// Restore coordinate system
mSpaceManager->Translate(dx, dy);
@@ -4797,9 +4640,9 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
- nsLineLayout textRunThingy(aPresContext, nsnull);
+ nsLineLayout textRunThingy(aPresContext);
- // Ask each child that implements nsIInlineReflow to find its text runs
+ // Ask each child to find its text runs
nsLineBox* line = mLines;
while (nsnull != line) {
if (!line->IsBlock()) {
@@ -4822,8 +4665,8 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
}
}
else {
- // A frame that doesn't implement nsIInlineReflow isn't text
- // therefore it will end an open text run.
+ // A block frame isn't text therefore it will end an open text
+ // run.
textRunThingy.EndTextRun();
}
line = line->mNext;
@@ -4835,39 +4678,6 @@ nsBlockFrame::ComputeTextRuns(nsIPresContext& aPresContext)
return NS_OK;
}
-void
-nsBlockFrame::TakeRunInFrames(nsBlockFrame* aRunInFrame)
-{
- // Simply steal the run-in-frame's line list and make it our
- // own. XXX Very similar to the logic in DrainOverflowLines...
- nsLineBox* line = aRunInFrame->mLines;
-
- // Make all the frames on the mOverflowLines list mine
- nsIFrame* lastFrame = nsnull;
- nsIFrame* frame = line->mFirstChild;
- while (nsnull != frame) {
- frame->SetParent(this);
- lastFrame = frame;
- frame->GetNextSibling(&frame);
- }
-
- // Join the line lists
- if (nsnull == mLines) {
- mLines = line;
- }
- else {
- // Join the sibling lists together
- lastFrame->SetNextSibling(mLines->mFirstChild);
-
- // Place overflow lines at the front of our line list
- nsLineBox* lastLine = nsLineBox::LastLine(line);
- lastLine->mNext = mLines;
- mLines = line;
- }
-
- aRunInFrame->mLines = nsnull;
-}
-
//----------------------------------------------------------------------
nsresult
@@ -5065,29 +4875,6 @@ nsAnonymousBlockFrame::RemoveFramesFrom(nsIFrame* aFrame)
#endif
}
-#if 0
-nscoord
-nsBlockFrame::ComputeCollapsedTopMargin(const nsHTMLReflowState& aReflowState)
-{
- nscoord myTopMargin = aReflowState.computedMargin.top;
- nsLineBox* line = mLines;
- if (nsnull != line) {
- if (line->IsEmptyLine()) {
- line = line->mNext;
- if (nsnull == line) {
- return myTopMargin;
- }
- }
- if (1 == line->ChildCount()) {
- nsHTMLReflowState rs();
- nscoord topMargin = line->mFirstChild->ComputeCollapsedTopMargin(rs);
- return nsBlockReflowContext::MaxMargin(topMargin, myTopMargin);
- }
- }
- return myTopMargin;
-}
-#endif
-
#ifdef DEBUG
void
nsBlockFrame::VerifyFrameCount(nsLineBox* line)
diff --git a/mozilla/layout/html/base/src/nsBulletFrame.cpp b/mozilla/layout/html/base/src/nsBulletFrame.cpp
index 6556ddb693a..23e1ae86183 100644
--- a/mozilla/layout/html/base/src/nsBulletFrame.cpp
+++ b/mozilla/layout/html/base/src/nsBulletFrame.cpp
@@ -71,6 +71,7 @@ nsBulletFrame::Paint(nsIPresContext& aCX,
if (disp->mVisible) {
const nsStyleList* myList =
(const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List);
+ PRUint8 listStyleType = myList->mListStyleType;
if (myList->mListStyleImage.Length() > 0) {
nsIImage* image = mImageLoader.GetImage();
@@ -81,11 +82,14 @@ nsBulletFrame::Paint(nsIPresContext& aCX,
}
}
else {
- nsRect innerArea(mPadding.left, mPadding.top,
- mRect.width - (mPadding.left + mPadding.right),
- mRect.height - (mPadding.top + mPadding.bottom));
- aRenderingContext.DrawImage(image, innerArea);
- return NS_OK;
+ if (!mImageLoader.GetLoadImageFailed()) {
+ nsRect innerArea(mPadding.left, mPadding.top,
+ mRect.width - (mPadding.left + mPadding.right),
+ mRect.height - (mPadding.top + mPadding.bottom));
+ aRenderingContext.DrawImage(image, innerArea);
+ return NS_OK;
+ }
+ listStyleType = NS_STYLE_LIST_STYLE_DISC;
}
}
@@ -98,7 +102,7 @@ nsBulletFrame::Paint(nsIPresContext& aCX,
aRenderingContext.SetColor(myColor->mColor);
nsAutoString text;
- switch (myList->mListStyleType) {
+ switch (listStyleType) {
case NS_STYLE_LIST_STYLE_NONE:
break;
diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp
index 346e7a44e47..c539e0fa6f4 100644
--- a/mozilla/layout/html/base/src/nsFrame.cpp
+++ b/mozilla/layout/html/base/src/nsFrame.cpp
@@ -1048,17 +1048,6 @@ nsFrame::MoveInSpaceManager(nsIPresContext& aPresContext,
return NS_OK;
}
-NS_IMETHODIMP
-nsFrame::VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedRect)
-{
- aCombinedRect = mRect;
- return NS_OK;
-}
-
NS_IMETHODIMP
nsFrame::ContentChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
diff --git a/mozilla/layout/html/base/src/nsFrame.h b/mozilla/layout/html/base/src/nsFrame.h
index e2e93645efb..7bf0d2a163a 100644
--- a/mozilla/layout/html/base/src/nsFrame.h
+++ b/mozilla/layout/html/base/src/nsFrame.h
@@ -234,11 +234,6 @@ public:
NS_IMETHOD MoveInSpaceManager(nsIPresContext& aPresContext,
nsISpaceManager* aSpaceManager,
nscoord aDeltaX, nscoord aDeltaY);
- NS_IMETHOD VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedRect);
// Selection Methods
// XXX Doc me... (in nsIFrame.h puhleeze)
diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp
index 25e4695569b..66e78923f61 100644
--- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp
@@ -115,7 +115,7 @@ nsHTMLContainerFrame::CreateNextInFlow(nsIPresContext& aPresContext,
nextInFlow->SetNextSibling(nextFrame);
NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES,
- ("nsInlineReflow::MaybeCreateNextInFlow: frame=%p nextInFlow=%p",
+ ("nsHTMLContainerFrame::MaybeCreateNextInFlow: frame=%p nextInFlow=%p",
aFrame, nextInFlow));
aNextInFlowResult = nextInFlow;
diff --git a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp
index 66732bed96f..568cf6534a7 100644
--- a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp
+++ b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp
@@ -126,7 +126,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext& aPresContext,
void
nsHTMLReflowState::Init(nsIPresContext& aPresContext)
{
- mRunInFrame = nsnull;
mCompactMarginWidth = 0;
mAlignCharOffset = 0;
mUseAlignCharOffset = 0;
@@ -1119,25 +1118,23 @@ nsHTMLReflowState::CalcLineHeight(nsIPresContext& aPresContext,
sc->GetStyleData(eStyleStruct_Text);
if (nsnull != text) {
nsStyleUnit unit = text->mLineHeight.GetUnit();
- if (eStyleUnit_Enumerated == unit) {
- // Normal value; we use 1.0 for normal
- // XXX could come from somewhere else
+ if (eStyleUnit_Normal == unit) {
+ // Normal value; we use a factor of 1.0 for normal
+ lineHeight = elementFont->mFont.size;
#ifdef NOISY_VERTICAL_ALIGN
- printf(" line-height: normal\n");
+ printf(" line-height: normal result=%d\n", lineHeight);
#endif
break;
} else if (eStyleUnit_Factor == unit) {
- if (nsnull != elementFont) {
- // CSS2 spec says that the number is inherited, not the
- // computed value. Therefore use the font size of the
- // element times the inherited number.
- nscoord size = elementFont->mFont.size;
- lineHeight = nscoord(size * text->mLineHeight.GetFactorValue());
+ // CSS2 spec says that the number is inherited, not the
+ // computed value. Therefore use the font size of the
+ // element times the inherited number.
+ nscoord size = elementFont->mFont.size;
+ lineHeight = nscoord(size * text->mLineHeight.GetFactorValue());
#ifdef NOISY_VERTICAL_ALIGN
- printf(" line-height: factor=%g result=%d\n",
- text->mLineHeight.GetFactorValue(), lineHeight);
+ printf(" line-height: factor=%g result=%d\n",
+ text->mLineHeight.GetFactorValue(), lineHeight);
#endif
- }
break;
}
else if (eStyleUnit_Coord == unit) {
diff --git a/mozilla/layout/html/base/src/nsIHTMLReflow.h b/mozilla/layout/html/base/src/nsIHTMLReflow.h
index 00e1ff5e5f4..d7603b8a2c8 100644
--- a/mozilla/layout/html/base/src/nsIHTMLReflow.h
+++ b/mozilla/layout/html/base/src/nsIHTMLReflow.h
@@ -171,9 +171,6 @@ struct nsHTMLReflowState : nsReflowState {
nscoord mComputedMinWidth, mComputedMaxWidth;
nscoord mComputedMinHeight, mComputedMaxHeight;
- // Run-in frame made available for reflow
- nsBlockFrame* mRunInFrame;
-
// Compact margin available space
nscoord mCompactMarginWidth;
@@ -428,16 +425,6 @@ public:
NS_IMETHOD MoveInSpaceManager(nsIPresContext& aPresContext,
nsISpaceManager* aSpaceManager,
nscoord aDeltaX, nscoord aDeltaY) = 0;
-
- NS_IMETHOD VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aReflowState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedRect) = 0;
-
-#if 0
- NS_IMETHOD RelativePositionFrames(nsRect& aCombinedArea) = 0;
-#endif
};
#endif /* nsIHTMLReflow_h___ */
diff --git a/mozilla/layout/html/base/src/nsImageMap.cpp b/mozilla/layout/html/base/src/nsImageMap.cpp
index 4f794005e40..31850c74fd0 100644
--- a/mozilla/layout/html/base/src/nsImageMap.cpp
+++ b/mozilla/layout/html/base/src/nsImageMap.cpp
@@ -77,8 +77,8 @@ public:
nsString mAltText;
nscoord* mCoords;
PRInt32 mNumCoords;
- PRBool mHasURL;
PRBool mSuppressFeedback;
+ PRBool mHasURL;
};
Area::Area(const nsString& aBaseURL, const nsString& aHREF,
@@ -753,7 +753,7 @@ nsImageMap::UpdateAreas()
// Get rid of old area data
FreeAreas();
- nsresult rv;
+ nsresult rv = NS_OK;
nsIContent* child;
PRInt32 i, n;
PRBool containsBlock = PR_FALSE, containsArea = PR_FALSE;
diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp
index aa3fb212cc7..67e433c8bd6 100644
--- a/mozilla/layout/html/base/src/nsInlineFrame.cpp
+++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp
@@ -20,7 +20,6 @@
#include "nsFrameList.h"
#include "nsBlockReflowContext.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsHTMLIIDs.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLParts.h"
@@ -28,6 +27,8 @@
#include "nsIStyleContext.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
+#include "nsIRenderingContext.h"
+#include "nsIFontMetrics.h"
// XXX TODO:
// append/insert/remove floater testing
@@ -35,7 +36,7 @@
// Theory of operation:
// XXX write this
-#ifdef NS_DEBUG
+#ifdef DEBUG
#undef NOISY_ANON_BLOCK
#else
#undef NOISY_ANON_BLOCK
@@ -89,17 +90,11 @@ public:
nsIRenderingContext& aRC,
nscoord& aDeltaWidth);
#endif
- NS_IMETHOD VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aParentReflowState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedArea);
protected:
// Additional reflow state used during our reflow methods
struct InlineReflowState {
nsIFrame* mNextRCFrame;
- nsInlineReflow* mInlineReflow;
nsIFrame* mPrevFrame;
nsInlineFrame* mNextInFlow;
};
@@ -1184,13 +1179,15 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
+ if (nsnull == aReflowState.lineLayout) {
+ return NS_ERROR_INVALID_ARG;
+ }
DrainOverflow();
// Set our own reflow state (additional state above and beyond
// aReflowState)
InlineReflowState irs;
irs.mPrevFrame = nsnull;
- irs.mInlineReflow = nsnull;
irs.mNextInFlow = (nsInlineFrame*) mNextInFlow;
if (eReflowReason_Incremental == aReflowState.reason) {
// Peel off the next frame in the path if this is an incremental
@@ -1228,8 +1225,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
}
if (HaveAnonymousBlock()) {
- if ((nsnull != aReflowState.lineLayout) &&
- (0 != aReflowState.lineLayout->GetPlacedFrames())) {
+ if (!aReflowState.lineLayout->LineIsEmpty()) {
// This inline frame cannot be placed on the current line
// because there already is an inline frame on this line (and we
// contain an anonymous block).
@@ -1239,30 +1235,27 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
else {
rv = ReflowBlockFrame(aPresContext, aReflowState, irs,
aMetrics, aStatus);
+
+ // If the combined area of our children exceeds our bounding box
+ // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear
+ // it.
+ if ((aMetrics.mCombinedArea.x < 0) ||
+ (aMetrics.mCombinedArea.y < 0) ||
+ (aMetrics.mCombinedArea.XMost() > aMetrics.width) ||
+ (aMetrics.mCombinedArea.YMost() > aMetrics.height)) {
+ mState |= NS_FRAME_OUTSIDE_CHILDREN;
+ }
+ else {
+ mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
+ }
}
}
else {
- if (nsnull != aReflowState.lineLayout) {
- rv = ReflowInlineFrames(aPresContext, aReflowState, irs,
- aMetrics, aStatus);
- }
- else {
- rv = NS_ERROR_NULL_POINTER;
- }
- }
-
- if (NS_SUCCEEDED(rv)) {
- // If the combined area of our children exceeds our bounding box
- // then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it.
- if ((aMetrics.mCombinedArea.x < 0) ||
- (aMetrics.mCombinedArea.y < 0) ||
- (aMetrics.mCombinedArea.XMost() > aMetrics.width) ||
- (aMetrics.mCombinedArea.YMost() > aMetrics.height)) {
- mState |= NS_FRAME_OUTSIDE_CHILDREN;
- }
- else {
- mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
- }
+ rv = ReflowInlineFrames(aPresContext, aReflowState, irs,
+ aMetrics, aStatus);
+ // Note: when we are reflowing inline frames the line layout code
+ // will properly compute our NS_FRAME_OUTSIDE_CHILDREN state for
+ // us.
}
return rv;
@@ -1288,114 +1281,6 @@ nsInlineFrame::FindTextRuns(nsLineLayout& aLineLayout)
return NS_OK;
}
-// Perform pass2 vertical alignment on top/bottom aligned child frames
-// XXX relative positioning will need to be done *after* this
-NS_IMETHODIMP
-nsInlineFrame::VerticalAlignFrames(nsIPresContext& aPresContext,
- const nsHTMLReflowState& aParentReflowState,
- nscoord aLineHeight,
- nscoord aDistanceFromTopEdge,
- nsRect& aCombinedArea)
-{
- if (HaveAnonymousBlock()) {
- // This should be impossible - when we have an inline frame and it
- // contains an anonymous block, none of the blocks children or the
- // block itself will trigger a pass2 valign at this level.
- NS_NOTREACHED("can't get here");
- aCombinedArea = mRect;
- return NS_OK;
- }
-
- // topEdge is the y coordinate of the line's top, relative to this
- // frame (== in this frames local coordinate system).
- nscoord topEdge = -aDistanceFromTopEdge;
-
- nsRect bbox, childCombinedArea;
- nscoord x0 = 0;
- nscoord y0 = 0;
- nscoord x1 = mRect.width;
- nscoord y1 = mRect.height;
- nsIFrame* frame = mFrames.FirstChild();
- while (nsnull != frame) {
- const nsStyleText* textStyle;
- frame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
- nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
- frame->GetRect(bbox);
-
- if (eStyleUnit_Enumerated == verticalAlignUnit) {
- PRUint8 verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
- if (NS_STYLE_VERTICAL_ALIGN_TOP == verticalAlignEnum) {
- nsMargin margin;
- nsHTMLReflowState::ComputeMarginFor(frame, &aParentReflowState,
- margin);
- nsCSSFrameType frameType =
- nsHTMLReflowState::DetermineFrameType(frame);
- bbox.y = topEdge + margin.top;
- if (NS_CSS_FRAME_TYPE_INLINE == frameType) {
- nsMargin bp;
- nsHTMLReflowState::ComputeBorderPaddingFor(frame,
- &aParentReflowState, bp);
- bbox.y -= bp.top;
- }
- frame->SetRect(bbox);
- }
- else if (NS_STYLE_VERTICAL_ALIGN_BOTTOM == verticalAlignEnum) {
- nsMargin margin;
- nsHTMLReflowState::ComputeMarginFor(frame, &aParentReflowState,
- margin);
- nsCSSFrameType frameType =
- nsHTMLReflowState::DetermineFrameType(frame);
- bbox.y = topEdge + aLineHeight - bbox.height - margin.bottom;
- if (NS_CSS_FRAME_TYPE_INLINE == frameType) {
- nsMargin bp;
- nsHTMLReflowState::ComputeBorderPaddingFor(frame,
- &aParentReflowState, bp);
- bbox.y += bp.bottom;
- }
- frame->SetRect(bbox);
- }
- }
-
- // Perform pass2 vertical alignment for top/bottom aligned
- // frames that are not our direct descendants.
- nsIHTMLReflow* ihr;
- nsresult rv = frame->QueryInterface(kIHTMLReflowIID, (void**)&ihr);
- if (NS_SUCCEEDED(rv)) {
- nsSize availSize(0, 0);
- // XXX whacky: we should be passing in the childs reflow state, right?
- nsHTMLReflowState ourReflowState(aPresContext, aParentReflowState,
- this, availSize);
- nscoord distanceFromTopEdge = bbox.y - topEdge;
- ihr->VerticalAlignFrames(aPresContext, ourReflowState, aLineHeight,
- distanceFromTopEdge, childCombinedArea);
- nscoord x = childCombinedArea.x;
- if (x < x0) x0 = x;
- nscoord y = childCombinedArea.y;
- if (y < y0) y0 = y;
- nscoord xmost = childCombinedArea.XMost();
- if (xmost > x1) x1 = xmost;
- nscoord ymost = childCombinedArea.YMost();
- if (ymost > y1) y1 = ymost;
- }
-
- frame->GetNextSibling(&frame);
- }
-
- aCombinedArea.x = mRect.x + x0;
- aCombinedArea.y = mRect.y + y0;
- aCombinedArea.width = x1 - x0;
- aCombinedArea.height = y1 - y0;
-
- // Update our outside-children flag bit
- if ((x0 < 0) || (y0 < 0) || (x1 > mRect.width) || (y1 > mRect.height)) {
- mState |= NS_FRAME_OUTSIDE_CHILDREN;
- }
- else {
- mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
- }
- return NS_OK;
-}
-
void
nsInlineFrame::DrainOverflow()
{
@@ -1427,35 +1312,19 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
nsresult rv = NS_OK;
aStatus = NS_FRAME_COMPLETE;
- nsInlineReflow ir(*aReflowState.lineLayout, aReflowState, this, PR_FALSE,
- nsnull != aMetrics.maxElementSize);
- irs.mInlineReflow = &ir;
- ir.SetNextRCFrame(irs.mNextRCFrame);
- aReflowState.lineLayout->PushInline(&ir);
-
- // Compute available area
- nscoord x = aReflowState.mComputedBorderPadding.left;
+ nsLineLayout* lineLayout = aReflowState.lineLayout;
+ nscoord leftEdge = 0;
+ if (nsnull == mPrevInFlow) {
+ leftEdge = aReflowState.mComputedBorderPadding.left;
+ }
nscoord availableWidth = aReflowState.availableWidth;
if (NS_UNCONSTRAINEDSIZE != availableWidth) {
- if (nsnull != mPrevInFlow) {
- x = 0;
- availableWidth -= aReflowState.mComputedBorderPadding.right +
- aReflowState.computedMargin.right;
- }
- else {
- availableWidth -= aReflowState.mComputedBorderPadding.left +
- aReflowState.computedMargin.left +
- aReflowState.mComputedBorderPadding.right +
- aReflowState.computedMargin.right;
- }
+ // Subtract off left and right border+padding from availableWidth
+ availableWidth -= leftEdge;
+ availableWidth -= aReflowState.mComputedBorderPadding.right;
}
- nscoord y = aReflowState.mComputedBorderPadding.top;
- nscoord availableHeight = aReflowState.availableHeight;
- if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
- availableHeight -= aReflowState.mComputedBorderPadding.top +
- aReflowState.mComputedBorderPadding.right;
- }
- ir.Init(x, y, availableWidth, availableHeight);
+ lineLayout->BeginSpan(this, &aReflowState,
+ leftEdge, leftEdge + availableWidth);
// First reflow our current children
nsIFrame* frame = mFrames.FirstChild();
@@ -1489,37 +1358,99 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
irs.mPrevFrame = frame;
}
}
-
- // Compute final metrics
- if (NS_SUCCEEDED(rv)) {
-#ifdef NS_DEBUG
- if (NS_FRAME_COMPLETE == aStatus) {
- // We can't be complete AND have overflow frames!
- NS_ASSERTION(mOverflowFrames.IsEmpty(), "whoops");
- }
+#ifdef DEBUG
+ if (NS_FRAME_COMPLETE == aStatus) {
+ // We can't be complete AND have overflow frames!
+ NS_ASSERTION(mOverflowFrames.IsEmpty(), "whoops");
+ }
#endif
- nsInlineReflow* ir = irs.mInlineReflow;
- nsRect bbox;
- ir->VerticalAlignFrames(bbox, aMetrics.ascent, aMetrics.descent);
- ir->RelativePositionFrames(aMetrics.mCombinedArea);
- aMetrics.width = bbox.XMost();
+
+ // If after reflowing our children they take up no area then make
+ // sure that we don't either.
+ nsSize size;
+ lineLayout->EndSpan(this, size, aMetrics.maxElementSize);
+ if ((0 == size.height) && (0 == size.width)) {
+ aMetrics.width = 0;
+ aMetrics.height = 0;
+ aMetrics.ascent = 0;
+ aMetrics.descent = 0;
+ if (nsnull != aMetrics.maxElementSize) {
+ aMetrics.maxElementSize->width = 0;
+ aMetrics.maxElementSize->height = 0;
+ }
+ }
+ else {
+ // Compute final width
+ aMetrics.width = size.width;
+ if (nsnull == mPrevInFlow) {
+ aMetrics.width += aReflowState.mComputedBorderPadding.left;
+ }
if (NS_FRAME_IS_COMPLETE(aStatus)) {
aMetrics.width += aReflowState.mComputedBorderPadding.right;
}
- aMetrics.height = bbox.height + aReflowState.mComputedBorderPadding.top +
+
+ // Compute final height. The height of our box is the sum of our
+ // font size plus the top and bottom border and padding. The height
+ // of children do not affect our height.
+ //
+ // Note 2: we use the actual font height for sizing our selves instead
+ // of the computed font height. On systems where they disagree the
+ // actual font height is more appropriate.
+ const nsStyleFont* font;
+ GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)font);
+ aReflowState.rendContext->SetFont(font->mFont);
+ nsIFontMetrics* fm;
+ aReflowState.rendContext->GetFontMetrics(fm);
+ fm->GetMaxAscent(aMetrics.ascent);
+ fm->GetMaxDescent(aMetrics.descent);
+ fm->GetHeight(aMetrics.height);
+ aMetrics.ascent += aReflowState.mComputedBorderPadding.top;
+ aMetrics.descent += aReflowState.mComputedBorderPadding.bottom;
+ aMetrics.height += aReflowState.mComputedBorderPadding.top +
aReflowState.mComputedBorderPadding.bottom;
-#ifdef NOISY_FINAL_SIZE
- ListTag(stdout);
- printf(": metrics=%d,%d ascent=%d descent=%d\n",
- aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent);
-#endif
- aMetrics.mCarriedOutTopMargin = 0;
- aMetrics.mCarriedOutBottomMargin = 0;
- if (nsnull != aMetrics.maxElementSize) {
- *aMetrics.maxElementSize = ir->GetMaxElementSize();
+
+#if defined(DEBUG) && defined(XP_UNIX)
+ static PRBool useComputedHeight = PR_FALSE;
+ static PRBool firstTime = 1;
+ if (firstTime) {
+ if (getenv("GECKO_USE_COMPUTED_HEIGHT")) {
+ useComputedHeight = PR_TRUE;
+ }
}
+ if (useComputedHeight) {
+ // Special debug code that violates the above CSS2 spec
+ // clarification. Why? So that we can predictably compute the values
+ // for testing layout.
+ nscoord computedHeight = aReflowState.mComputedBorderPadding.top +
+ aReflowState.mComputedBorderPadding.bottom +
+ font->mFont.size;
+ if (computedHeight != aMetrics.height) {
+ if (0 == (mState & 0x80000000)) {
+ nsFrame::ListTag(stdout, this);
+ printf(": using computedHeight %d instead of actual height %d\n",
+ computedHeight, aMetrics.height);
+ mState |= 0x80000000;
+ }
+ aMetrics.height = computedHeight;
+ }
+ }
+#endif
+
+ NS_RELEASE(fm);
}
- aReflowState.lineLayout->PopInline();
+
+ // For now our combined area is zero. The real value will be
+ // computed during vertical alignment of the line we are on.
+ aMetrics.mCombinedArea.x = 0;
+ aMetrics.mCombinedArea.y = 0;
+ aMetrics.mCombinedArea.width = aMetrics.width;
+ aMetrics.mCombinedArea.height = aMetrics.height;
+
+#ifdef NOISY_FINAL_SIZE
+ ListTag(stdout);
+ printf(": metrics=%d,%d ascent=%d descent=%d\n",
+ aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent);
+#endif
return rv;
}
@@ -1543,8 +1474,8 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
return NS_OK;
}
- nsInlineReflow* ir = irs.mInlineReflow;
- nsresult rv = ir->ReflowFrame(aFrame, PR_FALSE/* XXX */, aStatus);
+ nsLineLayout* lineLayout = aReflowState.lineLayout;
+ nsresult rv = lineLayout->ReflowFrame(aFrame, &irs.mNextRCFrame, aStatus);
if (NS_FAILED(rv)) {
return rv;
}
@@ -1656,7 +1587,7 @@ nsInlineFrame::PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
{
NS_PRECONDITION(nsnull != aFromChild, "null pointer");
NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child");
-#ifdef NS_DEBUG
+#ifdef DEBUG
nsIFrame* prevNextSibling;
aPrevSibling->GetNextSibling(&prevNextSibling);
NS_PRECONDITION(prevNextSibling == aFromChild, "bad prev sibling");
diff --git a/mozilla/layout/html/base/src/nsInlineReflow.cpp b/mozilla/layout/html/base/src/nsInlineReflow.cpp
index e44087d8f0f..d07e8a5074a 100644
--- a/mozilla/layout/html/base/src/nsInlineReflow.cpp
+++ b/mozilla/layout/html/base/src/nsInlineReflow.cpp
@@ -1,3 +1,4 @@
+#if 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
@@ -657,6 +658,14 @@ nsInlineReflow::VerticalAlignFrames(nsRect& aLineBox,
nscoord& aMaxAscent,
nscoord& aMaxDescent)
{
+#if 1
+ aLineBox.x = mLeftEdge;
+ aLineBox.y = mTopEdge;
+ aLineBox.width = mX - mLeftEdge;
+ aLineBox.height = mMinLineHeight;
+ aMaxAscent = 0;
+ aMaxDescent = 0;
+#else
PerFrameData* pfd0 = mFrameDataBase;
PerFrameData* end = pfd0 + mFrameNum;
@@ -1011,6 +1020,7 @@ nsInlineReflow::VerticalAlignFrames(nsRect& aLineBox,
aLineBox.x, aLineBox.y, aLineBox.width, aLineBox.height,
aMaxAscent, aMaxDescent);
#endif
+#endif
}
void
@@ -1230,3 +1240,4 @@ nsInlineReflow::JustifyFrames(nscoord aMaxWidth, nsRect& aLineBox)
}
}
}
+#endif
diff --git a/mozilla/layout/html/base/src/nsInlineReflow.h b/mozilla/layout/html/base/src/nsInlineReflow.h
index a64bb35aabf..b8b85134f92 100644
--- a/mozilla/layout/html/base/src/nsInlineReflow.h
+++ b/mozilla/layout/html/base/src/nsInlineReflow.h
@@ -1,3 +1,4 @@
+#if 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
@@ -109,6 +110,10 @@ public:
return mRightEdge - mX;
}
+ nscoord GetWidth() const {
+ return mX - mLeftEdge;
+ }
+
PRBool IsZeroHeight() const;
protected:
@@ -193,3 +198,4 @@ protected:
};
#endif /* nsInlineReflow_h___ */
+#endif
diff --git a/mozilla/layout/html/base/src/nsLineBox.cpp b/mozilla/layout/html/base/src/nsLineBox.cpp
index 251458a8c4d..004c3820b71 100644
--- a/mozilla/layout/html/base/src/nsLineBox.cpp
+++ b/mozilla/layout/html/base/src/nsLineBox.cpp
@@ -46,16 +46,19 @@ nsLineBox::~nsLineBox()
static void
ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
{
+ nsAutoString frameName;
PRInt32 j, i, n = aFloaters->Count();
for (i = 0; i < n; i++) {
for (j = aIndent; --j >= 0; ) fputs(" ", out);
nsPlaceholderFrame* ph = (nsPlaceholderFrame*) aFloaters->ElementAt(i);
if (nsnull != ph) {
- fprintf(out, "placeholder@%p\n", ph);
+ fprintf(out, "placeholder@%p ", ph);
nsIFrame* frame = ph->GetAnchoredItem();
if (nsnull != frame) {
- frame->List(out, aIndent + 1);
+ frame->GetFrameName(frameName);
+ fputs(frameName, out);
}
+ fprintf(out, "\n");
}
}
}
@@ -277,14 +280,7 @@ nsLineBox::UnplaceFloaters(nsISpaceManager* aSpaceManager)
PRBool
nsLineBox::CheckIsBlock() const
{
- nsIFrame* frame = mFirstChild;
- const nsStyleDisplay* display;
- frame->GetStyleData(eStyleStruct_Display,
- (const nsStyleStruct*&) display);
- const nsStylePosition* position;
- frame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
- PRBool isBlock = nsLineLayout::TreatFrameAsBlock(display, position);
+ PRBool isBlock = nsLineLayout::TreatFrameAsBlock(mFirstChild);
return isBlock == IsBlock();
}
#endif
diff --git a/mozilla/layout/html/base/src/nsLineLayout.cpp b/mozilla/layout/html/base/src/nsLineLayout.cpp
index 9a7cb8d366f..274f605c6b8 100644
--- a/mozilla/layout/html/base/src/nsLineLayout.cpp
+++ b/mozilla/layout/html/base/src/nsLineLayout.cpp
@@ -16,12 +16,38 @@
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
+#include "nsCOMPtr.h"
#include "nsLineLayout.h"
-#include "nsInlineReflow.h"
#include "nsStyleConsts.h"
+#include "nsHTMLContainerFrame.h"
+#include "nsHTMLIIDs.h"
+#include "nsISpaceManager.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIFontMetrics.h"
+#include "nsIRenderingContext.h"
+
+#ifdef DEBUG
+#undef NOISY_HORIZONTAL_ALIGN
+#undef REALLY_NOISY_HORIZONTAL_ALIGN
+#undef NOISY_VERTICAL_ALIGN
+#undef REALLY_NOISY_VERTICAL_ALIGN
+#undef NOISY_REFLOW
+#undef REALLY_NOISY_REFLOW
+#undef NOISY_PUSHING
+#undef REALLY_NOISY_PUSHING
+#define DEBUG_ADD_TEXT
+#else
+#undef NOISY_HORIZONTAL_ALIGN
+#undef REALLY_NOISY_HORIZONTAL_ALIGN
+#undef NOISY_VERTICAL_ALIGN
+#undef REALLY_NOISY_VERTICAL_ALIGN
+#undef NOISY_REFLOW
+#undef REALLY_NOISY_REFLOW
+#undef NOISY_PUSHING
+#undef REALLY_NOISY_PUSHING
+#undef DEBUG_ADD_TEXT
+#endif
nsTextRun::nsTextRun()
{
@@ -44,96 +70,1716 @@ nsTextRun::List(FILE* out, PRInt32 aIndent)
nsAutoString tmp;
text->GetFrameName(tmp);
fputs(tmp, out);
- printf(" ");
+ printf("@%p ", text);
}
fputs(">\n", out);
}
//----------------------------------------------------------------------
+#define PLACED_LEFT 0x1
+#define PLACED_RIGHT 0x2
+
+#define NUM_SPAN_DATA (sizeof(mSpanDataBuf) / sizeof(mSpanDataBuf[0]))
+#define NUM_FRAME_DATA (sizeof(mFrameDataBuf) / sizeof(mFrameDataBuf[0]))
+
nsLineLayout::nsLineLayout(nsIPresContext& aPresContext,
- nsISpaceManager* aSpaceManager)
- : mPresContext(aPresContext)
+ nsISpaceManager* aSpaceManager,
+ const nsHTMLReflowState* aOuterReflowState,
+ PRBool aComputeMaxElementSize)
+ : mPresContext(aPresContext),
+ mSpaceManager(aSpaceManager),
+ mBlockReflowState(aOuterReflowState),
+ mComputeMaxElementSize(aComputeMaxElementSize)
{
- mSpaceManager = aSpaceManager;
- mListPositionOutside = PR_FALSE;
+ // Stash away some style data that we need
+ aOuterReflowState->frame->GetStyleData(eStyleStruct_Text,
+ (const nsStyleStruct*&) mStyleText);
+ mTextAlign = mStyleText->mTextAlign;
+ switch (mStyleText->mWhiteSpace) {
+ case NS_STYLE_WHITESPACE_PRE:
+ case NS_STYLE_WHITESPACE_NOWRAP:
+ mNoWrap = PR_TRUE;
+ break;
+ default:
+ mNoWrap = PR_FALSE;
+ break;
+ }
+ mDirection = aOuterReflowState->mStyleDisplay->mDirection;
+ mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
+ aOuterReflowState->frame);
+ mBRFrame = nsnull;
mLineNumber = 0;
mColumn = 0;
- mUnderstandsWhiteSpace = PR_FALSE;
mEndsInWhiteSpace = PR_TRUE;
+ mUnderstandsWhiteSpace = PR_FALSE;
+ mFirstLetterStyleOK = PR_FALSE;
+ mIsTopOfPage = PR_FALSE;
+ mWasInWord = PR_FALSE;
+ mCanBreakBeforeFrame = PR_FALSE;
+ mUpdatedBand = PR_FALSE;
+ mPlacedFloaters = 0;
+ mTotalPlacedFrames = 0;
+ mTopEdge = mBottomEdge = 0;
+ mReflowTextRuns = nsnull;
+ mTextRun = nsnull;
- mTextRuns = nsnull;
- ResetTextRuns();
-}
+ // XXX Do this on demand to avoid extra setup time
+ // Place the baked-in per-frame-data on the frame free list
+ PerFrameData** pfdp = &mFrameFreeList;
+ PerFrameData* pfd = mFrameDataBuf;
+ PerFrameData* endpfd = pfd + NUM_FRAME_DATA;
+ while (pfd < endpfd) {
+#ifdef DEBUG
+ nsCRT::memset(pfd, 0xEE, sizeof(*pfd));
+#endif
+ *pfdp = pfd;
+ pfdp = &pfd->mNext;
+ pfd++;
+ }
+ *pfdp = nsnull;
-nsLineLayout::~nsLineLayout()
-{
- nsTextRun::DeleteTextRuns(mTextRuns);
-}
+ // XXX Do this on demand to avoid extra setup time
+ // Place the baked-in per-span-data on the span free list
+ PerSpanData** psdp = &mSpanFreeList;
+ PerSpanData* psd = mSpanDataBuf;
+ PerSpanData* endpsd = psd + NUM_SPAN_DATA;
+ while (psd < endpsd) {
+#ifdef DEBUG
+ nsCRT::memset(psd, 0xEE, sizeof(*psd));
+#endif
+ *psdp = psd;
+ psdp = &psd->mNext;
+ psd++;
+ }
+ *psdp = nsnull;
+
+ mCurrentSpan = mRootSpan = mLastSpan = nsnull;
+ mSpanDepth = 0;
-void
-nsLineLayout::ResetTextRuns()
-{
- nsTextRun::DeleteTextRuns(mTextRuns);
mTextRuns = nsnull;
mTextRunP = &mTextRuns;
mNewTextRun = nsnull;
}
-nsTextRun*
-nsLineLayout::TakeTextRuns()
+nsLineLayout::nsLineLayout(nsIPresContext& aPresContext)
+ : mPresContext(aPresContext)
{
- nsTextRun* result = mTextRuns;
mTextRuns = nsnull;
- ResetTextRuns();
- return result;
+ mTextRunP = &mTextRuns;
+ mNewTextRun = nsnull;
+ mRootSpan = nsnull;
+ mSpanFreeList = nsnull;
+ mFrameFreeList = nsnull;
+}
+
+nsLineLayout::~nsLineLayout()
+{
+ NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user");
+ nsTextRun::DeleteTextRuns(mTextRuns);
+
+ // Free up all of the per-span-data items that were allocated on the heap
+ PerSpanData* psd = mSpanFreeList;
+ while (nsnull != psd) {
+ PerSpanData* nextSpan = psd->mNext;
+ if ((psd < &mSpanDataBuf[0]) || (psd >= &mSpanDataBuf[NUM_SPAN_DATA])) {
+ delete psd;
+ }
+ psd = nextSpan;
+ }
+
+ // Free up all of the per-frame-data items that were allocated on the heap
+ PerFrameData* pfd = mFrameFreeList;
+ while (nsnull != pfd) {
+ PerFrameData* nextFrame = pfd->mNext;
+ if ((pfd < &mFrameDataBuf[0]) || (pfd >= &mFrameDataBuf[NUM_FRAME_DATA])) {
+ delete pfd;
+ }
+ pfd = nextFrame;
+ }
}
void
-nsLineLayout::EndTextRun()
+nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
+ nscoord aWidth, nscoord aHeight,
+ PRBool aIsTopOfPage)
{
- mNewTextRun = nsnull;
+ NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
+#ifdef DEBUG
+ if ((aWidth > 200000) && (aWidth != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": Init: bad caller: width WAS %d(0x%x)\n",
+ aWidth, aWidth);
+ aWidth = NS_UNCONSTRAINEDSIZE;
+ }
+ if ((aHeight > 200000) && (aHeight != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": Init: bad caller: height WAS %d(0x%x)\n",
+ aHeight, aHeight);
+ aHeight = NS_UNCONSTRAINEDSIZE;
+ }
+#endif
+#ifdef NOISY_REFLOW
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": BeginLineReflow: %d,%d,%d,%d %s\n",
+ aX, aY, aWidth, aHeight,
+ aIsTopOfPage ? "top-of-page" : "");
+#endif
+
+ mBRFrame = nsnull;
+ mColumn = 0;
+ mEndsInWhiteSpace = PR_TRUE;
+ mUnderstandsWhiteSpace = PR_FALSE;
+ mFirstLetterStyleOK = PR_FALSE;
+ mIsTopOfPage = aIsTopOfPage;
+ mCanBreakBeforeFrame = PR_FALSE;
+ mUpdatedBand = PR_FALSE;
+ mPlacedFloaters = 0;
+ mTotalPlacedFrames = 0;
+ mSpanDepth = 0;
+ mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
+
+ ForgetWordFrames();
+
+ PerSpanData* psd;
+ NewPerSpanData(&psd);
+ mCurrentSpan = mRootSpan = psd;
+ psd->mReflowState = mBlockReflowState;
+ psd->mLeftEdge = aX;
+ psd->mX = aX;
+ if (NS_UNCONSTRAINEDSIZE == aWidth) {
+ psd->mRightEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ psd->mRightEdge = aX + aWidth;
+ }
+
+ mTopEdge = aY;
+ if (NS_UNCONSTRAINEDSIZE == aHeight) {
+ mBottomEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ mBottomEdge = aY + aHeight;
+ }
+}
+
+void
+nsLineLayout::EndLineReflow()
+{
+#ifdef NOISY_REFLOW
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": EndLineReflow: width=%d\n", mRootSpan->mX - mRootSpan->mLeftEdge);
+#endif
+
+ PerSpanData* psd = mRootSpan;
+ while (nsnull != psd) {
+ // Put frames on free list
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ PerFrameData* nextFrame = pfd->mNext;
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ pfd = nextFrame;
+ }
+
+ // Put span on free list
+ PerSpanData* nextSpan = psd->mNext;
+ psd->mNext = mSpanFreeList;
+ mSpanFreeList = psd;
+ psd = nextSpan;
+ }
+ mCurrentSpan = mRootSpan = mLastSpan = nsnull;
+}
+
+void
+nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
+ nscoord aWidth, nscoord aHeight,
+ PRBool aPlacedLeftFloater)
+{
+ PerSpanData* psd = mRootSpan;
+ NS_PRECONDITION(psd->mX == psd->mLeftEdge, "update-band called late");
+#ifdef DEBUG
+ if ((aWidth > 200000) && (aWidth != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": UpdateBand: bad caller: width WAS %d(0x%x)\n",
+ aWidth, aWidth);
+ aWidth = NS_UNCONSTRAINEDSIZE;
+ }
+ if ((aHeight > 200000) && (aHeight != NS_UNCONSTRAINEDSIZE)) {
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": UpdateBand: bad caller: height WAS %d(0x%x)\n",
+ aHeight, aHeight);
+ aHeight = NS_UNCONSTRAINEDSIZE;
+ }
+#endif
+#ifdef NOISY_REFLOW
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": UpdateBand: %d,%d,%d,%d %s\n",
+ aX, aY, aWidth, aHeight,
+ aPlacedLeftFloater ? "placed-left-floater" : "");
+#endif
+
+ psd->mLeftEdge = aX;
+ psd->mX = aX;
+ if (NS_UNCONSTRAINEDSIZE == aWidth) {
+ psd->mRightEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ psd->mRightEdge = aX + aWidth;
+ }
+ mTopEdge = aY;
+ if (NS_UNCONSTRAINEDSIZE == aHeight) {
+ mBottomEdge = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ mBottomEdge = aY + aHeight;
+ }
+ mUpdatedBand = PR_TRUE;
+ mPlacedFloaters |= (aPlacedLeftFloater ? PLACED_LEFT : PLACED_RIGHT);
+}
+
+void
+nsLineLayout::UpdateFrames()
+{
+ if (NS_STYLE_DIRECTION_LTR == mDirection) {
+ if (PLACED_LEFT & mPlacedFloaters) {
+ // Note: Only adjust the outermost frames (the ones that are
+ // direct children of the block), not the ones in the child
+ // spans. The reason is simple: the frames in the spans have
+ // coordinates local to their parent therefore they are moved
+ // when their parent span is moved.
+ PerSpanData* psd = mRootSpan;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ pfd->mBounds.x = psd->mX;
+ pfd = pfd->mNext;
+ }
+ }
+ }
+ else if (PLACED_RIGHT & mPlacedFloaters) {
+ // XXX handle DIR=right-to-left
+ }
}
nsresult
-nsLineLayout::AddText(nsIFrame* aTextFrame)
+nsLineLayout::NewPerSpanData(PerSpanData** aResult)
{
- if (nsnull == mNewTextRun) {
- mNewTextRun = new nsTextRun();
- if (nsnull == mNewTextRun) {
+ PerSpanData* psd = mSpanFreeList;
+ if (nsnull == psd) {
+ psd = new PerSpanData;
+ if (nsnull == psd) {
return NS_ERROR_OUT_OF_MEMORY;
}
- *mTextRunP = mNewTextRun;
- mTextRunP = &mNewTextRun->mNext;
}
- mNewTextRun->mArray.AppendElement(aTextFrame);
- return NS_OK;/* XXX */
+ else {
+ mSpanFreeList = psd->mNext;
+ }
+ psd->mParent = nsnull;
+ psd->mFrame = nsnull;
+ psd->mFirstFrame = nsnull;
+ psd->mLastFrame = nsnull;
+ psd->mNext = nsnull;
+
+ // Link new span to the end of the span list
+ if (nsnull == mLastSpan) {
+ psd->mPrev = nsnull;
+ }
+ else {
+ mLastSpan->mNext = psd;
+ psd->mPrev = mLastSpan;
+ }
+ mLastSpan = psd;
+
+ *aResult = psd;
+ return NS_OK;
}
-nsTextRun*
-nsLineLayout::FindTextRunFor(nsIFrame* aFrame)
+nsresult
+nsLineLayout::BeginSpan(nsIFrame* aFrame,
+ const nsHTMLReflowState* aSpanReflowState,
+ nscoord aLeftEdge,
+ nscoord aRightEdge)
{
- // Only the first-in-flows are present in the text run list so
- // backup from the argument frame to its first-in-flow.
- for (;;) {
- nsIFrame* prevInFlow;
- aFrame->GetPrevInFlow(&prevInFlow);
- if (nsnull == prevInFlow) {
- break;
+#ifdef NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth+1);
+ nsFrame::ListTag(stdout, aFrame);
+ printf(": BeginSpan leftEdge=%d rightEdge=%d\n", aLeftEdge, aRightEdge);
+#endif
+
+ PerSpanData* psd;
+ nsresult rv = NewPerSpanData(&psd);
+ if (NS_SUCCEEDED(rv)) {
+ // Link up span frame's pfd to point to its child span data
+ PerFrameData* pfd = mCurrentSpan->mLastFrame;
+ NS_ASSERTION(pfd->mFrame == aFrame, "huh?");
+ pfd->mSpan = psd;
+
+ // Init new span
+ psd->mFrame = pfd;
+ psd->mParent = mCurrentSpan;
+ psd->mReflowState = aSpanReflowState;
+ psd->mLeftEdge = aLeftEdge;
+ psd->mX = aLeftEdge;
+ psd->mRightEdge = aRightEdge;
+
+ // Switch to new span
+ mCurrentSpan = psd;
+ mSpanDepth++;
+ }
+ return rv;
+}
+
+void
+nsLineLayout::EndSpan(nsIFrame* aFrame,
+ nsSize& aSizeResult,
+ nsSize* aMaxElementSize)
+{
+ NS_ASSERTION(mSpanDepth > 0, "end-span without begin-span");
+#ifdef NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ nsFrame::ListTag(stdout, aFrame);
+ printf(": EndSpan width=%d\n", mCurrentSpan->mX - mCurrentSpan->mLeftEdge);
+#endif
+ PerSpanData* psd = mCurrentSpan;
+ nscoord width = 0;
+ nscoord maxHeight = 0;
+ nscoord maxElementWidth = 0;
+ nscoord maxElementHeight = 0;
+ if (nsnull != psd->mLastFrame) {
+ width = psd->mX - psd->mLeftEdge;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
+
+ // Compute max-element-size if necessary
+ if (aMaxElementSize) {
+ nscoord mw = pfd->mMaxElementSize.width +
+ pfd->mMargin.left + pfd->mMargin.right;
+ if (maxElementWidth < mw) {
+ maxElementWidth = mw;
+ }
+ nscoord mh = pfd->mMaxElementSize.height +
+ pfd->mMargin.top + pfd->mMargin.bottom;
+ if (maxElementHeight < mh) {
+ maxElementHeight = mh;
+ }
+ }
+ pfd = pfd->mNext;
}
- aFrame = prevInFlow;
+ }
+ aSizeResult.width = width;
+ aSizeResult.height = maxHeight;
+ if (aMaxElementSize) {
+ aMaxElementSize->width = maxElementWidth;
+ aMaxElementSize->height = maxElementHeight;
}
- // Now look for the frame in each run
- nsTextRun* run = mReflowTextRuns;
- while (nsnull != run) {
- PRInt32 ix = run->mArray.IndexOf(aFrame);
- if (ix >= 0) {
- return run;
- }
- run = run->mNext;
+ mSpanDepth--;
+ mCurrentSpan->mReflowState = nsnull; // no longer valid so null it out!
+ mCurrentSpan = mCurrentSpan->mParent;
+}
+
+PRInt32
+nsLineLayout::GetCurrentSpanCount() const
+{
+ NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
+ PRInt32 count = 0;
+ PerFrameData* pfd = mRootSpan->mFirstFrame;
+ while (nsnull != pfd) {
+ count++;
+ pfd = pfd->mNext;
+ }
+ return count;
+}
+
+void
+nsLineLayout::SplitLineTo(PRInt32 aNewCount)
+{
+ NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
+
+#ifdef REALLY_NOISY_PUSHING
+ printf("SplitLineTo %d (current count=%d); before:\n", aNewCount,
+ GetCurrentSpanCount());
+ DumpPerSpanData(mRootSpan, 1);
+#endif
+ PerSpanData* psd = mRootSpan;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (--aNewCount == 0) {
+ // Truncate list at pfd (we keep pfd, but anything following is freed)
+ PerFrameData* next = pfd->mNext;
+ pfd->mNext = nsnull;
+ psd->mLastFrame = pfd;
+
+ // Now release all of the frames following pfd
+ pfd = next;
+ while (nsnull != pfd) {
+ next = pfd->mNext;
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ if (nsnull != pfd->mSpan) {
+ FreeSpan(pfd->mSpan);
+ }
+ pfd = next;
+ }
+ break;
+ }
+ pfd = pfd->mNext;
+ }
+#ifdef NOISY_PUSHING
+ printf("SplitLineTo %d (current count=%d); after:\n", aNewCount,
+ GetCurrentSpanCount());
+ DumpPerSpanData(mRootSpan, 1);
+#endif
+}
+
+void
+nsLineLayout::PushFrame(nsIFrame* aFrame)
+{
+ PerSpanData* psd = mCurrentSpan;
+ NS_ASSERTION(psd->mLastFrame->mFrame == aFrame, "pushing non-last frame");
+
+#ifdef REALLY_NOISY_PUSHING
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("PushFrame %p, before:\n", psd);
+ DumpPerSpanData(psd, 1);
+#endif
+
+ // Take the last frame off of the span's frame list
+ PerFrameData* pfd = psd->mLastFrame;
+ if (pfd == psd->mFirstFrame) {
+ // We are pushing away the only frame...empty the list
+ psd->mFirstFrame = nsnull;
+ psd->mLastFrame = nsnull;
+ }
+ else {
+ PerFrameData* prevFrame = pfd->mPrev;
+ prevFrame->mNext = nsnull;
+ psd->mLastFrame = prevFrame;
+ }
+
+ // Now free it, and if it has a span, free that too
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ if (nsnull != pfd->mSpan) {
+ FreeSpan(pfd->mSpan);
+ }
+#ifdef NOISY_PUSHING
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("PushFrame: %p after:\n", psd);
+ DumpPerSpanData(psd, 1);
+#endif
+}
+
+void
+nsLineLayout::FreeSpan(PerSpanData* psd)
+{
+ // Take span out of the list
+ if (nsnull != psd->mNext) psd->mNext->mPrev = psd->mPrev;
+ if (nsnull != psd->mPrev) psd->mPrev->mNext = psd->mNext;
+
+ // Free its frames
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (nsnull != pfd->mSpan) {
+ FreeSpan(pfd->mSpan);
+ }
+ PerFrameData* next = pfd->mNext;
+ pfd->mNext = mFrameFreeList;
+ mFrameFreeList = pfd;
+ pfd = next;
+ }
+}
+
+PRBool
+nsLineLayout::IsZeroHeight()
+{
+ PerSpanData* psd = mCurrentSpan;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ if (0 != pfd->mBounds.height) {
+ return PR_FALSE;
+ }
+ pfd = pfd->mNext;
+ }
+ return PR_TRUE;
+}
+
+nsresult
+nsLineLayout::NewPerFrameData(PerFrameData** aResult)
+{
+ PerFrameData* pfd = mFrameFreeList;
+ if (nsnull == pfd) {
+ pfd = new PerFrameData;
+ if (nsnull == pfd) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ mFrameFreeList = pfd->mNext;
+ }
+ pfd->mSpan = nsnull;
+ pfd->mNext = nsnull;
+ *aResult = pfd;
+ return NS_OK;
+}
+
+nsresult
+nsLineLayout::ReflowFrame(nsIFrame* aFrame,
+ nsIFrame** aNextRCFrame,
+ nsReflowStatus& aReflowStatus)
+{
+ PerFrameData* pfd;
+ nsresult rv = NewPerFrameData(&pfd);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ PerSpanData* psd = mCurrentSpan;
+ psd->AppendFrame(pfd);
+
+#ifdef REALLY_NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("%p: Begin ReflowFrame pfd=%p ", psd, pfd);
+ nsFrame::ListTag(stdout, aFrame);
+ printf("\n");
+#endif
+
+ // Compute the available size for the frame. This available width
+ // includes room for the side margins and for the text-indent.
+ nsSize availSize;
+ if (NS_UNCONSTRAINEDSIZE == psd->mRightEdge) {
+ availSize.width = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.width = psd->mRightEdge - psd->mX;
+ if (mNoWrap) {
+ // XXX Shouldn't this use NS_UNCONSTRAINEDSIZE?
+ availSize.width = psd->mReflowState->availableWidth;
+ }
+ }
+ if (NS_UNCONSTRAINEDSIZE == mBottomEdge) {
+ availSize.height = NS_UNCONSTRAINEDSIZE;
+ }
+ else {
+ availSize.height = mBottomEdge - mTopEdge;
+ }
+
+ // Get reflow reason set correctly. It's possible that a child was
+ // created and then it was decided that it could not be reflowed
+ // (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 reason = eReflowReason_Resize;
+ nsFrameState state;
+ aFrame->GetFrameState(&state);
+ if (NS_FRAME_FIRST_REFLOW & state) {
+ reason = eReflowReason_Initial;
+ }
+ else if (*aNextRCFrame == aFrame) {
+ reason = eReflowReason_Incremental;
+ // Make sure we only incrementally reflow once
+ *aNextRCFrame = nsnull;
+ }
+
+ // Setup reflow state for reflowing the frame
+ nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState, aFrame,
+ availSize, reason);
+ reflowState.lineLayout = this;
+ reflowState.isTopOfPage = mIsTopOfPage;
+ mUnderstandsWhiteSpace = PR_FALSE;
+ mCanBreakBeforeFrame = mTotalPlacedFrames > 0;
+
+ // Stash copies of some of the computed state away for later
+ // (vertical alignment, for example)
+ pfd->mFrame = aFrame;
+ pfd->mMargin = reflowState.computedMargin;
+ pfd->mBorderPadding = reflowState.mComputedBorderPadding;
+ pfd->mFrameType = reflowState.frameType;
+ pfd->mRelativePos =
+ reflowState.mStylePosition->mPosition == NS_STYLE_POSITION_RELATIVE;
+ if (pfd->mRelativePos) {
+ pfd->mOffsets = reflowState.computedOffsets;
+ }
+
+ // Capture this state *before* we reflow the frame in case it clears
+ // the state out. We need to know how to treat the current frame
+ // when breaking.
+ mWasInWord = InWord();
+
+ // Apply left margins (as appropriate) to the frame computing the
+ // new starting x,y coordinates for the frame.
+ ApplyLeftMargin(pfd, reflowState);
+
+ // Let frame know that are reflowing it
+ nscoord x = pfd->mBounds.x;
+ nscoord y = pfd->mBounds.y;
+ nsIHTMLReflow* htmlReflow;
+
+ aFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
+ htmlReflow->WillReflow(mPresContext);
+
+ // Adjust spacemanager coordinate system for the frame. The
+ // spacemanager coordinates are inside the current spans
+ // border+padding, but the x/y coordinates are not (recall that
+ // frame coordinates are relative to the parents origin and that the
+ // parents border/padding is inside the parent
+ // frame. Therefore we have to subtract out the parents
+ // border+padding before translating.
+ nsSize innerMaxElementSize;
+ nsHTMLReflowMetrics metrics(mComputeMaxElementSize
+ ? &innerMaxElementSize
+ : nsnull);
+#ifdef DEBUG
+ if (mComputeMaxElementSize) {
+ metrics.maxElementSize->width = nscoord(0xdeadbeef);
+ metrics.maxElementSize->height = nscoord(0xdeadbeef);
+ }
+#endif
+ nscoord tx = x - psd->mReflowState->mComputedBorderPadding.left;
+ nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
+ mSpaceManager->Translate(tx, ty);
+ htmlReflow->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
+ mSpaceManager->Translate(-tx, -ty);
+
+#ifdef DEBUG_kipp
+ NS_ASSERTION((metrics.width > -200000) && (metrics.width < 200000), "oy");
+ NS_ASSERTION((metrics.height > -200000) && (metrics.height < 200000), "oy");
+#endif
+#ifdef DEBUG
+ if (mComputeMaxElementSize &&
+ ((nscoord(0xdeadbeef) == metrics.maxElementSize->width) ||
+ (nscoord(0xdeadbeef) == metrics.maxElementSize->height))) {
+ printf("nsLineLayout: ");
+ nsFrame::ListTag(stdout, aFrame);
+ printf(" didn't set max-element-size!\n");
+ metrics.maxElementSize->width = 0;
+ metrics.maxElementSize->height = 0;
+ }
+#endif
+
+ aFrame->GetFrameState(&state);
+ if (NS_FRAME_OUTSIDE_CHILDREN & state) {
+ pfd->mCombinedArea = metrics.mCombinedArea;
+ }
+ else {
+ pfd->mCombinedArea.x = 0;
+ pfd->mCombinedArea.y = 0;
+ pfd->mCombinedArea.width = metrics.width;
+ pfd->mCombinedArea.height = metrics.height;
+ }
+ pfd->mBounds.width = metrics.width;
+ pfd->mBounds.height = metrics.height;
+ if (mComputeMaxElementSize) {
+ pfd->mMaxElementSize = *metrics.maxElementSize;
+ }
+
+ // Now that frame has been reflowed at least one time make sure that
+ // the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an
+ // initial reflow reason again.
+ if (eReflowReason_Initial == reason) {
+ aFrame->GetFrameState(&state);
+ aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
+ }
+
+ if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
+ // If frame is complete and has a next-in-flow, we need to delete
+ // them now. Do not do this when a break-before is signaled because
+ // the frame is going to get reflowed again (and may end up wanting
+ // a next-in-flow where it ends up).
+ if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
+ nsIFrame* kidNextInFlow;
+ aFrame->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)
+ nsHTMLContainerFrame* parent;
+ aFrame->GetParent((nsIFrame**) &parent);
+ parent->DeleteChildsNextInFlow(mPresContext, aFrame);
+ }
+ }
+
+ // See if we can place the frame. If we can't fit it, then we
+ // return now.
+ if (CanPlaceFrame(pfd, reflowState, metrics, aReflowStatus)) {
+ // Place the frame, updating aBounds with the final size and
+ // location. Then apply the bottom+right margins (as
+ // appropriate) to the frame.
+ PlaceFrame(pfd, metrics);
+ PerSpanData* span = pfd->mSpan;
+ if (span) {
+ // The frame we just finished reflowing is an inline
+ // container. It needs its child frames vertically aligned,
+ // so do most of it now.
+ VerticalAlignFrames(span);
+ }
+ }
+ else {
+ PushFrame(aFrame);
+ }
+ }
+ else {
+ PushFrame(aFrame);
+ }
+
+#ifdef REALLY_NOISY_REFLOW
+ nsFrame::IndentBy(stdout, mSpanDepth);
+ printf("End ReflowFrame ");
+ nsFrame::ListTag(stdout, aFrame);
+ printf(" status=%x\n", aReflowStatus);
+#endif
+ return rv;
+}
+
+void
+nsLineLayout::ApplyLeftMargin(PerFrameData* pfd,
+ nsHTMLReflowState& aReflowState)
+{
+ // If this is the first frame in the block, and its the first line
+ // of a block then see if the text-indent property amounts to
+ // anything.
+ nscoord indent = 0;
+ if (InBlockContext() && (0 == mLineNumber) &&
+ (0 == mTotalPlacedFrames)) {
+ nsStyleUnit unit = mStyleText->mTextIndent.GetUnit();
+ if (eStyleUnit_Coord == unit) {
+ indent = mStyleText->mTextIndent.GetCoordValue();
+ }
+ else if (eStyleUnit_Percent == unit) {
+ nscoord width =
+ nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState->parentReflowState);
+ if (0 != width) {
+ indent = nscoord(mStyleText->mTextIndent.GetPercentValue() * width);
+ }
+ }
+ }
+
+ // Adjust available width to account for the indent and the margins
+ aReflowState.availableWidth -= indent + pfd->mMargin.left +
+ pfd->mMargin.right;
+
+ // NOTE: While the x coordinate remains relative to the parent span,
+ // the y coordinate is fixed at the top edge for the line. During
+ // VerticalAlignFrames we will repair this so that the y coordinate
+ // is properly set and relative to the appropriate span.
+ PerSpanData* psd = mCurrentSpan;
+ pfd->mBounds.x = psd->mX + indent;
+ pfd->mBounds.y = mTopEdge;
+
+ // Compute left margin
+ nsIFrame* prevInFlow;
+ switch (aReflowState.mStyleDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ case NS_STYLE_FLOAT_RIGHT:
+ // When something is floated, its margins are applied there
+ // not here.
+ break;
+
+ case NS_STYLE_FLOAT_NONE:
+ // Only apply left-margin on the first-in flow for inline frames
+ pfd->mFrame->GetPrevInFlow(&prevInFlow);
+ if (nsnull != prevInFlow) {
+ // Zero this out so that when we compute the max-element-size
+ // of the frame we will properly avoid adding in the left
+ // margin.
+ pfd->mMargin.left = 0;
+ }
+ pfd->mBounds.x += pfd->mMargin.left;
+ break;
+ }
+}
+
+/**
+ * See if the frame can be placed now that we know it's desired size.
+ * We can always place the frame if the line is empty. Note that we
+ * know that the reflow-status is not a break-before because if it was
+ * ReflowFrame above would have returned false, preventing this method
+ * from being called. The logic in this method assumes that.
+ *
+ * Note that there is no check against the Y coordinate because we
+ * assume that the caller will take care of that.
+ */
+PRBool
+nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
+ const nsHTMLReflowState& aReflowState,
+ nsHTMLReflowMetrics& aMetrics,
+ nsReflowStatus& aStatus)
+{
+ // Compute right margin to use
+ nscoord rightMargin = 0;
+ if (0 != pfd->mBounds.width) {
+ switch (aReflowState.mStyleDisplay->mFloats) {
+ default:
+ NS_NOTYETIMPLEMENTED("Unsupported floater type");
+ // FALL THROUGH
+
+ case NS_STYLE_FLOAT_LEFT:
+ case NS_STYLE_FLOAT_RIGHT:
+ // When something is floated, its margins are applied there
+ // not here.
+ break;
+
+ case NS_STYLE_FLOAT_NONE:
+ // Only apply right margin for the last-in-flow
+ if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
+ // Zero this out so that when we compute the
+ // max-element-size of the frame we will properly avoid
+ // adding in the right margin.
+ pfd->mMargin.right = 0;
+ }
+ rightMargin = pfd->mMargin.right;
+ break;
+ }
+ }
+ pfd->mMargin.right = rightMargin;
+
+ // Set outside to PR_TRUE if the result of the reflow leads to the
+ // frame sticking outside of our available area.
+ PerSpanData* psd = mCurrentSpan;
+ PRBool outside = pfd->mBounds.XMost() + rightMargin > psd->mRightEdge;
+
+ // There are several special conditions that exist which allow us to
+ // ignore outside. If they are true then we can place frame and
+ // return PR_TRUE.
+ if (!mCanBreakBeforeFrame || mWasInWord || mNoWrap) {
+ return PR_TRUE;
+ }
+
+ if (0 == pfd->mMargin.left + pfd->mBounds.width + rightMargin) {
+ // Empty frames always fit right where they are
+ return PR_TRUE;
+ }
+
+ if (pfd == mCurrentSpan->mFirstFrame) {
+ return PR_TRUE;
+ }
+
+ if (outside) {
+ aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/**
+ * Place the frame. Update running counters.
+ */
+void
+nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
+{
+ // If frame is zero width then do not apply its left and right margins.
+ PerSpanData* psd = mCurrentSpan;
+ PRBool emptyFrame = PR_FALSE;
+ if ((0 == pfd->mBounds.width) && (0 == pfd->mBounds.height)) {
+ pfd->mBounds.x = psd->mX;
+ pfd->mBounds.y = mTopEdge;
+ emptyFrame = PR_TRUE;
+ }
+
+ // Record ascent and update max-ascent and max-descent values
+ pfd->mAscent = aMetrics.ascent;
+ pfd->mDescent = aMetrics.descent;
+ pfd->mCarriedOutTopMargin = aMetrics.mCarriedOutTopMargin;
+ pfd->mCarriedOutBottomMargin = aMetrics.mCarriedOutBottomMargin;
+
+ // If the band was updated during the reflow of that frame then we
+ // need to adjust any prior frames that were reflowed.
+ if (mUpdatedBand && InBlockContext()) {
+ UpdateFrames();
+ mUpdatedBand = PR_FALSE;
+ }
+
+ // Advance to next X coordinate
+ psd->mX = pfd->mBounds.XMost() + pfd->mMargin.right;
+
+ // If the frame is a not aware of white-space and it takes up some
+ // area, disable leading white-space compression for the next frame
+ // to be reflowed.
+ if (!mUnderstandsWhiteSpace && !emptyFrame) {
+ mEndsInWhiteSpace = PR_FALSE;
+ }
+
+ // Compute the bottom margin to apply. Note that the margin only
+ // applies if the frame ends up with a non-zero height.
+ if (!emptyFrame) {
+ // Inform line layout that we have placed a non-empty frame
+ mTotalPlacedFrames++;
+ }
+}
+
+nsresult
+nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
+ const nsHTMLReflowMetrics& aMetrics)
+{
+ NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
+
+ PerFrameData* pfd;
+ nsresult rv = NewPerFrameData(&pfd);
+ if (NS_SUCCEEDED(rv)) {
+ mRootSpan->AppendFrame(pfd);
+ pfd->mFrame = aFrame;
+ pfd->mMargin.SizeTo(0, 0, 0, 0);
+ pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
+ pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
+ pfd->mRelativePos = PR_FALSE;
+ pfd->mAscent = aMetrics.ascent;
+ pfd->mDescent = aMetrics.descent;
+ aFrame->GetRect(pfd->mBounds); // y value is irrelevant
+ pfd->mCombinedArea = aMetrics.mCombinedArea;
+ if (mComputeMaxElementSize) {
+ pfd->mMaxElementSize.SizeTo(aMetrics.width, aMetrics.height);
+ }
+ }
+ return rv;
+}
+
+#ifdef DEBUG
+void
+nsLineLayout::DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent)
+{
+ nsFrame::IndentBy(stdout, aIndent);
+ printf("%p: left=%d x=%d right=%d prev/next=%p/%p\n", psd, psd->mLeftEdge,
+ psd->mX, psd->mRightEdge, psd->mPrev, psd->mNext);
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ nsFrame::IndentBy(stdout, aIndent+1);
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(" %d,%d,%d,%d\n", pfd->mBounds.x, pfd->mBounds.y,
+ pfd->mBounds.width, pfd->mBounds.height);
+ if (pfd->mSpan) {
+ DumpPerSpanData(pfd->mSpan, aIndent + 1);
+ }
+ pfd = pfd->mNext;
+ }
+}
+#endif
+
+#define VALIGN_OTHER 0
+#define VALIGN_TOP 1
+#define VALIGN_BOTTOM 2
+
+void
+nsLineLayout::VerticalAlignFrames(nsRect& aLineBoxResult,
+ nsSize& aMaxElementSizeResult)
+{
+ // Synthesize a PerFrameData for the block frame
+ PerFrameData rootPFD;
+ rootPFD.mFrame = mBlockReflowState->frame;
+ rootPFD.mFrameType = mBlockReflowState->frameType;
+ rootPFD.mAscent = 0;
+ rootPFD.mDescent = 0;
+ mRootSpan->mFrame = &rootPFD;
+
+ // Partially place the children of the block frame. The baseline for
+ // this operation is set to zero so that the y coordinates for all
+ // of the placed children will be relative to there.
+ PerSpanData* psd = mRootSpan;
+ VerticalAlignFrames(psd);
+
+ // Compute the line-height. The line-height will be the larger of:
+ //
+ // [1] maxY - minY (the distance between the highest childs top edge
+ // and the lowest childs bottom edge)
+ //
+ // [2] the maximum logical box height (since not every frame may have
+ // participated in #1; for example: top/bottom aligned frames)
+ //
+ // [3] the minimum line height (line-height property set on the
+ // block frame)
+ nscoord lineHeight = psd->mMaxY - psd->mMinY;
+
+ // Now that the line-height is computed, we need to know where the
+ // baseline is in the line. Position baseline so that mMinY is just
+ // inside the top of the line box.
+ nscoord baselineY;
+ if (psd->mMinY < 0) {
+ baselineY = mTopEdge - psd->mMinY;
+ }
+ else {
+ baselineY = mTopEdge;
+ }
+
+ // It's possible that the line-height isn't tall enough because of
+ // the blocks minimum line-height.
+ if (0 != lineHeight) {
+ // If line contains nothing but empty boxes that have no height
+ // then don't apply the min-line-height.
+ //
+ // Note: This is how we hide lines that contain nothing but
+ // compressed whitespace.
+ if (lineHeight < mMinLineHeight) {
+ // Apply half of the extra space to the top of the line as top
+ // leading
+ nscoord extra = mMinLineHeight - lineHeight;
+ baselineY += extra / 2;
+ lineHeight = mMinLineHeight;
+ }
+ }
+
+ // It's also possible that the line-height isn't tall enough because
+ // of top/bottom aligned elements that were not accounted for in
+ // min/max Y.
+ //
+ // The CSS2 spec doesn't really say what happens when to the
+ // baseline in this situations. What we do is if the largest top
+ // aligned box height is greater than the line-height then we leave
+ // the baseline alone. If the largest bottom aligned box is greater
+ // than the line-height then we slide the baseline down by the extra
+ // amount.
+ //
+ // Navigator 4 gives precedence to the first top/bottom aligned
+ // object. We just let bottom aligned objects win.
+ if (lineHeight < mMaxBottomBoxHeight) {
+ // When the line is shorter than the maximum top aligned box
+ nscoord extra = mMaxBottomBoxHeight - lineHeight;
+ baselineY += extra;
+ lineHeight = mMaxBottomBoxHeight;
+ }
+ if (lineHeight < mMaxTopBoxHeight) {
+ lineHeight = mMaxTopBoxHeight;
+ }
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ==> lineHeight=%d baselineY=%d\n", lineHeight, baselineY);
+#endif
+
+ // Now position all of the frames in the root span. We will also
+ // recurse over the child spans and place any top/bottom aligned
+ // frames we find.
+ // XXX PERFORMANCE: set a bit per-span to avoid the extra work
+ // (propogate it upward too)
+ PerFrameData* pfd = psd->mFirstFrame;
+ nscoord maxElementWidth = 0;
+ nscoord maxElementHeight = 0;
+ while (nsnull != pfd) {
+ // Compute max-element-size if necessary
+ if (mComputeMaxElementSize) {
+ nscoord mw = pfd->mMaxElementSize.width +
+ pfd->mMargin.left + pfd->mMargin.right;
+ if (maxElementWidth < mw) {
+ maxElementWidth = mw;
+ }
+ nscoord mh = pfd->mMaxElementSize.height +
+ pfd->mMargin.top + pfd->mMargin.bottom;
+ if (maxElementHeight < mh) {
+ maxElementHeight = mh;
+ }
+ }
+ PerSpanData* span = pfd->mSpan;
+ switch (pfd->mVerticalAlign) {
+ case VALIGN_TOP:
+ if (span) {
+ pfd->mBounds.y = mTopEdge - pfd->mBorderPadding.top +
+ span->mTopLeading;
+ }
+ else {
+ pfd->mBounds.y = mTopEdge + pfd->mMargin.top;
+ }
+ break;
+ case VALIGN_BOTTOM:
+ if (span) {
+ // Compute bottom leading
+ pfd->mBounds.y = mTopEdge + lineHeight -
+ pfd->mBounds.height + pfd->mBorderPadding.bottom -
+ span->mBottomLeading;
+ }
+ else {
+ pfd->mBounds.y = mTopEdge + lineHeight - pfd->mMargin.bottom -
+ pfd->mBounds.height;
+ }
+ break;
+ case VALIGN_OTHER:
+ pfd->mBounds.y += baselineY;
+ break;
+ }
+ pfd->mFrame->SetRect(pfd->mBounds);
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(": y=%d\n", pfd->mBounds.y);
+#endif
+ if (span) {
+ nscoord distanceFromTop = pfd->mBounds.y - mTopEdge;
+ PlaceTopBottomFrames(span, distanceFromTop, lineHeight);
+ }
+ pfd = pfd->mNext;
+ }
+
+ // Fill in returned line-box and max-element-size data
+ aLineBoxResult.x = psd->mLeftEdge;
+ aLineBoxResult.y = mTopEdge;
+ aLineBoxResult.width = psd->mX - psd->mLeftEdge;
+ aLineBoxResult.height = lineHeight;
+ aMaxElementSizeResult.width = maxElementWidth;
+ aMaxElementSizeResult.height = maxElementHeight;
+
+ // Undo root-span mFrame pointer to prevent brane damage later on...
+ mRootSpan->mFrame = nsnull;
+}
+
+void
+nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd,
+ nscoord aDistanceFromTop,
+ nscoord aLineHeight)
+{
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ PerSpanData* span = pfd->mSpan;
+ switch (pfd->mVerticalAlign) {
+ case VALIGN_TOP:
+ if (span) {
+ pfd->mBounds.y = -aDistanceFromTop - pfd->mBorderPadding.top +
+ span->mTopLeading;
+ }
+ else {
+ pfd->mBounds.y = -aDistanceFromTop + pfd->mMargin.top;
+ }
+ pfd->mFrame->SetRect(pfd->mBounds);
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(": y=%d dTop=%d [bp.top=%d topLeading=%d]\n",
+ pfd->mBounds.y, aDistanceFromTop,
+ span ? pfd->mBorderPadding.top : 0,
+ span ? span->mTopLeading : 0);
+#endif
+ break;
+ case VALIGN_BOTTOM:
+ if (span) {
+ // Compute bottom leading
+ pfd->mBounds.y = -aDistanceFromTop + aLineHeight -
+ pfd->mBounds.height + pfd->mBorderPadding.bottom -
+ span->mBottomLeading;
+ }
+ else {
+ pfd->mBounds.y = -aDistanceFromTop + aLineHeight -
+ pfd->mMargin.bottom - pfd->mBounds.height;
+ }
+ pfd->mFrame->SetRect(pfd->mBounds);
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, pfd->mFrame);
+ printf(": y=%d\n", pfd->mBounds.y);
+#endif
+ break;
+ }
+ if (span) {
+ nscoord distanceFromTop = distanceFromTop + pfd->mBounds.y;
+ PlaceTopBottomFrames(span, distanceFromTop, aLineHeight);
+ }
+ pfd = pfd->mNext;
+ }
+}
+
+// Vertically place frames within a given span. Note: this doesn't
+// place top/bottom aligned frames as those have to wait until the
+// entire line box height is known. This is called after the span
+// frame has finished being reflowed so that we know its height.
+void
+nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
+{
+ // Get parent frame info
+ PerFrameData* parentPFD = psd->mFrame;
+ nsIFrame* parentFrame = parentPFD->mFrame;
+
+ // Get the parent frame's font for all of the frames in this span
+ const nsStyleFont* parentFont;
+ parentFrame->GetStyleData(eStyleStruct_Font,
+ (const nsStyleStruct*&)parentFont);
+ nsIRenderingContext* rc = mBlockReflowState->rendContext;
+ rc->SetFont(parentFont->mFont);
+ nsIFontMetrics* fm;
+ rc->GetFontMetrics(fm);
+
+
+ // Setup baselineY, minY, and maxY
+ nscoord baselineY, minY, maxY;
+ if (psd == mRootSpan) {
+ // Use a zero baselineY since we don't yet know where the baseline
+ // will be (until we know how tall the line is; then we will
+ // know). In addition, use extreme values for the minY and maxY
+ // values so that only the child frames will impact their values
+ // (since these are children of the block, there is no span box to
+ // provide initial values).
+ baselineY = 0;
+ minY = 0;
+ maxY = 0;
+#ifdef NOISY_VERTICAL_ALIGN
+ nsFrame::ListTag(stdout, parentFrame);
+ printf(": pass1 valign frames: topEdge=%d minLineHeight=%d\n",
+ mTopEdge, mMinLineHeight);
+#endif
+ }
+ else if (0 != parentPFD->mBounds.height) {
+ // Compute the logical height for this span. Also compute the top
+ // leading.
+ nscoord logicalHeight =
+ nsHTMLReflowState::CalcLineHeight(mPresContext, parentFrame);
+ nscoord contentHeight = parentPFD->mBounds.height -
+ parentPFD->mBorderPadding.top - parentPFD->mBorderPadding.bottom;
+ nscoord leading = logicalHeight - contentHeight;
+ psd->mTopLeading = leading / 2;
+ psd->mBottomLeading = leading - psd->mTopLeading;
+ psd->mLogicalHeight = logicalHeight;
+
+ // The initial values for the min and max Y values are in the spans
+ // coordinate space, and cover the logical height of the span. If
+ // there are child frames in this span that stick out of this area
+ // then the minY and maxY are updated by the amount of logical
+ // height that is outside this range.
+ minY = parentPFD->mBorderPadding.top - psd->mTopLeading;
+ maxY = minY + psd->mLogicalHeight;
+
+ // This is the distance from the top edge of the parents visual
+ // box to the baseline.
+ nscoord parentAscent;
+ fm->GetMaxAscent(parentAscent);
+ baselineY = parentAscent + parentPFD->mBorderPadding.top;
+#ifdef NOISY_VERTICAL_ALIGN
+ nsFrame::ListTag(stdout, parentFrame);
+ printf(": baseLine=%d logicalHeight=%d topLeading=%d h=%d bp=%d,%d\n",
+ baselineY, logicalHeight, psd->mTopLeading,
+ parentPFD->mBounds.height,
+ parentPFD->mBorderPadding.top, parentPFD->mBorderPadding.bottom);
+#endif
+ }
+ else {
+ // When a span container is zero height it means that all of its
+ // kids are zero height as well.
+ psd->mMinY = 0;
+ psd->mMaxY = 0;
+ psd->mTopLeading = 0;
+ psd->mBottomLeading = 0;
+ psd->mLogicalHeight = 0;
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ==> [empty line]\n");
+#endif
+ return;
+ }
+
+ nscoord maxTopBoxHeight = 0;
+ nscoord maxBottomBoxHeight = 0;
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ nsIFrame* frame = pfd->mFrame;
+
+ // Compute the logical height of the frame
+ nscoord logicalHeight;
+ nscoord topLeading;
+ PerSpanData* frameSpan = pfd->mSpan;
+ if (frameSpan) {
+ // For span frames the logical-height and top-leading was
+ // pre-computed when the span was reflowed.
+ logicalHeight = frameSpan->mLogicalHeight;
+ topLeading = frameSpan->mTopLeading;
+ }
+ else {
+ // For other elements the logical height is the same as the
+ // frames height plus its margins.
+ logicalHeight = pfd->mBounds.height + pfd->mMargin.top +
+ pfd->mMargin.bottom;
+ topLeading = 0;
+ }
+
+ // Get vertical-align property
+ const nsStyleText* textStyle;
+ frame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
+ nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
+ if (eStyleUnit_Inherit == verticalAlignUnit) {
+ printf("XXX: vertical-align: inherit not implemented for ");
+ nsFrame::ListTag(stdout, frame);
+ printf("\n");
+ }
+ PRUint8 verticalAlignEnum;
+ nscoord parentAscent, parentDescent, parentXHeight;
+ nscoord parentSuperscript, parentSubscript;
+ nscoord coordOffset, percentOffset, elementLineHeight;
+ nscoord revisedBaselineY;
+ switch (verticalAlignUnit) {
+ case eStyleUnit_Enumerated:
+ default:
+ if (eStyleUnit_Enumerated == verticalAlignUnit) {
+ verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
+ }
+ else {
+ verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_BASELINE;
+ }
+ switch (verticalAlignEnum) {
+ default:
+ case NS_STYLE_VERTICAL_ALIGN_BASELINE:
+ // The elements baseline is aligned with the baseline of
+ // the parent.
+ if (frameSpan) {
+ // XXX explain
+ pfd->mBounds.y = baselineY - pfd->mAscent;
+ }
+ else {
+ // For non-span elements the borders, padding and
+ // margins are significant. Use the visual box height
+ // and the bottom margin as the distance off of the
+ // baseline.
+ pfd->mBounds.y = baselineY - pfd->mAscent - pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_SUB:
+ // Lower the baseline of the box to the subscript offset
+ // of the parent's box. This is identical to the baseline
+ // alignment except for the addition of the subscript
+ // offset to the baseline Y.
+ fm->GetSubscriptOffset(parentSubscript);
+ revisedBaselineY = baselineY + parentSubscript;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_SUPER:
+ // Raise the baseline of the box to the superscript offset
+ // of the parent's box. This is identical to the baseline
+ // alignment except for the subtraction of the superscript
+ // offset to the baseline Y.
+ fm->GetSuperscriptOffset(parentSuperscript);
+ revisedBaselineY = baselineY - parentSuperscript;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_TOP:
+ pfd->mVerticalAlign = VALIGN_TOP;
+ if (logicalHeight > maxTopBoxHeight) {
+ maxTopBoxHeight = logicalHeight;
+ }
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
+ pfd->mVerticalAlign = VALIGN_BOTTOM;
+ if (logicalHeight > maxBottomBoxHeight) {
+ maxBottomBoxHeight = logicalHeight;
+ }
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
+ // Align the midpoint of the frame with 1/2 the parents
+ // x-height above the baseline.
+ fm->GetXHeight(parentXHeight);
+ if (frameSpan) {
+ pfd->mBounds.y = baselineY -
+ (parentXHeight + pfd->mBounds.height)/2;
+ }
+ else {
+ pfd->mBounds.y = baselineY - (parentXHeight + logicalHeight)/2 +
+ pfd->mMargin.top;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
+ // The top of the logical box is aligned with the top of
+ // the parent elements text.
+ fm->GetMaxAscent(parentAscent);
+ if (frameSpan) {
+ pfd->mBounds.y = baselineY - parentAscent -
+ pfd->mBorderPadding.top + frameSpan->mTopLeading;
+ }
+ else {
+ pfd->mBounds.y = baselineY - parentAscent + pfd->mMargin.top;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
+ // The bottom of the logical box is aligned with the
+ // bottom of the parent elements text.
+ fm->GetMaxDescent(parentDescent);
+ if (frameSpan) {
+ pfd->mBounds.y = baselineY + parentDescent -
+ pfd->mBounds.height + pfd->mBorderPadding.bottom -
+ frameSpan->mBottomLeading;
+ }
+ else {
+ pfd->mBounds.y = baselineY + parentDescent -
+ pfd->mBounds.height - pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+ }
+ break;
+
+ case eStyleUnit_Coord:
+ // According to the CSS2 spec (10.8.1), a positive value
+ // "raises" the box by the given distance while a negative value
+ // "lowers" the box by the given distance (with zero being the
+ // baseline). Since Y coordinates increase towards the bottom of
+ // the screen we reverse the sign.
+ coordOffset = textStyle->mVerticalAlign.GetCoordValue();
+ revisedBaselineY = baselineY - coordOffset;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+
+ case eStyleUnit_Percent:
+ // Similar to a length value (eStyleUnit_Coord) except that the
+ // percentage is a function of the elements line-height value.
+ elementLineHeight =
+ nsHTMLReflowState::CalcLineHeight(mPresContext, frame);
+ percentOffset = nscoord(
+ textStyle->mVerticalAlign.GetPercentValue() * elementLineHeight
+ );
+ revisedBaselineY = baselineY - percentOffset;
+ if (frameSpan) {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
+ }
+ else {
+ pfd->mBounds.y = revisedBaselineY - pfd->mAscent -
+ pfd->mMargin.bottom;
+ }
+ pfd->mVerticalAlign = VALIGN_OTHER;
+ break;
+ }
+
+ // Update minY/maxY for frames that we just placed
+ if (pfd->mVerticalAlign == VALIGN_OTHER) {
+ nscoord yTop, yBottom;
+ if (frameSpan) {
+ // For spans that were are now placing, use their position
+ // plus their already computed min-Y and max-Y values for
+ // computing yTop and yBottom.
+ yTop = pfd->mBounds.y + frameSpan->mMinY;
+ yBottom = pfd->mBounds.y + frameSpan->mMaxY;
+ }
+ else {
+ yTop = pfd->mBounds.y - pfd->mMargin.top;
+ yBottom = yTop + logicalHeight;
+ }
+ if (yTop < minY) minY = yTop;
+ if (yBottom > maxY) maxY = yBottom;
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ");
+ nsFrame::ListTag(stdout, frame);
+ printf(": raw: a=%d d=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minY=%d maxY=%d\n",
+ pfd->mAscent, pfd->mDescent, pfd->mBounds.height,
+ pfd->mBorderPadding.top, pfd->mBorderPadding.bottom,
+ logicalHeight,
+ pfd->mSpan ? topLeading : 0,
+ pfd->mBounds.y, minY, maxY);
+#endif
+ if (psd != mRootSpan) {
+ frame->SetRect(pfd->mBounds);
+ }
+ }
+ pfd = pfd->mNext;
+ }
+ NS_RELEASE(fm);
+ psd->mMinY = minY;
+ psd->mMaxY = maxY;
+#ifdef NOISY_VERTICAL_ALIGN
+ printf(" ==> minY=%d maxY=%d delta=%d maxBoxHeight=%d\n",
+ minY, maxY, maxY - minY, maxBoxHeight);
+#endif
+ if (maxTopBoxHeight > mMaxTopBoxHeight) {
+ mMaxTopBoxHeight = maxTopBoxHeight;
+ }
+ if (maxBottomBoxHeight > mMaxBottomBoxHeight) {
+ mMaxBottomBoxHeight = maxBottomBoxHeight;
+ }
+}
+
+void
+nsLineLayout::TrimTrailingWhiteSpace(nsRect& aLineBounds)
+{
+}
+
+void
+nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds, PRBool aAllowJustify)
+{
+ PerSpanData* psd = mRootSpan;
+ nscoord availWidth = psd->mRightEdge;
+ if (NS_UNCONSTRAINEDSIZE == availWidth) {
+ // Don't bother horizontal aligning on pass1 table reflow
+#ifdef REALLY_NOISY_HORIZONTAL_ALIGN
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": skipping horizontal alignment in pass1 table reflow\n");
+#endif
+ return;
+ }
+ availWidth -= psd->mLeftEdge;
+ nscoord remainingWidth = availWidth - aLineBounds.width;
+#ifdef REALLY_NOISY_HORIZONTAL_ALIGN
+ nsFrame::ListTag(stdout, mBlockReflowState->frame);
+ printf(": availWidth=%d lineWidth=%d delta=%d\n",
+ availWidth, aLineBounds.width, remainingWidth);
+#endif
+ if (remainingWidth > 0) {
+ nscoord dx = 0;
+ switch (mTextAlign) {
+ case NS_STYLE_TEXT_ALIGN_DEFAULT:
+ if (NS_STYLE_DIRECTION_LTR == mDirection) {
+ // default alignment for left-to-right is left so do nothing
+ break;
+ }
+ // Fall through to align right case for default alignment
+ // used when the direction is right-to-left.
+
+ case NS_STYLE_TEXT_ALIGN_RIGHT:
+ dx = remainingWidth;
+ break;
+
+ case NS_STYLE_TEXT_ALIGN_LEFT:
+ break;
+
+ case NS_STYLE_TEXT_ALIGN_JUSTIFY:
+ // If this is not the last line then go ahead and justify the
+ // frames in the line. If it is the last line then if the
+ // direction is right-to-left then we right-align the frames.
+ if (aAllowJustify) {
+ break;
+ }
+ else if (NS_STYLE_DIRECTION_RTL == mDirection) {
+ // right align the frames
+ dx = remainingWidth;;
+ }
+ break;
+
+ case NS_STYLE_TEXT_ALIGN_CENTER:
+ dx = remainingWidth / 2;
+ break;
+ }
+ if (0 != dx) {
+ PerFrameData* pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ pfd->mBounds.x += dx;
+ pfd->mFrame->SetRect(pfd->mBounds);
+ pfd = pfd->mNext;
+ }
+ }
+ }
+}
+
+void
+nsLineLayout::RelativePositionFrames(nsRect& aCombinedArea)
+{
+ RelativePositionFrames(mRootSpan, aCombinedArea);
+}
+
+void
+nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
+{
+ nsPoint origin;
+ nsRect spanCombinedArea;
+ PerFrameData* pfd;
+
+ nscoord x0, y0, x1, y1;
+ if (nsnull != psd->mFrame) {
+ // The minimum combined area for the frames in a span covers the
+ // entire span frame.
+ pfd = psd->mFrame;
+ x0 = 0;
+ y0 = 0;
+ x1 = pfd->mBounds.width;
+ y1 = pfd->mBounds.height;
+ }
+ else {
+ // The minimum combined area for the frames that are direct
+ // children of the block starts at the upper left corner of the
+ // line but has no width or height.
+ x1 = x0 = psd->mLeftEdge;
+ y1 = y0 = mTopEdge;
+ }
+
+ pfd = psd->mFirstFrame;
+ while (nsnull != pfd) {
+ nscoord x = pfd->mBounds.x;
+ nscoord y = pfd->mBounds.y;
+
+ // Adjust the origin of the frame
+ if (pfd->mRelativePos) {
+ nsIFrame* frame = pfd->mFrame;
+ frame->GetOrigin(origin);
+ // XXX what about right and bottom?
+ nscoord dx = pfd->mOffsets.left;
+ nscoord dy = pfd->mOffsets.top;
+ frame->MoveTo(origin.x + dx, origin.y + dy);
+ x += dx;
+ y += dy;
+ }
+
+ // Note: the combined area of a child is in its coordinate
+ // system. We adjust the childs combined area into our coordinate
+ // system before computing the aggregated value by adding in
+ // x and y which were computed above.
+ nsRect* r = &pfd->mCombinedArea;
+ if (pfd->mSpan) {
+ // Compute a new combined area for the child span before
+ // aggregating it into our combined area.
+ r = &spanCombinedArea;
+ RelativePositionFrames(pfd->mSpan, spanCombinedArea);
+ }
+
+ nscoord xl = x + r->x;
+ nscoord xr = x + r->XMost();
+ if (xl < x0) x0 = xl;
+ if (xr > x1) x1 = xr;
+ nscoord yt = y + r->y;
+ nscoord yb = y + r->YMost();
+ if (yt < y0) y0 = yt;
+ if (yb > y1) y1 = yb;
+
+ pfd = pfd->mNext;
+ }
+
+ // Compute aggregated combined area
+ aCombinedArea.x = x0;
+ aCombinedArea.y = y0;
+ aCombinedArea.width = x1 - x0;
+ aCombinedArea.height = y1 - y0;
+
+ // If we just computed a spans combined area, we need to update its
+ // NS_FRAME_OUTSIDE_CHILDREN bit..
+ if (nsnull != psd->mFrame) {
+ pfd = psd->mFrame;
+ nsIFrame* frame = pfd->mFrame;
+ nsFrameState oldState;
+ frame->GetFrameState(&oldState);
+ nsFrameState newState = oldState & ~NS_FRAME_OUTSIDE_CHILDREN;
+ if ((x0 < 0) || (y0 < 0) ||
+ (x1 > pfd->mBounds.width) || (y1 > pfd->mBounds.height)) {
+ newState |= NS_FRAME_OUTSIDE_CHILDREN;
+ }
+ if (newState != oldState) {
+ frame->SetFrameState(newState);
+ }
+ }
+}
+
+void
+nsLineLayout::ForgetWordFrame(nsIFrame* aFrame)
+{
+ NS_ASSERTION((void*)aFrame == mWordFrames[0], "forget-word-frame");
+ if (0 != mWordFrames.Count()) {
+ mWordFrames.RemoveElementAt(0);
}
- return nsnull;
}
nsIFrame*
@@ -164,56 +1810,41 @@ nsLineLayout::FindNextText(nsIFrame* aFrame)
return nsnull;
}
-PRBool
-nsLineLayout::IsNextWordFrame(nsIFrame* aFrame)
+nsresult
+nsLineLayout::AddText(nsIFrame* aTextFrame)
{
- if (0 != mWordFrames.Count()) {
- nsIFrame* next = (nsIFrame*) mWordFrames[0];
- return next == aFrame;
+ if (nsnull == mNewTextRun) {
+ mNewTextRun = new nsTextRun();
+ if (nsnull == mNewTextRun) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *mTextRunP = mNewTextRun;
+ mTextRunP = &mNewTextRun->mNext;
}
- return PR_FALSE;
-}
-
-PRBool
-nsLineLayout::IsLastWordFrame(nsIFrame* aFrame)
-{
- PRInt32 n = mWordFrames.Count();
- if (0 != n) {
- nsIFrame* next = (nsIFrame*) mWordFrames[0];
- return (next == aFrame) && (1 == n);
+ mNewTextRun->mArray.AppendElement(aTextFrame);
+#ifdef DEBUG_ADD_TEXT
+ PRInt32 n = mNewTextRun->mArray.Count();
+ for (PRInt32 i = 0; i < n - 1; i++) {
+ NS_ASSERTION(mNewTextRun->mArray[i] != (void*)aTextFrame, "yikes");
}
- return PR_FALSE;
+#endif
+ return NS_OK;/* XXX */
}
void
-nsLineLayout::ForgetWordFrame(nsIFrame* aFrame)
+nsLineLayout::EndTextRun()
{
- NS_ASSERTION((void*)aFrame == mWordFrames[0], "forget-word-frame");
- if (0 != mWordFrames.Count()) {
- mWordFrames.RemoveElementAt(0);
- }
+ mNewTextRun = nsnull;
}
-// XXX move this somewhere else!!!
-PRBool
-nsLineLayout::TreatFrameAsBlock(const nsStyleDisplay* aDisplay,
- const nsStylePosition* aPosition)
+nsTextRun*
+nsLineLayout::TakeTextRuns()
{
- if (NS_STYLE_POSITION_ABSOLUTE == aPosition->mPosition) {
- return PR_FALSE;
- }
- if (NS_STYLE_FLOAT_NONE != aDisplay->mFloats) {
- return PR_FALSE;
- }
- switch (aDisplay->mDisplay) {
- case NS_STYLE_DISPLAY_BLOCK:
- case NS_STYLE_DISPLAY_LIST_ITEM:
- case NS_STYLE_DISPLAY_RUN_IN:
- case NS_STYLE_DISPLAY_COMPACT:
- case NS_STYLE_DISPLAY_TABLE:
- return PR_TRUE;
- }
- return PR_FALSE;
+ nsTextRun* result = mTextRuns;
+ mTextRuns = nsnull;
+ mTextRunP = &mTextRuns;
+ mNewTextRun = nsnull;
+ return result;
}
PRBool
@@ -223,24 +1854,19 @@ nsLineLayout::TreatFrameAsBlock(nsIFrame* aFrame)
const nsStylePosition* position;
aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
aFrame->GetStyleData(eStyleStruct_Position,(const nsStyleStruct*&) position);
- return TreatFrameAsBlock(display, position);
-}
-
-void
-nsLineLayout::UpdateInlines(nscoord aX, nscoord aY,
- nscoord aWidth, nscoord aHeight,
- PRBool aIsLeftFloater)
-{
- PRInt32 i, n = mInlineStack.Count();
- for (i = 0; i < n; i++) {
- nsInlineReflow* ir = (nsInlineReflow*) mInlineStack[i];
- ir->UpdateBand(aX, aY, aWidth, aHeight, aIsLeftFloater);
-
- // After the first inline is updated the remainder are relative to
- // their parent therefore zap the x,y coordinates.
-
- // XXX border/padding adjustments need to be re-applied for inlines
- aX = 0;
- aY = 0;
+ if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) {
+ return PR_FALSE;
}
+ if (NS_STYLE_FLOAT_NONE != display->mFloats) {
+ return PR_FALSE;
+ }
+ switch (display->mDisplay) {
+ case NS_STYLE_DISPLAY_BLOCK:
+ case NS_STYLE_DISPLAY_LIST_ITEM:
+ case NS_STYLE_DISPLAY_RUN_IN:
+ case NS_STYLE_DISPLAY_COMPACT:
+ case NS_STYLE_DISPLAY_TABLE:
+ return PR_TRUE;
+ }
+ return PR_FALSE;
}
diff --git a/mozilla/layout/html/base/src/nsLineLayout.h b/mozilla/layout/html/base/src/nsLineLayout.h
index 3e16f842d76..1542bcd7dd5 100644
--- a/mozilla/layout/html/base/src/nsLineLayout.h
+++ b/mozilla/layout/html/base/src/nsLineLayout.h
@@ -19,132 +19,28 @@
#ifndef nsLineLayout_h___
#define nsLineLayout_h___
-#include "nsIFrame.h"
+#include "nsFrame.h"
#include "nsVoidArray.h"
#include "nsTextReflow.h"
+class nsISpaceManager;
class nsBlockReflowState;
-class nsInlineReflow;
class nsPlaceholderFrame;
-struct nsStyleDisplay;
-struct nsStylePosition;
-struct nsStyleSpacing;
-
-// XXX rename to nsLineReflow
-
-//----------------------------------------------------------------------
+struct nsStyleText;
class nsLineLayout {
public:
nsLineLayout(nsIPresContext& aPresContext,
- nsISpaceManager* aSpaceManager);
+ nsISpaceManager* aSpaceManager,
+ const nsHTMLReflowState* aOuterReflowState,
+ PRBool aComputeMaxElementSize);
+ nsLineLayout(nsIPresContext& aPresContext);
~nsLineLayout();
- void Init(nsBlockReflowState* aReflowState) {/* XXX ctor arg really */
- mBlockReflowState = aReflowState;
+ void Init(nsBlockReflowState* aState) {
+ mBlockRS = aState;
}
- // Prepare this line-layout for the reflow of a new line
- void Reset() {
- mTotalPlacedFrames = 0;
- mColumn = 0;
- mEndsInWhiteSpace = PR_TRUE;
- mUnderstandsWhiteSpace = PR_FALSE;
- mBRFrame = nsnull;
- mPlacedFrames.Clear();
- ForgetWordFrames();
- mFirstLetterStyleOK = PR_FALSE;
- mPass2VAlignCount = 0;
- }
-
- // Record the prescence of a frame that needs pass2 vertical-align
- // handling.
- void RecordPass2VAlignFrame() {
- mPass2VAlignCount++;
- }
-
- PRBool NeedPass2VAlign() const {
- return 0 != mPass2VAlignCount;
- }
-
- // Add to the placed-frame count
- void AddPlacedFrame(nsIFrame* aFrame) {
- mTotalPlacedFrames++;
- mPlacedFrames.AppendElement(aFrame);
- }
-
- // Get the placed-frame count
- PRInt32 GetPlacedFrames() const {
- return mTotalPlacedFrames;
- }
-
- const nsVoidArray& PlacedFrames() const {
- return mPlacedFrames;
- }
-
- void SetBRFrame(nsIFrame* aFrame) {
- mBRFrame = aFrame;
- }
-
- nsIFrame* GetBRFrame() const {
- return mBRFrame;
- }
-
- void PushInline(nsInlineReflow* aInlineReflow) {
- mInlineStack.AppendElement(aInlineReflow);
- }
-
- void PopInline() {
- PRInt32 n = mInlineStack.Count();
- if (n > 0) {
- mInlineStack.RemoveElementAt(n - 1);
- }
- }
-
- void UpdateInlines(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
- PRBool aPlacedLeftFloater);
-
- // Reset the text-run information in preparation for a FindTextRuns
- void ResetTextRuns();
-
- // Add another piece of text to a text-run during FindTextRuns.
- // Note: continuation frames must NOT add themselves; just the
- // first-in-flow
- nsresult AddText(nsIFrame* aTextFrame);
-
- // Close out a text-run during FindTextRuns.
- void EndTextRun();
-
- // This returns the first nsTextRun found during a
- // FindTextRuns. The internal text-run state is reset.
- nsTextRun* TakeTextRuns();
-
- void SetReflowTextRuns(nsTextRun* aTextRuns) {
- mReflowTextRuns = aTextRuns;
- }
-
- nsIFrame* FindNextText(nsIFrame* aFrame);
-
- nsTextRun* FindTextRunFor(nsIFrame* aFrame);
-
- void RecordWordFrame(nsIFrame* aWordFrame) {
- mWordFrames.AppendElement(aWordFrame);
- }
-
- void ForgetWordFrames() {
- mWordFrames.Clear();
- }
-
- PRBool IsNextWordFrame(nsIFrame* aFrame);
-
- PRBool InWord() {
- return 0 != mWordFrames.Count();
- }
-
- PRBool IsLastWordFrame(nsIFrame* aFrame);
-
- void ForgetWordFrame(nsIFrame* aFrame);
-
PRInt32 GetColumn() {
return mColumn;
}
@@ -153,7 +49,7 @@ public:
mColumn = aNewColumn;
}
- void NextLine() {
+ void AdvanceToNextLine() {
mLineNumber++;
}
@@ -161,33 +57,63 @@ public:
return mLineNumber;
}
- static PRBool TreatFrameAsBlock(const nsStyleDisplay* aDisplay,
- const nsStylePosition* aPosition);
+ void BeginLineReflow(nscoord aX, nscoord aY,
+ nscoord aWidth, nscoord aHeight,
+ PRBool aIsTopOfPage);
- static PRBool TreatFrameAsBlock(nsIFrame* aFrame);
+ void EndLineReflow();
- // --------------------------------------------------
+ void UpdateBand(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
+ PRBool aPlacedLeftFloater);
- void InitFloater(nsPlaceholderFrame* aFrame);
+ nsresult BeginSpan(nsIFrame* aFrame,
+ const nsHTMLReflowState* aSpanReflowState,
+ nscoord aLeftEdge,
+ nscoord aRightEdge);
- void AddFloater(nsPlaceholderFrame* aFrame);
+ void EndSpan(nsIFrame* aFrame, nsSize& aSizeResult,
+ nsSize* aMaxElementSize);
- nsIPresContext& mPresContext;
- nsISpaceManager* mSpaceManager;
- nsBlockReflowState* mBlockReflowState;
+ PRInt32 GetCurrentSpanCount() const;
- PRBool mListPositionOutside;
- PRInt32 mLineNumber;
- PRInt32 mColumn;
-
- void SetUnderstandsWhiteSpace(PRBool aSetting) {
- mUnderstandsWhiteSpace = aSetting;
+ void SplitLineTo(PRInt32 aNewCount);
+
+ PRBool IsZeroHeight();
+
+ nsresult ReflowFrame(nsIFrame* aFrame,
+ nsIFrame** aNextRCFrame,
+ nsReflowStatus& aReflowStatus);
+
+
+ nscoord GetCarriedOutTopMargin() const {
+ return mCurrentSpan->mLastFrame->mCarriedOutTopMargin;
}
- PRBool GetUnderstandsWhiteSpace() const {
- return mUnderstandsWhiteSpace;
+ nscoord GetCarriedOutBottomMargin() const {
+ return mCurrentSpan->mLastFrame->mCarriedOutBottomMargin;
}
+ nsresult AddBulletFrame(nsIFrame* aFrame,
+ const nsHTMLReflowMetrics& aMetrics);
+
+ void RemoveBulletFrame(nsIFrame* aFrame) {
+ PushFrame(aFrame);
+ }
+
+ void VerticalAlignFrames(nsRect& aLineBoxResult,
+ nsSize& aMaxElementSizeResult);
+
+ void TrimTrailingWhiteSpace(nsRect& aLineBounds);
+
+ void HorizontalAlignFrames(nsRect& aLineBounds, PRBool aAllowJustify);
+
+ void RelativePositionFrames(nsRect& aCombinedArea);
+
+ //----------------------------------------
+
+ // Support methods for white-space compression and word-wrapping
+ // during line reflow
+
void SetEndsInWhiteSpace(PRBool aState) {
mEndsInWhiteSpace = aState;
}
@@ -196,6 +122,51 @@ public:
return mEndsInWhiteSpace;
}
+ void SetUnderstandsWhiteSpace(PRBool aSetting) {
+ mUnderstandsWhiteSpace = aSetting;
+ }
+
+ void RecordWordFrame(nsIFrame* aWordFrame) {
+ mWordFrames.AppendElement(aWordFrame);
+ }
+
+ PRBool InWord() const {
+ return 0 != mWordFrames.Count();
+ }
+
+ void ForgetWordFrame(nsIFrame* aFrame);
+
+ void ForgetWordFrames() {
+ mWordFrames.Clear();
+ }
+
+ nsIFrame* FindNextText(nsIFrame* aFrame);
+
+ PRBool LineIsEmpty() const {
+ return 0 == mTotalPlacedFrames;
+ }
+
+ //----------------------------------------
+
+ // Inform the line-layout engine about the presence of a BR frame
+ // XXX get rid of this: use get-frame-type?
+ void SetBRFrame(nsIFrame* aFrame) {
+ mBRFrame = aFrame;
+ }
+
+ // Return the line's BR frame if any
+ nsIFrame* GetBRFrame() const {
+ return mBRFrame;
+ }
+
+ //----------------------------------------
+ // Inform the line-layout about the presence of a floating frame
+ // XXX get rid of this: use get-frame-type?
+ void InitFloater(nsPlaceholderFrame* aFrame);
+ void AddFloater(nsPlaceholderFrame* aFrame);
+
+ //----------------------------------------
+
PRBool GetFirstLetterStyleOK() const {
return mFirstLetterStyleOK;
}
@@ -204,29 +175,185 @@ public:
mFirstLetterStyleOK = aSetting;
}
-protected:
- nsIFrame* mBRFrame;
+ //----------------------------------------
+ // Text run usage methods. These methods are using during reflow to
+ // track the current text run and to advance through text runs.
+ void SetReflowTextRuns(nsTextRun* aTextRuns) {
+ mReflowTextRuns = aTextRuns;
+ }
+
+ //----------------------------------------
+
+ static PRBool TreatFrameAsBlock(nsIFrame* aFrame);
+
+ //----------------------------------------
+
+ // XXX Move this out of line-layout; make some little interface to
+ // deal with it...
+
+ // Add another piece of text to a text-run during FindTextRuns.
+ // Note: continuation frames must NOT add themselves; just the
+ // first-in-flow
+ nsresult AddText(nsIFrame* aTextFrame);
+
+ // Close out a text-run during FindTextRuns.
+ void EndTextRun();
+
+ // This returns the first nsTextRun found during a FindTextRuns. The
+ // internal text-run state is reset.
+ nsTextRun* TakeTextRuns();
+
+ nsIPresContext& mPresContext;
+
+protected:
+ // This state is constant for a given block frame doing line layout
+ nsISpaceManager* mSpaceManager;
+ const nsStyleText* mStyleText;
+ const nsHTMLReflowState* mBlockReflowState;
+ nsBlockReflowState* mBlockRS;/* XXX hack! */
+ nscoord mMinLineHeight;
+ PRBool mComputeMaxElementSize;
+ PRBool mNoWrap;
+ PRUint8 mTextAlign;
+ PRUint8 mDirection;
+
+ // This state varies during the reflow of a line
+ nsIFrame* mBRFrame;
+ PRInt32 mLineNumber;
+ PRInt32 mColumn;
PRBool mEndsInWhiteSpace;
PRBool mUnderstandsWhiteSpace;
PRBool mFirstLetterStyleOK;
- PRInt32 mPass2VAlignCount;
-
+ PRBool mIsTopOfPage;
+ PRBool mWasInWord;
+ PRBool mCanBreakBeforeFrame;
+ PRBool mUpdatedBand;
+ PRUint8 mPlacedFloaters;
PRInt32 mTotalPlacedFrames;
- nsVoidArray mPlacedFrames;
-
nsVoidArray mWordFrames;
- nsVoidArray mInlineStack;
+ nscoord mTopEdge;
+ nscoord mBottomEdge;
+ nscoord mMaxTopBoxHeight;
+ nscoord mMaxBottomBoxHeight;
- // These slots are used during FindTextRuns
+ nsTextRun* mReflowTextRuns;
+ nsTextRun* mTextRun;
+
+ // Per-frame data recorded by the line-layout reflow logic. This
+ // state is the state needed to post-process the line after reflow
+ // has completed (vertical alignment, horizontal alignment,
+ // justification and relative positioning).
+ struct PerSpanData;
+ struct PerFrameData {
+ // link to next/prev frame in same span
+ PerFrameData* mNext;
+ PerFrameData* mPrev;
+
+ // pointer to child span data if this is an inline container frame
+ PerSpanData* mSpan;
+
+ // The frame and its type
+ nsIFrame* mFrame;
+ nsCSSFrameType mFrameType;
+
+ // From metrics
+ nscoord mAscent, mDescent;
+ nsRect mBounds;
+ nsSize mMaxElementSize;
+ nsRect mCombinedArea;
+ nscoord mCarriedOutTopMargin;
+ nscoord mCarriedOutBottomMargin;
+
+ // From reflow-state
+ nsMargin mMargin;
+ nsMargin mBorderPadding;
+ nsMargin mOffsets;
+ PRBool mRelativePos;
+
+ // Other state we use
+ PRUint8 mVerticalAlign;
+ };
+ PerFrameData mFrameDataBuf[20];
+ PerFrameData* mFrameFreeList;
+
+ struct PerSpanData {
+ PerSpanData* mNext;
+ PerSpanData* mPrev;
+ PerSpanData* mParent;
+ PerFrameData* mFrame;
+ PerFrameData* mFirstFrame;
+ PerFrameData* mLastFrame;
+
+ const nsHTMLReflowState* mReflowState;
+ nscoord mLeftEdge;
+ nscoord mX;
+ nscoord mRightEdge;
+
+ nscoord mTopLeading, mBottomLeading;
+ nscoord mLogicalHeight;
+ nscoord mMinY, mMaxY;
+
+ void AppendFrame(PerFrameData* pfd) {
+ if (nsnull == mLastFrame) {
+ mFirstFrame = pfd;
+ }
+ else {
+ mLastFrame->mNext = pfd;
+ pfd->mPrev = mLastFrame;
+ }
+ mLastFrame = pfd;
+ }
+ };
+ PerSpanData mSpanDataBuf[20];
+ PerSpanData* mSpanFreeList;
+ PerSpanData* mRootSpan;
+ PerSpanData* mLastSpan;
+ PerSpanData* mCurrentSpan;
+ PRInt32 mSpanDepth;
+
+ // XXX These slots are used ONLY during FindTextRuns
nsTextRun* mTextRuns;
nsTextRun** mTextRunP;
nsTextRun* mNewTextRun;
- // These slots are used during InlineReflow
- nsTextRun* mReflowTextRuns;
- nsTextRun* mTextRun;
+ nsresult NewPerFrameData(PerFrameData** aResult);
+
+ nsresult NewPerSpanData(PerSpanData** aResult);
+
+ void FreeSpan(PerSpanData* psd);
+
+ PRBool InBlockContext() const {
+ return mSpanDepth == 0;
+ }
+
+ void PushFrame(nsIFrame* aFrame);
+
+ void ApplyLeftMargin(PerFrameData* pfd,
+ nsHTMLReflowState& aReflowState);
+
+ PRBool CanPlaceFrame(PerFrameData* pfd,
+ const nsHTMLReflowState& aReflowState,
+ nsHTMLReflowMetrics& aMetrics,
+ nsReflowStatus& aStatus);
+
+ void PlaceFrame(PerFrameData* pfd,
+ nsHTMLReflowMetrics& aMetrics);
+
+ void UpdateFrames();
+
+ void VerticalAlignFrames(PerSpanData* psd);
+
+ void PlaceTopBottomFrames(PerSpanData* psd,
+ nscoord aDistanceFromTop,
+ nscoord aLineHeight);
+
+ void RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea);
+
+#ifdef DEBUG
+ void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
+#endif
};
#endif /* nsLineLayout_h___ */