Bug 263825. Make paginated floats work, and other fixes. r+sr=dbaron
This commit is contained in:
Родитель
9a36e969fe
Коммит
30604288b9
|
@ -538,6 +538,7 @@ nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
|
||||||
|
|
||||||
NS_ASSERTION(!entry->placeholderFrame, "Registering a placeholder for a frame that already has a placeholder!");
|
NS_ASSERTION(!entry->placeholderFrame, "Registering a placeholder for a frame that already has a placeholder!");
|
||||||
entry->placeholderFrame = aPlaceholderFrame;
|
entry->placeholderFrame = aPlaceholderFrame;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
|
||||||
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
|
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
|
||||||
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
|
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
|
||||||
LAYOUT_ATOM(overflowOutOfFlowsProperty, "OverflowOutOfFlowsProperty") // nsFrameList*
|
LAYOUT_ATOM(overflowOutOfFlowsProperty, "OverflowOutOfFlowsProperty") // nsFrameList*
|
||||||
LAYOUT_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsPlaceholder*
|
LAYOUT_ATOM(overflowPlaceholdersProperty, "OverflowPlaceholdersProperty") // nsFrameList*
|
||||||
LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
|
LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
|
||||||
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
|
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
|
||||||
LAYOUT_ATOM(tableBCProperty, "TableBCProperty") // table border collapsing info (e.g. damage area, table border widths)
|
LAYOUT_ATOM(tableBCProperty, "TableBCProperty") // table border collapsing info (e.g. damage area, table border widths)
|
||||||
|
|
|
@ -490,9 +490,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
||||||
PrettyUC(aReflowState.mComputedHeight, height);
|
PrettyUC(aReflowState.mComputedHeight, height);
|
||||||
printf("c=%s,%s \n", width, height);
|
printf("c=%s,%s \n", width, height);
|
||||||
}
|
}
|
||||||
if (nsBlockFrame::gNoisy) {
|
AutoNoisyIndenter indent(nsBlockFrame::gNoisy);
|
||||||
nsBlockFrame::gNoiseIndent++;
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
@ -665,11 +663,8 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (nsBlockFrame::gNoisy) {
|
|
||||||
nsBlockFrame::gNoiseIndent--;
|
|
||||||
}
|
|
||||||
if (nsBlockFrame::gNoisyReflow) {
|
if (nsBlockFrame::gNoisyReflow) {
|
||||||
nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent);
|
nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1);
|
||||||
printf("abs pos ");
|
printf("abs pos ");
|
||||||
if (nsnull != aKidFrame) {
|
if (nsnull != aKidFrame) {
|
||||||
nsIFrameDebug* frameDebug;
|
nsIFrameDebug* frameDebug;
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -63,6 +63,32 @@ class nsIntervalSet;
|
||||||
#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX 4
|
#define NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX 4
|
||||||
#define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX
|
#define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_ABSOLUTE_LIST_INDEX
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some invariants:
|
||||||
|
* -- The overflow out-of-flows list contains the out-of-
|
||||||
|
* flow frames whose placeholders are in the overflow list.
|
||||||
|
* -- A given piece of content has at most one placeholder
|
||||||
|
* frame in a block's normal child list.
|
||||||
|
* -- A given piece of content can have an unlimited number
|
||||||
|
* of placeholder frames in the overflow-lines list.
|
||||||
|
* -- A line containing a continuation placeholder contains
|
||||||
|
* only continuation placeholders.
|
||||||
|
* -- While a block is being reflowed, its overflowPlaceholdersList
|
||||||
|
* frame property points to an nsFrameList in its
|
||||||
|
* nsBlockReflowState. This list contains placeholders for
|
||||||
|
* floats whose prev-in-flow is in the block's regular line
|
||||||
|
* list. The list is always empty/non-existent after the
|
||||||
|
* block has been reflowed.
|
||||||
|
* -- In all these frame lists, if there are two frames for
|
||||||
|
* the same content appearing in the list, then the frames
|
||||||
|
* appear with the prev-in-flow before the next-in-flow.
|
||||||
|
* -- While reflowing a block, its overflow line list
|
||||||
|
* will usually be empty but in some cases will have lines
|
||||||
|
* (while we reflow the block at its shrink-wrap width).
|
||||||
|
* In this case any new overflowing content must be
|
||||||
|
* prepended to the overflow lines.
|
||||||
|
*/
|
||||||
|
|
||||||
// see nsHTMLParts.h for the public block state bits
|
// see nsHTMLParts.h for the public block state bits
|
||||||
#define NS_BLOCK_HAS_LINE_CURSOR 0x01000000
|
#define NS_BLOCK_HAS_LINE_CURSOR 0x01000000
|
||||||
#define NS_BLOCK_HAS_OVERFLOW_LINES 0x02000000
|
#define NS_BLOCK_HAS_OVERFLOW_LINES 0x02000000
|
||||||
|
@ -222,9 +248,11 @@ public:
|
||||||
virtual void DeleteNextInFlowChild(nsPresContext* aPresContext,
|
virtual void DeleteNextInFlowChild(nsPresContext* aPresContext,
|
||||||
nsIFrame* aNextInFlow);
|
nsIFrame* aNextInFlow);
|
||||||
|
|
||||||
// Determines whether the collapsed margin carried out of the last
|
/**
|
||||||
// line includes the margin-top of a line with clearance (in which
|
* Determines whether the collapsed margin carried out of the last
|
||||||
// case we must avoid collapsing that margin with our bottom margin)
|
* line includes the margin-top of a line with clearance (in which
|
||||||
|
* case we must avoid collapsing that margin with our bottom margin)
|
||||||
|
*/
|
||||||
PRBool CheckForCollapsedBottomMarginFromClearanceLine();
|
PRBool CheckForCollapsedBottomMarginFromClearanceLine();
|
||||||
|
|
||||||
/** return the topmost block child based on y-index.
|
/** return the topmost block child based on y-index.
|
||||||
|
@ -243,7 +271,7 @@ public:
|
||||||
|
|
||||||
// Create a contination for aPlaceholder and its out of flow frame and
|
// Create a contination for aPlaceholder and its out of flow frame and
|
||||||
// add it to the list of overflow floats
|
// add it to the list of overflow floats
|
||||||
nsresult SplitPlaceholder(nsPresContext& aPresContext, nsIFrame& aPlaceholder);
|
nsresult SplitPlaceholder(nsBlockReflowState& aState, nsIFrame* aPlaceholder);
|
||||||
|
|
||||||
void UndoSplitPlaceholders(nsBlockReflowState& aState,
|
void UndoSplitPlaceholders(nsBlockReflowState& aState,
|
||||||
nsIFrame* aLastPlaceholder);
|
nsIFrame* aLastPlaceholder);
|
||||||
|
@ -258,6 +286,12 @@ public:
|
||||||
aDirtyRect, aFrame, aWhichLayer, aFlags);
|
aDirtyRect, aFrame, aWhichLayer, aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool HandleOverflowPlaceholdersForPulledFrame(
|
||||||
|
nsBlockReflowState& aState, nsIFrame* aFrame);
|
||||||
|
|
||||||
|
PRBool HandleOverflowPlaceholdersOnPulledLine(
|
||||||
|
nsBlockReflowState& aState, nsLineBox* aLine);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsBlockFrame();
|
nsBlockFrame();
|
||||||
virtual ~nsBlockFrame();
|
virtual ~nsBlockFrame();
|
||||||
|
@ -331,18 +365,23 @@ protected:
|
||||||
nsresult AddFrames(nsIFrame* aFrameList,
|
nsresult AddFrames(nsIFrame* aFrameList,
|
||||||
nsIFrame* aPrevSibling);
|
nsIFrame* aPrevSibling);
|
||||||
|
|
||||||
|
public:
|
||||||
/** does all the real work for removing aDeletedFrame from this
|
/** does all the real work for removing aDeletedFrame from this
|
||||||
* finds the line containing aFrame.
|
* finds the line containing aFrame.
|
||||||
* handled continued frames
|
* handled continued frames
|
||||||
* marks lines dirty as needed
|
* marks lines dirty as needed
|
||||||
|
* @param aDestroyFrames if false then we don't actually destroy the
|
||||||
|
* frame or its next in flows, we just remove them. This does NOT work
|
||||||
|
* on out of flow frames so always use PR_TRUE for out of flows.
|
||||||
*/
|
*/
|
||||||
nsresult DoRemoveFrame(nsIFrame* aDeletedFrame);
|
nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, PRBool aDestroyFrames = PR_TRUE);
|
||||||
|
protected:
|
||||||
|
|
||||||
/** grab overflow lines from this block's prevInFlow, and make them
|
/** grab overflow lines from this block's prevInFlow, and make them
|
||||||
* part of this block's mLines list.
|
* part of this block's mLines list.
|
||||||
* @return PR_TRUE if any lines were drained.
|
* @return PR_TRUE if any lines were drained.
|
||||||
*/
|
*/
|
||||||
PRBool DrainOverflowLines();
|
PRBool DrainOverflowLines(nsBlockReflowState& aState);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a float from our float list and also the float cache
|
* Remove a float from our float list and also the float cache
|
||||||
|
@ -350,6 +389,8 @@ protected:
|
||||||
*/
|
*/
|
||||||
line_iterator RemoveFloat(nsIFrame* aFloat);
|
line_iterator RemoveFloat(nsIFrame* aFloat);
|
||||||
|
|
||||||
|
void CollectFloats(nsIFrame* aFrame, nsFrameList& aList, nsIFrame** aTail,
|
||||||
|
PRBool aFromOverflow);
|
||||||
// Remove a float, abs, rel positioned frame from the appropriate block's list
|
// Remove a float, abs, rel positioned frame from the appropriate block's list
|
||||||
static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame);
|
static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame);
|
||||||
|
|
||||||
|
@ -391,8 +432,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult PrepareResizeReflow(nsBlockReflowState& aState);
|
nsresult PrepareResizeReflow(nsBlockReflowState& aState);
|
||||||
|
|
||||||
/** reflow all lines that have been marked dirty */
|
/** reflow all lines that have been marked dirty.
|
||||||
nsresult ReflowDirtyLines(nsBlockReflowState& aState);
|
* @param aTryPull set this to PR_TRUE if you want to try pulling content from
|
||||||
|
* our next in flow while there is room.
|
||||||
|
*/
|
||||||
|
nsresult ReflowDirtyLines(nsBlockReflowState& aState, PRBool aTryPull);
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Methods for line reflow
|
// Methods for line reflow
|
||||||
|
@ -498,13 +542,13 @@ protected:
|
||||||
PRBool aDamageDeletedLine,
|
PRBool aDamageDeletedLine,
|
||||||
nsIFrame*& aFrameResult);
|
nsIFrame*& aFrameResult);
|
||||||
|
|
||||||
nsresult PullFrameFrom(nsBlockReflowState& aState,
|
PRBool PullFrameFrom(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine,
|
nsLineBox* aLine,
|
||||||
nsBlockFrame* aFromContainer,
|
nsBlockFrame* aFromContainer,
|
||||||
PRBool aFromOverflowLine,
|
PRBool aFromOverflowLine,
|
||||||
nsLineList::iterator aFromLine,
|
nsLineList::iterator aFromLine,
|
||||||
PRBool aDamageDeletedLines,
|
PRBool aDamageDeletedLines,
|
||||||
nsIFrame*& aFrameResult);
|
nsIFrame*& aFrameResult);
|
||||||
|
|
||||||
void PushLines(nsBlockReflowState& aState,
|
void PushLines(nsBlockReflowState& aState,
|
||||||
nsLineList::iterator aLineBefore);
|
nsLineList::iterator aLineBefore);
|
||||||
|
@ -552,17 +596,39 @@ protected:
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
|
public:
|
||||||
nsLineList* GetOverflowLines() const;
|
nsLineList* GetOverflowLines() const;
|
||||||
|
protected:
|
||||||
nsLineList* RemoveOverflowLines();
|
nsLineList* RemoveOverflowLines();
|
||||||
nsresult SetOverflowLines(nsLineList* aOverflowLines);
|
nsresult SetOverflowLines(nsLineList* aOverflowLines);
|
||||||
|
|
||||||
nsFrameList* GetOverflowPlaceholders() const;
|
nsFrameList* GetOverflowPlaceholders() const;
|
||||||
nsFrameList* RemoveOverflowPlaceholders();
|
|
||||||
nsresult SetOverflowPlaceholders(nsFrameList* aOverflowPlaceholders);
|
|
||||||
|
|
||||||
nsFrameList* GetOverflowOutOfFlows() const;
|
/**
|
||||||
nsFrameList* RemoveOverflowOutOfFlows();
|
* This class is useful for efficiently modifying the out of flow
|
||||||
nsresult SetOverflowOutOfFlows(nsFrameList* aFloaters);
|
* overflow list. It gives the client direct writable access to
|
||||||
|
* the frame list temporarily but ensures that property is only
|
||||||
|
* written back if absolutely necessary.
|
||||||
|
*/
|
||||||
|
struct nsAutoOOFFrameList {
|
||||||
|
nsFrameList mList;
|
||||||
|
|
||||||
|
nsAutoOOFFrameList(nsBlockFrame* aBlock) :
|
||||||
|
mList(aBlock->GetOverflowOutOfFlows().FirstChild()),
|
||||||
|
aOldHead(mList.FirstChild()), mBlock(aBlock) {}
|
||||||
|
~nsAutoOOFFrameList() {
|
||||||
|
if (mList.FirstChild() != aOldHead) {
|
||||||
|
mBlock->SetOverflowOutOfFlows(mList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
nsIFrame* aOldHead;
|
||||||
|
nsBlockFrame* mBlock;
|
||||||
|
};
|
||||||
|
friend class nsAutoOOFFrameList;
|
||||||
|
|
||||||
|
nsFrameList GetOverflowOutOfFlows() const;
|
||||||
|
void SetOverflowOutOfFlows(const nsFrameList& aList);
|
||||||
|
|
||||||
nsIFrame* LastChild();
|
nsIFrame* LastChild();
|
||||||
|
|
||||||
|
@ -613,5 +679,23 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
class AutoNoisyIndenter {
|
||||||
|
public:
|
||||||
|
AutoNoisyIndenter(PRBool aDoIndent) : mIndented(aDoIndent) {
|
||||||
|
if (mIndented) {
|
||||||
|
nsBlockFrame::gNoiseIndent++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~AutoNoisyIndenter() {
|
||||||
|
if (mIndented) {
|
||||||
|
nsBlockFrame::gNoiseIndent--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
PRBool mIndented;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* nsBlockFrame_h___ */
|
#endif /* nsBlockFrame_h___ */
|
||||||
|
|
||||||
|
|
|
@ -107,55 +107,79 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
|
||||||
if (0 == aRS.mComputedBorderPadding.top &&
|
if (0 == aRS.mComputedBorderPadding.top &&
|
||||||
!(aRS.frame->GetStateBits() & NS_BLOCK_MARGIN_ROOT) &&
|
!(aRS.frame->GetStateBits() & NS_BLOCK_MARGIN_ROOT) &&
|
||||||
NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, &bf))) {
|
NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, &bf))) {
|
||||||
nsBlockFrame* block = NS_STATIC_CAST(nsBlockFrame*, aRS.frame);
|
// iterate not just through the lines of 'block' but also its
|
||||||
|
// overflow lines and the normal and overflow lines of its next in
|
||||||
for (nsBlockFrame::line_iterator line = block->begin_lines(),
|
// flows. Note that this will traverse some frames more than once:
|
||||||
line_end = block->end_lines();
|
// for example, if A contains B and A->nextinflow contains
|
||||||
line != line_end; ++line) {
|
// B->nextinflow, we'll traverse B->nextinflow twice. But this is
|
||||||
if (!aClearanceFrame && line->HasClearance()) {
|
// OK because our traversal is idempotent.
|
||||||
// If we don't have a clearance frame, then we're computing
|
for (nsBlockFrame* block = NS_STATIC_CAST(nsBlockFrame*, aRS.frame);
|
||||||
// the collapsed margin in the first pass, assuming that all
|
block; block = NS_STATIC_CAST(nsBlockFrame*, block->GetNextInFlow())) {
|
||||||
// lines have no clearance. So clear their clearance flags.
|
for (PRBool overflowLines = PR_FALSE; overflowLines <= PR_TRUE; ++overflowLines) {
|
||||||
line->ClearHasClearance();
|
nsBlockFrame::line_iterator line;
|
||||||
line->MarkDirty();
|
nsBlockFrame::line_iterator line_end;
|
||||||
dirtiedLine = PR_TRUE;
|
PRBool anyLines = PR_TRUE;
|
||||||
|
if (overflowLines) {
|
||||||
|
nsLineList* lines = block->GetOverflowLines();
|
||||||
|
if (!lines) {
|
||||||
|
anyLines = PR_FALSE;
|
||||||
|
} else {
|
||||||
|
line = lines->begin();
|
||||||
|
line_end = lines->end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
line = block->begin_lines();
|
||||||
|
line_end = block->end_lines();
|
||||||
|
}
|
||||||
|
for (; anyLines && line != line_end; ++line) {
|
||||||
|
if (!aClearanceFrame && line->HasClearance()) {
|
||||||
|
// If we don't have a clearance frame, then we're computing
|
||||||
|
// the collapsed margin in the first pass, assuming that all
|
||||||
|
// lines have no clearance. So clear their clearance flags.
|
||||||
|
line->ClearHasClearance();
|
||||||
|
line->MarkDirty();
|
||||||
|
dirtiedLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool isEmpty = line->IsEmpty();
|
||||||
|
if (line->IsBlock()) {
|
||||||
|
nsBlockFrame* kidBlock = NS_STATIC_CAST(nsBlockFrame*, line->mFirstChild);
|
||||||
|
if (kidBlock == aClearanceFrame) {
|
||||||
|
line->SetHasClearance();
|
||||||
|
line->MarkDirty();
|
||||||
|
dirtiedLine = PR_TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
// Here is where we recur. Now that we have determined that a
|
||||||
|
// generational collapse is required we need to compute the
|
||||||
|
// child blocks margin and so in so that we can look into
|
||||||
|
// it. For its margins to be computed we need to have a reflow
|
||||||
|
// state for it. Since the reflow reason is irrelevant, we'll
|
||||||
|
// arbitrarily make it a `resize' to avoid the path-plucking
|
||||||
|
// behavior if we're in an incremental reflow.
|
||||||
|
nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight);
|
||||||
|
nsHTMLReflowState reflowState(kidBlock->GetPresContext(),
|
||||||
|
aRS, kidBlock,
|
||||||
|
availSpace, eReflowReason_Resize);
|
||||||
|
// Record that we're being optimistic by assuming the kid
|
||||||
|
// has no clearance
|
||||||
|
if (kidBlock->GetStyleDisplay()->mBreakType != NS_STYLE_CLEAR_NONE) {
|
||||||
|
*aMayNeedRetry = PR_TRUE;
|
||||||
|
}
|
||||||
|
if (ComputeCollapsedTopMargin(reflowState, aMargin, aClearanceFrame, aMayNeedRetry)) {
|
||||||
|
line->MarkDirty();
|
||||||
|
dirtiedLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
if (isEmpty)
|
||||||
|
aMargin->Include(reflowState.mComputedMargin.bottom);
|
||||||
|
}
|
||||||
|
if (!isEmpty)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool isEmpty = line->IsEmpty();
|
|
||||||
if (line->IsBlock()) {
|
|
||||||
nsBlockFrame* kidBlock = NS_STATIC_CAST(nsBlockFrame*, line->mFirstChild);
|
|
||||||
if (kidBlock == aClearanceFrame) {
|
|
||||||
line->SetHasClearance();
|
|
||||||
line->MarkDirty();
|
|
||||||
dirtiedLine = PR_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Here is where we recur. Now that we have determined that a
|
|
||||||
// generational collapse is required we need to compute the
|
|
||||||
// child blocks margin and so in so that we can look into
|
|
||||||
// it. For its margins to be computed we need to have a reflow
|
|
||||||
// state for it. Since the reflow reason is irrelevant, we'll
|
|
||||||
// arbitrarily make it a `resize' to avoid the path-plucking
|
|
||||||
// behavior if we're in an incremental reflow.
|
|
||||||
nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight);
|
|
||||||
nsHTMLReflowState reflowState(kidBlock->GetPresContext(),
|
|
||||||
aRS, kidBlock,
|
|
||||||
availSpace, eReflowReason_Resize);
|
|
||||||
// Record that we're being optimistic by assuming the kid
|
|
||||||
// has no clearance
|
|
||||||
if (kidBlock->GetStyleDisplay()->mBreakType != NS_STYLE_CLEAR_NONE) {
|
|
||||||
*aMayNeedRetry = PR_TRUE;
|
|
||||||
}
|
|
||||||
if (ComputeCollapsedTopMargin(reflowState, aMargin, aClearanceFrame, aMayNeedRetry)) {
|
|
||||||
line->MarkDirty();
|
|
||||||
dirtiedLine = PR_TRUE;
|
|
||||||
}
|
|
||||||
if (isEmpty)
|
|
||||||
aMargin->Include(reflowState.mComputedMargin.bottom);
|
|
||||||
}
|
|
||||||
if (!isEmpty)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOISY_VERTICAL_MARGINS
|
#ifdef NOISY_VERTICAL_MARGINS
|
||||||
|
@ -624,7 +648,9 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||||
if (nsnull != kidNextInFlow) {
|
if (nsnull != kidNextInFlow) {
|
||||||
// Remove all of the childs next-in-flows. Make sure that we ask
|
// Remove all of the childs next-in-flows. Make sure that we ask
|
||||||
// the right parent to do the removal (it's possible that the
|
// the right parent to do the removal (it's possible that the
|
||||||
// parent is not this because we are executing pullup code)
|
// parent is not this because we are executing pullup code).
|
||||||
|
// Floats will eventually be removed via nsBlockFrame::RemoveFloat
|
||||||
|
// which detaches the placeholder from the float.
|
||||||
/* XXX promote DeleteChildsNextInFlow to nsIFrame to elminate this cast */
|
/* XXX promote DeleteChildsNextInFlow to nsIFrame to elminate this cast */
|
||||||
NS_STATIC_CAST(nsHTMLContainerFrame*, kidNextInFlow->GetParent())
|
NS_STATIC_CAST(nsHTMLContainerFrame*, kidNextInFlow->GetParent())
|
||||||
->DeleteNextInFlowChild(mPresContext, kidNextInFlow);
|
->DeleteNextInFlowChild(mPresContext, kidNextInFlow);
|
||||||
|
@ -654,17 +680,20 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
||||||
const nsMargin& aComputedOffsets,
|
const nsMargin& aComputedOffsets,
|
||||||
nsCollapsingMargin& aBottomMarginResult,
|
nsCollapsingMargin& aBottomMarginResult,
|
||||||
nsRect& aInFlowBounds,
|
nsRect& aInFlowBounds,
|
||||||
nsRect& aCombinedRect)
|
nsRect& aCombinedRect,
|
||||||
|
nsReflowStatus aReflowStatus)
|
||||||
{
|
{
|
||||||
// Compute collapsed bottom margin value
|
// Compute collapsed bottom margin value.
|
||||||
aBottomMarginResult = mMetrics.mCarriedOutBottomMargin;
|
if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
|
||||||
aBottomMarginResult.Include(mMargin.bottom);
|
aBottomMarginResult = mMetrics.mCarriedOutBottomMargin;
|
||||||
|
aBottomMarginResult.Include(mMargin.bottom);
|
||||||
|
} else {
|
||||||
|
// The used bottom-margin is set to zero above a break.
|
||||||
|
aBottomMarginResult.Zero();
|
||||||
|
}
|
||||||
|
|
||||||
// See if the block will fit in the available space
|
|
||||||
PRBool fits;
|
|
||||||
nscoord x = mX;
|
nscoord x = mX;
|
||||||
nscoord y = mY;
|
nscoord y = mY;
|
||||||
|
|
||||||
nscoord backupContainingBlockAdvance = 0;
|
nscoord backupContainingBlockAdvance = 0;
|
||||||
|
|
||||||
// Check whether the block's bottom margin collapses with its top
|
// Check whether the block's bottom margin collapses with its top
|
||||||
|
@ -673,11 +702,12 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
||||||
// check that first. Note that a block can have clearance and still
|
// check that first. Note that a block can have clearance and still
|
||||||
// have adjoining top/bottom margins, because the clearance goes
|
// have adjoining top/bottom margins, because the clearance goes
|
||||||
// above the top margin.
|
// above the top margin.
|
||||||
if (0 == mMetrics.height && aLine->CachedIsEmpty())
|
PRBool empty = 0 == mMetrics.height && aLine->CachedIsEmpty();
|
||||||
{
|
if (empty) {
|
||||||
// Collapse the bottom margin with the top margin that was already
|
// Collapse the bottom margin with the top margin that was already
|
||||||
// applied.
|
// applied.
|
||||||
aBottomMarginResult.Include(mTopMargin);
|
aBottomMarginResult.Include(mTopMargin);
|
||||||
|
|
||||||
#ifdef NOISY_VERTICAL_MARGINS
|
#ifdef NOISY_VERTICAL_MARGINS
|
||||||
printf(" ");
|
printf(" ");
|
||||||
nsFrame::ListTag(stdout, mOuterReflowState.frame);
|
nsFrame::ListTag(stdout, mOuterReflowState.frame);
|
||||||
|
@ -686,10 +716,6 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
||||||
printf(" -- collapsing top & bottom margin together; y=%d spaceY=%d\n",
|
printf(" -- collapsing top & bottom margin together; y=%d spaceY=%d\n",
|
||||||
y, mSpace.y);
|
y, mSpace.y);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Empty blocks always fit
|
|
||||||
fits = PR_TRUE;
|
|
||||||
|
|
||||||
// Section 8.3.1 of CSS 2.1 says that blocks with adjoining
|
// Section 8.3.1 of CSS 2.1 says that blocks with adjoining
|
||||||
// top/bottom margins whose top margin collapses with their
|
// top/bottom margins whose top margin collapses with their
|
||||||
// parent's top margin should have their top border-edge at the
|
// parent's top margin should have their top border-edge at the
|
||||||
|
@ -709,97 +735,92 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
||||||
// point from where this empty block will be.
|
// point from where this empty block will be.
|
||||||
backupContainingBlockAdvance = mTopMargin.get();
|
backupContainingBlockAdvance = mTopMargin.get();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// See if the frame fit. If it's the first frame then it always
|
|
||||||
// fits. If the height is unconstrained then it always fits, even
|
|
||||||
// if there's some sort of integer overflow that makes
|
|
||||||
// y + mMetrics.height appear to go beyond the available height.
|
|
||||||
// XXX This is a bit of a hack. We really need to use floats in layout!
|
|
||||||
if (aForceFit ||
|
|
||||||
mSpace.height == NS_UNCONSTRAINEDSIZE ||
|
|
||||||
y + mMetrics.height <= mSpace.YMost())
|
|
||||||
{
|
|
||||||
fits = PR_TRUE;
|
|
||||||
|
|
||||||
// Adjust the max-element-size in the metrics to take into
|
// See if the frame fit. If it's the first frame or empty then it
|
||||||
// account the margins around the block element.
|
// always fits. If the height is unconstrained then it always fits,
|
||||||
// Do not allow auto margins to impact the max-element size
|
// even if there's some sort of integer overflow that makes y +
|
||||||
// since they are springy and don't really count!
|
// mMetrics.height appear to go beyond the available height.
|
||||||
if (mMetrics.mComputeMEW) {
|
if (!empty && !aForceFit && mSpace.height != NS_UNCONSTRAINEDSIZE) {
|
||||||
nsMargin maxElemMargin;
|
nscoord yMost = y - backupContainingBlockAdvance + mMetrics.height;
|
||||||
const nsStyleSides &styleMargin = mStyleMargin->mMargin;
|
if (yMost > mSpace.YMost()) {
|
||||||
nsStyleCoord coord;
|
// didn't fit, we must acquit.
|
||||||
if (styleMargin.GetLeftUnit() == eStyleUnit_Coord)
|
|
||||||
maxElemMargin.left = styleMargin.GetLeft(coord).GetCoordValue();
|
|
||||||
else
|
|
||||||
maxElemMargin.left = 0;
|
|
||||||
if (styleMargin.GetRightUnit() == eStyleUnit_Coord)
|
|
||||||
maxElemMargin.right = styleMargin.GetRight(coord).GetCoordValue();
|
|
||||||
else
|
|
||||||
maxElemMargin.right = 0;
|
|
||||||
|
|
||||||
nscoord dummyXOffset;
|
|
||||||
// Base the margins on the max-element size
|
|
||||||
ComputeShrinkwrapMargins(mStyleMargin, mMetrics.mMaxElementWidth,
|
|
||||||
maxElemMargin, dummyXOffset);
|
|
||||||
|
|
||||||
mMetrics.mMaxElementWidth += maxElemMargin.left + maxElemMargin.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the same for the maximum width
|
|
||||||
if (mComputeMaximumWidth) {
|
|
||||||
nsMargin maxWidthMargin;
|
|
||||||
const nsStyleSides &styleMargin = mStyleMargin->mMargin;
|
|
||||||
nsStyleCoord coord;
|
|
||||||
if (styleMargin.GetLeftUnit() == eStyleUnit_Coord)
|
|
||||||
maxWidthMargin.left = styleMargin.GetLeft(coord).GetCoordValue();
|
|
||||||
else
|
|
||||||
maxWidthMargin.left = 0;
|
|
||||||
if (styleMargin.GetRightUnit() == eStyleUnit_Coord)
|
|
||||||
maxWidthMargin.right = styleMargin.GetRight(coord).GetCoordValue();
|
|
||||||
else
|
|
||||||
maxWidthMargin.right = 0;
|
|
||||||
|
|
||||||
nscoord dummyXOffset;
|
|
||||||
// Base the margins on the maximum width
|
|
||||||
ComputeShrinkwrapMargins(mStyleMargin, mMetrics.mMaximumWidth,
|
|
||||||
maxWidthMargin, dummyXOffset);
|
|
||||||
|
|
||||||
mMetrics.mMaximumWidth += maxWidthMargin.left + maxWidthMargin.right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Send the DidReflow() notification, but don't bother placing
|
|
||||||
// the frame
|
|
||||||
mFrame->DidReflow(mPresContext, &aReflowState, NS_FRAME_REFLOW_FINISHED);
|
mFrame->DidReflow(mPresContext, &aReflowState, NS_FRAME_REFLOW_FINISHED);
|
||||||
fits = PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fits) {
|
if (!empty)
|
||||||
// Calculate the actual x-offset and left and right margin
|
{
|
||||||
nsBlockHorizontalAlign align;
|
// Adjust the max-element-size in the metrics to take into
|
||||||
align.mXOffset = x;
|
// account the margins around the block element.
|
||||||
AlignBlockHorizontally(mMetrics.width, align);
|
// Do not allow auto margins to impact the max-element size
|
||||||
x = align.mXOffset;
|
// since they are springy and don't really count!
|
||||||
mMargin.left = align.mLeftMargin;
|
if (mMetrics.mComputeMEW) {
|
||||||
mMargin.right = align.mRightMargin;
|
nsMargin maxElemMargin;
|
||||||
|
const nsStyleSides &styleMargin = mStyleMargin->mMargin;
|
||||||
|
nsStyleCoord coord;
|
||||||
|
if (styleMargin.GetLeftUnit() == eStyleUnit_Coord)
|
||||||
|
maxElemMargin.left = styleMargin.GetLeft(coord).GetCoordValue();
|
||||||
|
else
|
||||||
|
maxElemMargin.left = 0;
|
||||||
|
if (styleMargin.GetRightUnit() == eStyleUnit_Coord)
|
||||||
|
maxElemMargin.right = styleMargin.GetRight(coord).GetCoordValue();
|
||||||
|
else
|
||||||
|
maxElemMargin.right = 0;
|
||||||
|
|
||||||
|
nscoord dummyXOffset;
|
||||||
|
// Base the margins on the max-element size
|
||||||
|
ComputeShrinkwrapMargins(mStyleMargin, mMetrics.mMaxElementWidth,
|
||||||
|
maxElemMargin, dummyXOffset);
|
||||||
|
|
||||||
|
mMetrics.mMaxElementWidth += maxElemMargin.left + maxElemMargin.right;
|
||||||
|
}
|
||||||
|
|
||||||
aInFlowBounds = nsRect(x, y - backupContainingBlockAdvance,
|
// do the same for the maximum width
|
||||||
mMetrics.width, mMetrics.height);
|
if (mComputeMaximumWidth) {
|
||||||
|
nsMargin maxWidthMargin;
|
||||||
// Apply CSS relative positioning
|
const nsStyleSides &styleMargin = mStyleMargin->mMargin;
|
||||||
const nsStyleDisplay* styleDisp = mFrame->GetStyleDisplay();
|
nsStyleCoord coord;
|
||||||
if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
|
if (styleMargin.GetLeftUnit() == eStyleUnit_Coord)
|
||||||
x += aComputedOffsets.left;
|
maxWidthMargin.left = styleMargin.GetLeft(coord).GetCoordValue();
|
||||||
y += aComputedOffsets.top;
|
else
|
||||||
|
maxWidthMargin.left = 0;
|
||||||
|
if (styleMargin.GetRightUnit() == eStyleUnit_Coord)
|
||||||
|
maxWidthMargin.right = styleMargin.GetRight(coord).GetCoordValue();
|
||||||
|
else
|
||||||
|
maxWidthMargin.right = 0;
|
||||||
|
|
||||||
|
nscoord dummyXOffset;
|
||||||
|
// Base the margins on the maximum width
|
||||||
|
ComputeShrinkwrapMargins(mStyleMargin, mMetrics.mMaximumWidth,
|
||||||
|
maxWidthMargin, dummyXOffset);
|
||||||
|
|
||||||
|
mMetrics.mMaximumWidth += maxWidthMargin.left + maxWidthMargin.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now place the frame and complete the reflow process
|
|
||||||
nsContainerFrame::FinishReflowChild(mFrame, mPresContext, &aReflowState, mMetrics, x, y, 0);
|
|
||||||
|
|
||||||
aCombinedRect = mMetrics.mOverflowArea + nsPoint(x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fits;
|
// Calculate the actual x-offset and left and right margin
|
||||||
|
nsBlockHorizontalAlign align;
|
||||||
|
align.mXOffset = x;
|
||||||
|
AlignBlockHorizontally(mMetrics.width, align);
|
||||||
|
x = align.mXOffset;
|
||||||
|
mMargin.left = align.mLeftMargin;
|
||||||
|
mMargin.right = align.mRightMargin;
|
||||||
|
|
||||||
|
aInFlowBounds = nsRect(x, y - backupContainingBlockAdvance,
|
||||||
|
mMetrics.width, mMetrics.height);
|
||||||
|
|
||||||
|
// Apply CSS relative positioning
|
||||||
|
const nsStyleDisplay* styleDisp = mFrame->GetStyleDisplay();
|
||||||
|
if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
|
||||||
|
x += aComputedOffsets.left;
|
||||||
|
y += aComputedOffsets.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now place the frame and complete the reflow process
|
||||||
|
nsContainerFrame::FinishReflowChild(mFrame, mPresContext, &aReflowState, mMetrics, x, y, 0);
|
||||||
|
|
||||||
|
aCombinedRect = mMetrics.mOverflowArea + nsPoint(x, y);
|
||||||
|
|
||||||
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,8 @@ public:
|
||||||
const nsMargin& aComputedOffsets,
|
const nsMargin& aComputedOffsets,
|
||||||
nsCollapsingMargin& aBottomMarginResult /* out */,
|
nsCollapsingMargin& aBottomMarginResult /* out */,
|
||||||
nsRect& aInFlowBounds,
|
nsRect& aInFlowBounds,
|
||||||
nsRect& aCombinedRect);
|
nsRect& aCombinedRect,
|
||||||
|
nsReflowStatus aReflowStatus);
|
||||||
|
|
||||||
void AlignBlockHorizontally(nscoord aWidth, nsBlockHorizontalAlign&);
|
void AlignBlockHorizontally(nscoord aWidth, nsBlockHorizontalAlign&);
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,12 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
|
if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
||||||
|
mBlock->SetProperty(nsLayoutAtoms::overflowPlaceholdersProperty,
|
||||||
|
&mOverflowPlaceholders, nsnull);
|
||||||
|
mBlock->AddStateBits(NS_BLOCK_HAS_OVERFLOW_PLACEHOLDERS);
|
||||||
|
}
|
||||||
|
|
||||||
if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) {
|
if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
@ -172,6 +178,11 @@ nsBlockReflowState::~nsBlockReflowState()
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
mSpaceManager->Translate(-borderPadding.left, -borderPadding.top);
|
mSpaceManager->Translate(-borderPadding.left, -borderPadding.top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
||||||
|
mBlock->UnsetProperty(nsLayoutAtoms::overflowPlaceholdersProperty);
|
||||||
|
mBlock->RemoveStateBits(NS_BLOCK_HAS_OVERFLOW_PLACEHOLDERS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLineBox*
|
nsLineBox*
|
||||||
|
@ -543,7 +554,7 @@ nsBlockReflowState::IsImpactedByFloat() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PRBool
|
||||||
nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
|
nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
|
||||||
nsPlaceholderFrame* aPlaceholder,
|
nsPlaceholderFrame* aPlaceholder,
|
||||||
nsReflowStatus& aReflowStatus)
|
nsReflowStatus& aReflowStatus)
|
||||||
|
@ -554,7 +565,7 @@ nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
|
||||||
|
|
||||||
// Then add the float to the current line and place it when
|
// Then add the float to the current line and place it when
|
||||||
// appropriate
|
// appropriate
|
||||||
AddFloat(aLineLayout, aPlaceholder, PR_TRUE, aReflowStatus);
|
return AddFloat(aLineLayout, aPlaceholder, PR_TRUE, aReflowStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called by the line layout's AddFloat method when a
|
// This is called by the line layout's AddFloat method when a
|
||||||
|
@ -567,7 +578,7 @@ nsBlockReflowState::InitFloat(nsLineLayout& aLineLayout,
|
||||||
// technically we're supposed let the current line flow around the
|
// technically we're supposed let the current line flow around the
|
||||||
// float as well unless it won't fit next to what we already have.
|
// float as well unless it won't fit next to what we already have.
|
||||||
// But nobody else implements it that way...
|
// But nobody else implements it that way...
|
||||||
void
|
PRBool
|
||||||
nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||||
nsPlaceholderFrame* aPlaceholder,
|
nsPlaceholderFrame* aPlaceholder,
|
||||||
PRBool aInitialReflow,
|
PRBool aInitialReflow,
|
||||||
|
@ -582,12 +593,11 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||||
fc->mIsCurrentLineFloat = aLineLayout.CanPlaceFloatNow();
|
fc->mIsCurrentLineFloat = aLineLayout.CanPlaceFloatNow();
|
||||||
fc->mMaxElementWidth = 0;
|
fc->mMaxElementWidth = 0;
|
||||||
|
|
||||||
|
PRBool placed;
|
||||||
|
|
||||||
// Now place the float immediately if possible. Otherwise stash it
|
// Now place the float immediately if possible. Otherwise stash it
|
||||||
// away in mPendingFloats and place it later.
|
// away in mPendingFloats and place it later.
|
||||||
if (fc->mIsCurrentLineFloat) {
|
if (fc->mIsCurrentLineFloat) {
|
||||||
// Record this float in the current-line list
|
|
||||||
mCurrentLineFloats.Append(fc);
|
|
||||||
|
|
||||||
// Because we are in the middle of reflowing a placeholder frame
|
// Because we are in the middle of reflowing a placeholder frame
|
||||||
// within a line (and possibly nested in an inline frame or two
|
// within a line (and possibly nested in an inline frame or two
|
||||||
// that's a child of our block) we need to restore the space
|
// that's a child of our block) we need to restore the space
|
||||||
|
@ -601,15 +611,19 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||||
|
|
||||||
// And then place it
|
// And then place it
|
||||||
PRBool isLeftFloat;
|
PRBool isLeftFloat;
|
||||||
FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus);
|
placed = FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus);
|
||||||
|
if (placed) {
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloat,
|
isLeftFloat,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
|
||||||
|
// Record this float in the current-line list
|
||||||
|
mCurrentLineFloats.Append(fc);
|
||||||
|
}
|
||||||
|
|
||||||
// Restore coordinate system
|
// Restore coordinate system
|
||||||
mSpaceManager->Translate(dx, dy);
|
mSpaceManager->Translate(dx, dy);
|
||||||
|
@ -618,7 +632,16 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||||
// This float will be placed after the line is done (it is a
|
// This float will be placed after the line is done (it is a
|
||||||
// below-current-line float).
|
// below-current-line float).
|
||||||
mBelowCurrentLineFloats.Append(fc);
|
mBelowCurrentLineFloats.Append(fc);
|
||||||
|
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
||||||
|
// If the float might not be complete, mark it incomplete now to
|
||||||
|
// prevent the placeholders being torn down. We will destroy any
|
||||||
|
// placeholders later if PlaceBelowCurrentLineFloats finds the
|
||||||
|
// float is complete.
|
||||||
|
aReflowStatus = NS_FRAME_NOT_COMPLETE;
|
||||||
|
}
|
||||||
|
placed = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
return placed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -716,6 +739,12 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
||||||
nscoord saveY = mY;
|
nscoord saveY = mY;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Get the available space at the new Y coordinate
|
// Get the available space at the new Y coordinate
|
||||||
|
if (mAvailSpaceRect.height <= 0) {
|
||||||
|
// there is no more available space. We lose.
|
||||||
|
result = PR_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mY += mAvailSpaceRect.height;
|
mY += mAvailSpaceRect.height;
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
|
|
||||||
|
@ -752,7 +781,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
PRBool
|
||||||
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
PRBool* aIsLeftFloat,
|
PRBool* aIsLeftFloat,
|
||||||
nsReflowStatus& aReflowStatus)
|
nsReflowStatus& aReflowStatus)
|
||||||
|
@ -821,6 +850,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
PRBool keepFloatOnSameLine = PR_FALSE;
|
PRBool keepFloatOnSameLine = PR_FALSE;
|
||||||
|
|
||||||
while (! CanPlaceFloat(floatSize, floatDisplay->mFloats)) {
|
while (! CanPlaceFloat(floatSize, floatDisplay->mFloats)) {
|
||||||
|
if (mAvailSpaceRect.height <= 0) {
|
||||||
|
// No space, nowhere to put anything.
|
||||||
|
mY = saveY;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// Nope. try to advance to the next band.
|
// Nope. try to advance to the next band.
|
||||||
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
|
if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
|
||||||
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
||||||
|
@ -880,25 +915,10 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
}
|
}
|
||||||
// If the float is continued, it will get the same absolute x value as its prev-in-flow
|
// If the float is continued, it will get the same absolute x value as its prev-in-flow
|
||||||
nsRect prevRect(0,0,0,0);
|
nsRect prevRect(0,0,0,0);
|
||||||
nsIFrame* prevInFlow = floatFrame->GetPrevInFlow();
|
|
||||||
if (prevInFlow) {
|
|
||||||
prevRect = prevInFlow->GetRect();
|
|
||||||
|
|
||||||
// If prevInFlow's placeholder is in a block that wasn't continued, we need to adjust
|
// We don't worry about the geometry of the prev in flow, let the continuation
|
||||||
// prevRect.x to account for the missing frame offsets.
|
// place and size itself as required.
|
||||||
nsIFrame* placeParent = placeholder->GetParent();
|
|
||||||
nsIFrame* placeParentPrev = placeParent->GetPrevInFlow();
|
|
||||||
nsIFrame* prevPlace =
|
|
||||||
mPresContext->FrameManager()->GetPlaceholderFrameFor(prevInFlow);
|
|
||||||
|
|
||||||
nsIFrame* prevPlaceParent = prevPlace->GetParent();
|
|
||||||
|
|
||||||
for (nsIFrame* ancestor = prevPlaceParent;
|
|
||||||
ancestor && (ancestor != placeParentPrev);
|
|
||||||
ancestor = ancestor->GetParent()) {
|
|
||||||
prevRect.x += ancestor->GetRect().x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Assign an x and y coordinate to the float. Note that the x,y
|
// Assign an x and y coordinate to the float. Note that the x,y
|
||||||
// coordinates are computed <b>relative to the translation in the
|
// coordinates are computed <b>relative to the translation in the
|
||||||
// spacemanager</b> which means that the impacted region will be
|
// spacemanager</b> which means that the impacted region will be
|
||||||
|
@ -907,15 +927,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
nscoord floatX, floatY;
|
nscoord floatX, floatY;
|
||||||
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
|
if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
|
||||||
isLeftFloat = PR_TRUE;
|
isLeftFloat = PR_TRUE;
|
||||||
floatX = (prevInFlow) ? prevRect.x : mAvailSpaceRect.x;
|
floatX = mAvailSpaceRect.x;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloat = PR_FALSE;
|
isLeftFloat = PR_FALSE;
|
||||||
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.width) {
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.width) {
|
||||||
if (prevInFlow) {
|
if (!keepFloatOnSameLine) {
|
||||||
floatX = prevRect.x;
|
|
||||||
}
|
|
||||||
else if (!keepFloatOnSameLine) {
|
|
||||||
floatX = mAvailSpaceRect.XMost() - floatSize.width;
|
floatX = mAvailSpaceRect.XMost() - floatSize.width;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -947,7 +964,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
// if the float split, then take up all of the vertical height
|
// if the float split, then take up all of the vertical height
|
||||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
|
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
|
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
|
||||||
floatSize.height = PR_MAX(floatSize.height, mContentArea.height);
|
floatSize.height = PR_MAX(floatSize.height, mContentArea.height - floatY);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect region(floatX, floatY, floatSize.width, floatSize.height);
|
nsRect region(floatX, floatY, floatSize.width, floatSize.height);
|
||||||
|
@ -1041,6 +1058,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
printf(" %d,%d,%d,%d\n", r.x, r.y, r.width, r.height);
|
printf(" %d,%d,%d,%d\n", r.x, r.y, r.width, r.height);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1066,17 +1085,25 @@ nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheList& aList)
|
||||||
// Place the float
|
// Place the float
|
||||||
PRBool isLeftFloat;
|
PRBool isLeftFloat;
|
||||||
nsReflowStatus reflowStatus;
|
nsReflowStatus reflowStatus;
|
||||||
FlowAndPlaceFloat(fc, &isLeftFloat, reflowStatus);
|
PRBool placed = FlowAndPlaceFloat(fc, &isLeftFloat, reflowStatus);
|
||||||
|
|
||||||
if (NS_FRAME_IS_TRUNCATED(reflowStatus)) {
|
if (!placed || NS_FRAME_IS_TRUNCATED(reflowStatus)) {
|
||||||
// return before processing all of the floats, since the line will be pushed.
|
// return before processing all of the floats, since the line will be pushed.
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
else if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
|
else if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
|
||||||
// Create a continuation for the incomplete float and its placeholder.
|
// Create a continuation for the incomplete float and its placeholder.
|
||||||
nsresult rv = mBlock->SplitPlaceholder(*mPresContext, *fc->mPlaceholder);
|
nsresult rv = mBlock->SplitPlaceholder(*this, fc->mPlaceholder);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
} else {
|
||||||
|
// Float is complete. We need to delete any leftover placeholders now.
|
||||||
|
nsIFrame* nextPlaceholder = fc->mPlaceholder->GetNextInFlow();
|
||||||
|
if (nextPlaceholder) {
|
||||||
|
nsHTMLContainerFrame* parent =
|
||||||
|
NS_STATIC_CAST(nsHTMLContainerFrame*, nextPlaceholder->GetParent());
|
||||||
|
parent->DeleteNextInFlowChild(mPresContext, nextPlaceholder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fc = fc->Next();
|
fc = fc->Next();
|
||||||
|
|
|
@ -68,21 +68,22 @@ public:
|
||||||
|
|
||||||
void GetAvailableSpace(nscoord aY);
|
void GetAvailableSpace(nscoord aY);
|
||||||
|
|
||||||
void InitFloat(nsLineLayout& aLineLayout,
|
/*
|
||||||
nsPlaceholderFrame* aPlaceholderFrame,
|
* The following functions all return PR_TRUE if they were able to
|
||||||
nsReflowStatus& aReflowStatus);
|
* place the float, PR_FALSE if the float did not fit in available
|
||||||
|
* space.
|
||||||
void AddFloat(nsLineLayout& aLineLayout,
|
*/
|
||||||
nsPlaceholderFrame* aPlaceholderFrame,
|
PRBool InitFloat(nsLineLayout& aLineLayout,
|
||||||
PRBool aInitialReflow,
|
nsPlaceholderFrame* aPlaceholderFrame,
|
||||||
nsReflowStatus& aReflowStatus);
|
nsReflowStatus& aReflowStatus);
|
||||||
|
PRBool AddFloat(nsLineLayout& aLineLayout,
|
||||||
|
nsPlaceholderFrame* aPlaceholderFrame,
|
||||||
|
PRBool aInitialReflow,
|
||||||
|
nsReflowStatus& aReflowStatus);
|
||||||
PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats);
|
PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats);
|
||||||
|
PRBool FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||||
void FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
PRBool* aIsLeftFloat,
|
||||||
PRBool* aIsLeftFloat,
|
nsReflowStatus& aReflowStatus);
|
||||||
nsReflowStatus& aReflowStatus);
|
|
||||||
|
|
||||||
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheList& aFloats);
|
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheList& aFloats);
|
||||||
|
|
||||||
// Returns the first coordinate >= aY that clears the
|
// Returns the first coordinate >= aY that clears the
|
||||||
|
@ -162,6 +163,10 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
|
// Placeholders for continuation out-of-flow frames that need to
|
||||||
|
// move to our next in flow are placed here during reflow.
|
||||||
|
nsFrameList mOverflowPlaceholders;
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
|
|
@ -69,6 +69,10 @@ public:
|
||||||
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
|
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
|
||||||
nsIFrame* aOldFrame);
|
nsIFrame* aOldFrame);
|
||||||
|
|
||||||
|
NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint,
|
||||||
|
nsFramePaintLayer aWhichLayer,
|
||||||
|
nsIFrame** aFrame);
|
||||||
|
|
||||||
virtual nsIFrame* GetContentInsertionFrame() {
|
virtual nsIFrame* GetContentInsertionFrame() {
|
||||||
return GetFirstChild(nsnull)->GetContentInsertionFrame();
|
return GetFirstChild(nsnull)->GetContentInsertionFrame();
|
||||||
}
|
}
|
||||||
|
@ -163,6 +167,16 @@ nsColumnSetFrame::GetType() const
|
||||||
return nsLayoutAtoms::columnSetFrame;
|
return nsLayoutAtoms::columnSetFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsColumnSetFrame::GetFrameForPoint(const nsPoint& aPoint,
|
||||||
|
nsFramePaintLayer aWhichLayer,
|
||||||
|
nsIFrame** aFrame)
|
||||||
|
{
|
||||||
|
// This frame counts as part of the background.
|
||||||
|
return GetFrameForPointUsing(aPoint, nsnull, aWhichLayer,
|
||||||
|
(aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND), aFrame);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsColumnSetFrame::SetInitialChildList(nsPresContext* aPresContext,
|
nsColumnSetFrame::SetInitialChildList(nsPresContext* aPresContext,
|
||||||
nsIAtom* aListName,
|
nsIAtom* aListName,
|
||||||
|
@ -260,6 +274,9 @@ nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState)
|
||||||
// colWidth*nominalColumnCount is nearly availContentWidth
|
// colWidth*nominalColumnCount is nearly availContentWidth
|
||||||
// make sure to round down
|
// make sure to round down
|
||||||
numColumns = (availContentWidth + colGap)/(colGap + colWidth);
|
numColumns = (availContentWidth + colGap)/(colGap + colWidth);
|
||||||
|
if (numColumns <= 0) {
|
||||||
|
numColumns = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute extra space and divide it among the columns
|
// Compute extra space and divide it among the columns
|
||||||
|
|
|
@ -638,6 +638,20 @@ nsFrame::Destroy(nsPresContext* aPresContext)
|
||||||
|
|
||||||
nsIPresShell *shell = aPresContext->GetPresShell();
|
nsIPresShell *shell = aPresContext->GetPresShell();
|
||||||
if (shell) {
|
if (shell) {
|
||||||
|
if (mState & NS_FRAME_OUT_OF_FLOW) {
|
||||||
|
nsPlaceholderFrame* placeholder
|
||||||
|
= shell->FrameManager()->GetPlaceholderFrameFor(this);
|
||||||
|
if (placeholder) {
|
||||||
|
NS_WARNING("Deleting out of flow without tearing down placeholder relationship");
|
||||||
|
if (placeholder->GetOutOfFlowFrame()) {
|
||||||
|
NS_ASSERTION(placeholder->GetOutOfFlowFrame() == this,
|
||||||
|
"no-one told the frame manager about this");
|
||||||
|
shell->FrameManager()->UnregisterPlaceholderFrame(placeholder);
|
||||||
|
placeholder->SetOutOfFlowFrame(nsnull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the frame contains generated context, remove it from
|
// If the frame contains generated context, remove it from
|
||||||
// the quoteList.
|
// the quoteList.
|
||||||
if (mState & NS_FRAME_GENERATED_CONTENT) {
|
if (mState & NS_FRAME_GENERATED_CONTENT) {
|
||||||
|
@ -2724,6 +2738,14 @@ nsFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const
|
||||||
if (0 != mState) {
|
if (0 != mState) {
|
||||||
fprintf(out, " [state=%08x]", mState);
|
fprintf(out, " [state=%08x]", mState);
|
||||||
}
|
}
|
||||||
|
nsIFrame* prevInFlow = GetPrevInFlow();
|
||||||
|
nsIFrame* nextInFlow = GetNextInFlow();
|
||||||
|
if (nsnull != prevInFlow) {
|
||||||
|
fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, prevInFlow));
|
||||||
|
}
|
||||||
|
if (nsnull != nextInFlow) {
|
||||||
|
fprintf(out, " next-in-flow=%p", NS_STATIC_CAST(void*, nextInFlow));
|
||||||
|
}
|
||||||
fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent));
|
fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent));
|
||||||
nsFrame* f = NS_CONST_CAST(nsFrame*, this);
|
nsFrame* f = NS_CONST_CAST(nsFrame*, this);
|
||||||
nsRect* overflowArea = f->GetOverflowAreaProperty(PR_FALSE);
|
nsRect* overflowArea = f->GetOverflowAreaProperty(PR_FALSE);
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
#include "nsIFrameDebug.h"
|
#include "nsIFrameDebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
#include "nsLayoutUtils.h"
|
||||||
|
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -160,6 +162,7 @@ nsFrameList::AppendFrame(nsIFrame* aParent, nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(nsnull != aFrame, "null ptr");
|
NS_PRECONDITION(nsnull != aFrame, "null ptr");
|
||||||
if (nsnull != aFrame) {
|
if (nsnull != aFrame) {
|
||||||
|
NS_PRECONDITION(!aFrame->GetNextSibling(), "Can only append one frame here");
|
||||||
nsIFrame* lastChild = LastChild();
|
nsIFrame* lastChild = LastChild();
|
||||||
if (nsnull == lastChild) {
|
if (nsnull == lastChild) {
|
||||||
mFirstChild = aFrame;
|
mFirstChild = aFrame;
|
||||||
|
@ -180,11 +183,11 @@ PRBool
|
||||||
nsFrameList::RemoveFrame(nsIFrame* aFrame, nsIFrame* aPrevSiblingHint)
|
nsFrameList::RemoveFrame(nsIFrame* aFrame, nsIFrame* aPrevSiblingHint)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(nsnull != aFrame, "null ptr");
|
NS_PRECONDITION(nsnull != aFrame, "null ptr");
|
||||||
if (nsnull != aFrame) {
|
if (aFrame) {
|
||||||
nsIFrame* nextFrame = aFrame->GetNextSibling();
|
nsIFrame* nextFrame = aFrame->GetNextSibling();
|
||||||
aFrame->SetNextSibling(nsnull);
|
|
||||||
if (aFrame == mFirstChild) {
|
if (aFrame == mFirstChild) {
|
||||||
mFirstChild = nextFrame;
|
mFirstChild = nextFrame;
|
||||||
|
aFrame->SetNextSibling(nsnull);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -194,6 +197,7 @@ nsFrameList::RemoveFrame(nsIFrame* aFrame, nsIFrame* aPrevSiblingHint)
|
||||||
}
|
}
|
||||||
if (prevSibling) {
|
if (prevSibling) {
|
||||||
prevSibling->SetNextSibling(nextFrame);
|
prevSibling->SetNextSibling(nextFrame);
|
||||||
|
aFrame->SetNextSibling(nsnull);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,6 +445,58 @@ nsFrameList::GetLength() const
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int PR_CALLBACK CompareByContentOrder(const void* aF1, const void* aF2,
|
||||||
|
void* aDummy)
|
||||||
|
{
|
||||||
|
const nsIFrame* f1 = NS_STATIC_CAST(const nsIFrame*, aF1);
|
||||||
|
const nsIFrame* f2 = NS_STATIC_CAST(const nsIFrame*, aF2);
|
||||||
|
if (f1->GetContent() != f2->GetContent()) {
|
||||||
|
return nsLayoutUtils::CompareTreePosition(f1->GetContent(), f2->GetContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f1 == f2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsIFrame* f;
|
||||||
|
for (f = f2; f; f = f->GetPrevInFlow()) {
|
||||||
|
if (f == f1) {
|
||||||
|
// f1 comes before f2 in the flow
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (f = f1; f; f = f->GetPrevInFlow()) {
|
||||||
|
if (f == f2) {
|
||||||
|
// f1 comes after f2 in the flow
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(PR_FALSE, "Frames for same content but not in relative flow order");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsFrameList::SortByContentOrder()
|
||||||
|
{
|
||||||
|
if (!mFirstChild)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsAutoVoidArray array;
|
||||||
|
nsIFrame* f;
|
||||||
|
for (f = mFirstChild; f; f = f->GetNextSibling()) {
|
||||||
|
array.AppendElement(f);
|
||||||
|
}
|
||||||
|
array.Sort(CompareByContentOrder, nsnull);
|
||||||
|
f = mFirstChild = NS_STATIC_CAST(nsIFrame*, array.FastElementAt(0));
|
||||||
|
for (PRInt32 i = 1; i < array.Count(); ++i) {
|
||||||
|
nsIFrame* ff = NS_STATIC_CAST(nsIFrame*, array.FastElementAt(i));
|
||||||
|
f->SetNextSibling(ff);
|
||||||
|
f = ff;
|
||||||
|
}
|
||||||
|
f->SetNextSibling(nsnull);
|
||||||
|
}
|
||||||
|
|
||||||
nsIFrame*
|
nsIFrame*
|
||||||
nsFrameList::GetPrevSiblingFor(nsIFrame* aFrame) const
|
nsFrameList::GetPrevSiblingFor(nsIFrame* aFrame) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,6 +115,14 @@ public:
|
||||||
|
|
||||||
PRBool Split(nsIFrame* aAfterFrame, nsIFrame** aNextFrameResult);
|
PRBool Split(nsIFrame* aAfterFrame, nsIFrame** aNextFrameResult);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the frames according to content order so that the first
|
||||||
|
* frame in the list is the first in content order. Frames for
|
||||||
|
* the same content will be ordered so that a prev in flow
|
||||||
|
* comes before its next in flow.
|
||||||
|
*/
|
||||||
|
void SortByContentOrder();
|
||||||
|
|
||||||
nsIFrame* PullFrame(nsIFrame* aParent,
|
nsIFrame* PullFrame(nsIFrame* aParent,
|
||||||
nsIFrame* aLastChild,
|
nsIFrame* aLastChild,
|
||||||
nsFrameList& aFromList);
|
nsFrameList& aFromList);
|
||||||
|
|
|
@ -147,14 +147,22 @@ struct nsHTMLReflowState {
|
||||||
// reason == eReflowReason_Incremental.
|
// reason == eReflowReason_Incremental.
|
||||||
nsReflowPath *path;
|
nsReflowPath *path;
|
||||||
|
|
||||||
// the available space in which to reflow the frame. The space represents the
|
// the available width in which to reflow the frame. The space
|
||||||
// amount of room for the frame's border, padding, and content area (not the
|
// represents the amount of room for the frame's border, padding,
|
||||||
// margin area. The parent frame deals with the child frame's margins). The
|
// and content area (not the margin area. The parent frame deals
|
||||||
// frame size you choose should fit within the available space.
|
// with the child frame's margins). The frame size you choose should
|
||||||
// A value of NS_UNCONSTRAINEDSIZE for the available height means you can
|
// fit within the available width.
|
||||||
// choose whatever size you want. In galley mode the available height is always
|
nscoord availableWidth;
|
||||||
// NS_UNCONSTRAINEDSIZE, and only page mode involves a constrained height
|
|
||||||
nscoord availableWidth, availableHeight;
|
// A value of NS_UNCONSTRAINEDSIZE for the available height means
|
||||||
|
// you can choose whatever size you want. In galley mode the
|
||||||
|
// available height is always NS_UNCONSTRAINEDSIZE, and only page
|
||||||
|
// mode involves a constrained height. The element's the top border
|
||||||
|
// and padding, and content, must fit. If the element is complete
|
||||||
|
// after reflow then its bottom border, padding and margin (and
|
||||||
|
// similar for its complete ancestors) will need to fit in this
|
||||||
|
// height.
|
||||||
|
nscoord availableHeight;
|
||||||
|
|
||||||
// rendering context to use for measurement
|
// rendering context to use for measurement
|
||||||
nsIRenderingContext* rendContext;
|
nsIRenderingContext* rendContext;
|
||||||
|
|
|
@ -772,7 +772,7 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext,
|
||||||
else if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
else if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||||
if (nsLayoutAtoms::placeholderFrame == aFrame->GetType()) {
|
if (nsLayoutAtoms::placeholderFrame == aFrame->GetType()) {
|
||||||
nsBlockReflowState* blockRS = lineLayout->mBlockRS;
|
nsBlockReflowState* blockRS = lineLayout->mBlockRS;
|
||||||
blockRS->mBlock->SplitPlaceholder(*aPresContext, *aFrame);
|
blockRS->mBlock->SplitPlaceholder(*blockRS, aFrame);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nsIFrame* newFrame;
|
nsIFrame* newFrame;
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "nsBlockFrame.h"
|
#include "nsBlockFrame.h"
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
#include "nsLayoutAtoms.h"
|
#include "nsLayoutAtoms.h"
|
||||||
|
#include "nsFrameManager.h"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static PRInt32 ctorCount;
|
static PRInt32 ctorCount;
|
||||||
|
@ -62,6 +63,12 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock)
|
||||||
MOZ_COUNT_CTOR(nsLineBox);
|
MOZ_COUNT_CTOR(nsLineBox);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
++ctorCount;
|
++ctorCount;
|
||||||
|
NS_ASSERTION(!aIsBlock || aCount == 1, "Blocks must have exactly one child");
|
||||||
|
nsIFrame* f = aFrame;
|
||||||
|
for (PRInt32 n = aCount; n > 0; f = f->GetNextSibling(), --n) {
|
||||||
|
NS_ASSERTION(aIsBlock == f->GetStyleDisplay()->IsBlockLevel(),
|
||||||
|
"wrong kind of child frame");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mAllFlags = 0;
|
mAllFlags = 0;
|
||||||
|
@ -464,7 +471,6 @@ nsLineBox::RemoveFloat(nsIFrame* aFrame)
|
||||||
if (fc) {
|
if (fc) {
|
||||||
// Note: the placeholder is part of the line's child list
|
// Note: the placeholder is part of the line's child list
|
||||||
// and will be removed later.
|
// and will be removed later.
|
||||||
fc->mPlaceholder->SetOutOfFlowFrame(nsnull);
|
|
||||||
mInlineData->mFloats.Remove(fc);
|
mInlineData->mFloats.Remove(fc);
|
||||||
MaybeFreeData();
|
MaybeFreeData();
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
|
|
|
@ -1012,11 +1012,16 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
|
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
|
||||||
if (outOfFlowFrame) {
|
if (outOfFlowFrame) {
|
||||||
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
|
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
|
||||||
|
PRBool didPlace;
|
||||||
if (eReflowReason_Incremental == reason) {
|
if (eReflowReason_Incremental == reason) {
|
||||||
InitFloat(placeholder, aReflowStatus);
|
didPlace = InitFloat(placeholder, aReflowStatus);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AddFloat(placeholder, aReflowStatus);
|
didPlace = AddFloat(placeholder, aReflowStatus);
|
||||||
|
}
|
||||||
|
printf("*** Reflowed float, didPlace=%d, status=%d\n", aReflowStatus);
|
||||||
|
if (!didPlace) {
|
||||||
|
aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
||||||
}
|
}
|
||||||
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
|
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
|
||||||
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
|
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
|
||||||
|
|
|
@ -252,12 +252,12 @@ public:
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Inform the line-layout about the presence of a floating frame
|
// Inform the line-layout about the presence of a floating frame
|
||||||
// XXX get rid of this: use get-frame-type?
|
// XXX get rid of this: use get-frame-type?
|
||||||
void InitFloat(nsPlaceholderFrame* aFrame, nsReflowStatus& aReflowStatus) {
|
PRBool InitFloat(nsPlaceholderFrame* aFrame, nsReflowStatus& aReflowStatus) {
|
||||||
mBlockRS->InitFloat(*this, aFrame, aReflowStatus);
|
return mBlockRS->InitFloat(*this, aFrame, aReflowStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFloat(nsPlaceholderFrame* aFrame, nsReflowStatus& aReflowStatus) {
|
PRBool AddFloat(nsPlaceholderFrame* aFrame, nsReflowStatus& aReflowStatus) {
|
||||||
mBlockRS->AddFloat(*this, aFrame, PR_FALSE, aReflowStatus);
|
return mBlockRS->AddFloat(*this, aFrame, PR_FALSE, aReflowStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
#include "nsIRenderingContext.h"
|
#include "nsIRenderingContext.h"
|
||||||
#include "nsLayoutAtoms.h"
|
#include "nsLayoutAtoms.h"
|
||||||
|
#include "nsFrameManager.h"
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
||||||
|
@ -86,6 +87,18 @@ nsPlaceholderFrame::Reflow(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsPlaceholderFrame::Destroy(nsPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIPresShell* shell = aPresContext->GetPresShell();
|
||||||
|
if (shell && mOutOfFlowFrame) {
|
||||||
|
NS_ASSERTION(!shell->FrameManager()->GetPlaceholderFrameFor(mOutOfFlowFrame),
|
||||||
|
"Placeholder relationship should have been torn down");
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsSplittableFrame::Destroy(aPresContext);
|
||||||
|
}
|
||||||
|
|
||||||
nsIAtom*
|
nsIAtom*
|
||||||
nsPlaceholderFrame::GetType() const
|
nsPlaceholderFrame::GetType() const
|
||||||
{
|
{
|
||||||
|
@ -136,6 +149,14 @@ nsPlaceholderFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent
|
||||||
if (0 != mState) {
|
if (0 != mState) {
|
||||||
fprintf(out, " [state=%08x]", mState);
|
fprintf(out, " [state=%08x]", mState);
|
||||||
}
|
}
|
||||||
|
nsIFrame* prevInFlow = GetPrevInFlow();
|
||||||
|
nsIFrame* nextInFlow = GetNextInFlow();
|
||||||
|
if (nsnull != prevInFlow) {
|
||||||
|
fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, prevInFlow));
|
||||||
|
}
|
||||||
|
if (nsnull != nextInFlow) {
|
||||||
|
fprintf(out, " next-in-flow=%p", NS_STATIC_CAST(void*, nextInFlow));
|
||||||
|
}
|
||||||
if (mOutOfFlowFrame) {
|
if (mOutOfFlowFrame) {
|
||||||
fprintf(out, " outOfFlowFrame=");
|
fprintf(out, " outOfFlowFrame=");
|
||||||
nsFrame::ListTag(out, mOutOfFlowFrame);
|
nsFrame::ListTag(out, mOutOfFlowFrame);
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
const nsHTMLReflowState& aReflowState,
|
const nsHTMLReflowState& aReflowState,
|
||||||
nsReflowStatus& aStatus);
|
nsReflowStatus& aStatus);
|
||||||
|
|
||||||
|
NS_IMETHOD Destroy(nsPresContext* aPresContext);
|
||||||
|
|
||||||
// nsIFrame overrides
|
// nsIFrame overrides
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
NS_IMETHOD Paint(nsPresContext* aPresContext,
|
NS_IMETHOD Paint(nsPresContext* aPresContext,
|
||||||
|
|
|
@ -359,11 +359,13 @@ nsSpaceManager::GetBandData(nscoord aYOffset,
|
||||||
// If there are no unavailable rects or the offset is below the bottommost
|
// If there are no unavailable rects or the offset is below the bottommost
|
||||||
// band, then all the space is available
|
// band, then all the space is available
|
||||||
nscoord yMost;
|
nscoord yMost;
|
||||||
|
nscoord maxHeight = aMaxSize.height == NS_UNCONSTRAINEDSIZE ? NS_UNCONSTRAINEDSIZE
|
||||||
|
: PR_MAX(0, aMaxSize.height - aYOffset);
|
||||||
|
|
||||||
if (!YMost(yMost) || (y >= yMost)) {
|
if (!YMost(yMost) || (y >= yMost)) {
|
||||||
// All the requested space is available
|
// All the requested space is available
|
||||||
aBandData.mCount = 1;
|
aBandData.mCount = 1;
|
||||||
aBandData.mTrapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, aMaxSize.height);
|
aBandData.mTrapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, maxHeight);
|
||||||
aBandData.mTrapezoids[0].mState = nsBandTrapezoid::Available;
|
aBandData.mTrapezoids[0].mState = nsBandTrapezoid::Available;
|
||||||
aBandData.mTrapezoids[0].mFrame = nsnull;
|
aBandData.mTrapezoids[0].mFrame = nsnull;
|
||||||
} else {
|
} else {
|
||||||
|
@ -378,14 +380,14 @@ nsSpaceManager::GetBandData(nscoord aYOffset,
|
||||||
// the top of the band is available
|
// the top of the band is available
|
||||||
aBandData.mCount = 1;
|
aBandData.mCount = 1;
|
||||||
aBandData.mTrapezoids[0] =
|
aBandData.mTrapezoids[0] =
|
||||||
nsRect(0, aYOffset, aMaxSize.width, PR_MIN(band->mTop - y, aMaxSize.height));
|
nsRect(0, aYOffset, aMaxSize.width, PR_MIN(band->mTop - y, maxHeight));
|
||||||
aBandData.mTrapezoids[0].mState = nsBandTrapezoid::Available;
|
aBandData.mTrapezoids[0].mState = nsBandTrapezoid::Available;
|
||||||
aBandData.mTrapezoids[0].mFrame = nsnull;
|
aBandData.mTrapezoids[0].mFrame = nsnull;
|
||||||
break;
|
break;
|
||||||
} else if (y < band->mBottom) {
|
} else if (y < band->mBottom) {
|
||||||
// The band contains the y-offset. Return a list of available and
|
// The band contains the y-offset. Return a list of available and
|
||||||
// unavailable rects within the band
|
// unavailable rects within the band
|
||||||
return GetBandAvailableSpace(band, y, aMaxSize, aBandData);
|
return GetBandAvailableSpace(band, y, nsSize(aMaxSize.width, maxHeight), aBandData);
|
||||||
} else {
|
} else {
|
||||||
// Skip to the next band
|
// Skip to the next band
|
||||||
band = GetNextBand(band);
|
band = GetNextBand(band);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче