Spanked to collapse inline-reflow with line-layout into line-layout; fixed bugs #1278, #1990, #3527, #1670, etc.

This commit is contained in:
kipp%netscape.com 1999-03-18 21:03:25 +00:00
parent 4448c809b6
commit c9067260be
37 changed files with 4875 additions and 2836 deletions

View File

@ -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)

View File

@ -277,8 +277,6 @@ protected:
nsLineBox* aLine,
nscoord aDeltaY);
void TakeRunInFrames(nsBlockFrame* aRunInFrame);
nsresult ComputeTextRuns(nsIPresContext& aPresContext);
void BuildFloaterList();

View File

@ -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 {

View File

@ -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;

View File

@ -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 = &ll;
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)

View File

@ -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 = &ll;
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)

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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");

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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___ */

View File

@ -44,7 +44,6 @@ CPPSRCS= \
nsImageFrame.cpp \
nsImageMap.cpp \
nsInlineFrame.cpp \
nsInlineReflow.cpp \
nsLeafFrame.cpp \
nsLineBox.cpp \
nsLineLayout.cpp \

View File

@ -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 \

View File

@ -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 = &ll;
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)

View File

@ -277,8 +277,6 @@ protected:
nsLineBox* aLine,
nscoord aDeltaY);
void TakeRunInFrames(nsBlockFrame* aRunInFrame);
nsresult ComputeTextRuns(nsIPresContext& aPresContext);
void BuildFloaterList();

View File

@ -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 {

View File

@ -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;

View File

@ -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 = &ll;
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)

View File

@ -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 = &ll;
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)

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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) {

View File

@ -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___ */

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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___ */