Moved vertical margin application into here; implement top-margin collapsing logic
git-svn-id: svn://10.0.0.236/trunk@25293 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -24,15 +24,16 @@
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#undef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
#undef NOISY_MAX_ELEMENT_SIZE
|
||||
#undef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
#undef NOISY_VERTICAL_MARGINS
|
||||
#else
|
||||
#undef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
#undef NOISY_MAX_ELEMENT_SIZE
|
||||
#undef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
#undef NOISY_VERTICAL_MARGINS
|
||||
#endif
|
||||
|
||||
nsBlockReflowContext::nsBlockReflowContext(nsIPresContext& aPresContext,
|
||||
@@ -44,15 +45,67 @@ nsBlockReflowContext::nsBlockReflowContext(nsIPresContext& aPresContext,
|
||||
{
|
||||
mCompactMarginWidth = 0;
|
||||
mStyleSpacing = nsnull;
|
||||
#ifdef DEBUG
|
||||
mIndent = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsBlockReflowContext::ComputeCollapsedTopMargin(nsHTMLReflowState& aRS)
|
||||
{
|
||||
#ifdef NOISY_VERTICAL_MARGINS
|
||||
mIndent++;
|
||||
#endif
|
||||
|
||||
// Get aFrame's top margin
|
||||
nscoord topMargin = aRS.computedMargin.top;
|
||||
|
||||
// Calculate aFrame's generational top-margin from its child
|
||||
// blocks. Note that if aFrame has a non-zero top-border or
|
||||
// top-padding then this step is skipped because it will be a margin
|
||||
// root.
|
||||
nscoord generationalTopMargin = 0;
|
||||
if (0 == aRS.mComputedBorderPadding.top) {
|
||||
nsBlockFrame* bf;
|
||||
if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf))) {
|
||||
// Ask the block frame for the top block child that we should
|
||||
// try to collapse the top margin with.
|
||||
nsIFrame* childFrame = bf->GetTopBlockChild();
|
||||
if (nsnull != childFrame) {
|
||||
|
||||
// Here is where we recurse. 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.
|
||||
nsSize availSpace(aRS.computedWidth, aRS.computedHeight);
|
||||
nsHTMLReflowState reflowState(mPresContext, aRS, childFrame,
|
||||
availSpace);
|
||||
generationalTopMargin = ComputeCollapsedTopMargin(reflowState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now compute the collapsed top-margin value. At this point we have
|
||||
// the child frames effective top margin value.
|
||||
nscoord collapsedTopMargin = MaxMargin(topMargin, generationalTopMargin);
|
||||
|
||||
#ifdef NOISY_VERTICAL_MARGINS
|
||||
nsFrame::IndentBy(stdout, mIndent);
|
||||
nsFrame::ListTag(stdout, aRS.frame);
|
||||
printf(": topMargin=%d generationalTopMargin=%d => %d\n",
|
||||
topMargin, generationalTopMargin, collapsedTopMargin);
|
||||
mIndent--;
|
||||
#endif
|
||||
|
||||
return collapsedTopMargin;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
const nsRect& aSpace,
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
PRBool aIsAdjacentWithTop,
|
||||
nsMargin& aComputedOffsets,
|
||||
nsReflowStatus& aFrameReflowStatus)
|
||||
@@ -61,27 +114,6 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
mFrame = aFrame;
|
||||
mSpace = aSpace;
|
||||
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
#ifdef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
PRIntn pass = 0;
|
||||
#endif
|
||||
mSpeculativeTopMargin = 0;
|
||||
if (aApplyTopMargin) {
|
||||
// Compute a "speculative" collapsed top-margin value. Its
|
||||
// speculative because we don't yet have the
|
||||
// carried-out-top-margin value so the final collapsed value isn't
|
||||
// knowable yet. We want to pre-apply the collapsed top-margin
|
||||
// value so that when a block is flowing around floaters that we
|
||||
// don't have to reflow it twice (we can't just slide it down when
|
||||
// its flowing around a floater after discovering the final top
|
||||
// margin value).
|
||||
mSpeculativeTopMargin = MaxMargin(mMargin.top, aPrevBottomMargin);
|
||||
}
|
||||
again:
|
||||
#else
|
||||
mSpeculativeTopMargin = 0;
|
||||
#endif
|
||||
|
||||
// Get reflow reason set correctly. It's possible that a child was
|
||||
// created and then it was decided that it could not be reflowed
|
||||
// (for example, a block frame that isn't at the start of a
|
||||
@@ -100,6 +132,7 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
// Setup reflow state for reflowing the frame
|
||||
// XXX subtract out vertical margin?
|
||||
nsSize availSpace(aSpace.width, aSpace.height);
|
||||
nsHTMLReflowState reflowState(mPresContext, mOuterReflowState, aFrame,
|
||||
availSpace, reason);
|
||||
@@ -111,13 +144,38 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
}
|
||||
mIsTable = NS_STYLE_DISPLAY_TABLE == reflowState.mStyleDisplay->mDisplay;
|
||||
|
||||
nscoord topMargin = 0;
|
||||
if (aApplyTopMargin) {
|
||||
// Compute the childs collapsed top margin (its margin collpased
|
||||
// with its first childs top-margin -- recursively).
|
||||
#ifdef NOISY_VERTICAL_MARGINS
|
||||
nsFrame::ListTag(stdout, mOuterReflowState.frame);
|
||||
printf(": prevBottomMargin=%d\n", aPrevBottomMargin);
|
||||
#endif
|
||||
topMargin = ComputeCollapsedTopMargin(reflowState);
|
||||
|
||||
// Collapse that value with the previous bottom margin to perform
|
||||
// the sibling to sibling collaspe.
|
||||
topMargin = MaxMargin(topMargin, aPrevBottomMargin);
|
||||
|
||||
// Adjust the available height if its constrained so that the
|
||||
// child frame doesn't think it can reflow into its margin area.
|
||||
// XXX write me
|
||||
#if 0
|
||||
availSpace.y += topMargin;
|
||||
if (NS_UNCONSTRAINEDSIZE != availHeight) {
|
||||
availSpace.height -= topMargin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Compute x/y coordinate where reflow will begin. Use the rules
|
||||
// from 10.3.3 to determine what to apply. At this point in the
|
||||
// reflow auto left/right margins will have a zero value.
|
||||
mMargin = reflowState.computedMargin;
|
||||
mStyleSpacing = reflowState.mStyleSpacing;
|
||||
nscoord x = aSpace.x + mMargin.left;
|
||||
nscoord y = aSpace.y + mSpeculativeTopMargin;
|
||||
nscoord y = aSpace.y + topMargin;
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
@@ -244,31 +302,6 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
parent->DeleteChildsNextInFlow(mPresContext, aFrame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
if (aApplyTopMargin) {
|
||||
// Compute final collapsed margin value
|
||||
CollapseMargins(mMargin, mMetrics.mCarriedOutTopMargin,
|
||||
mMetrics.mCarriedOutBottomMargin,
|
||||
mMetrics.height, aPrevBottomMargin,
|
||||
mTopMargin, mBottomMargin);
|
||||
|
||||
if (mSpeculativeTopMargin != mTopMargin) {
|
||||
// We lost our speculative gamble. Use new computed margin
|
||||
// value as the speculative value and try the reflow again.
|
||||
#ifdef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
nsFrame::ListTag(stdout, mOuterReflowState.frame);
|
||||
printf(": reflowing again: ");
|
||||
nsFrame::ListTag(stdout, aFrame);
|
||||
printf(" guess=%d actual=%d [pass %d]\n",
|
||||
mSpeculativeTopMargin, mTopMargin, pass);
|
||||
pass++;
|
||||
#endif
|
||||
mSpeculativeTopMargin = mTopMargin;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -328,21 +361,15 @@ nsBlockReflowContext::CollapseMargins(const nsMargin& aMargin,
|
||||
*/
|
||||
PRBool
|
||||
nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
const nsMargin& aComputedOffsets,
|
||||
nscoord* aBottomMarginResult,
|
||||
nsRect& aInFlowBounds,
|
||||
nsRect& aCombinedRect)
|
||||
{
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
// Compute final collapsed margin value
|
||||
CollapseMargins(mMargin, mMetrics.mCarriedOutTopMargin,
|
||||
mMetrics.mCarriedOutBottomMargin,
|
||||
mMetrics.height, aPrevBottomMargin,
|
||||
mTopMargin, mBottomMargin);
|
||||
#endif
|
||||
// Compute collapsed bottom margin value
|
||||
nscoord collapsedBottomMargin = MaxMargin(mMetrics.mCarriedOutBottomMargin,
|
||||
mMargin.bottom);
|
||||
*aBottomMarginResult = collapsedBottomMargin;
|
||||
|
||||
// See if the block will fit in the available space
|
||||
PRBool fits = PR_TRUE;
|
||||
@@ -354,20 +381,13 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
|
||||
nsRect r(x, y, 0, 0);
|
||||
mFrame->SetRect(r);
|
||||
aInFlowBounds = r;
|
||||
// Retain combined area information in case we contain a floater
|
||||
// and nothing else.
|
||||
aCombinedRect = mMetrics.mCombinedArea;
|
||||
aCombinedRect.x += x;
|
||||
aCombinedRect.y += y;
|
||||
mTopMargin = 0;
|
||||
mBottomMargin = 0;
|
||||
}
|
||||
else {
|
||||
// Apply top margin unless it's going to be carried out.
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
if (aApplyTopMargin) {
|
||||
y += mTopMargin;
|
||||
}
|
||||
#endif
|
||||
|
||||
// See if the frame fit. If its the first frame then it always
|
||||
// fits.
|
||||
if (aForceFit || (y + mMetrics.height <= mSpace.YMost())) {
|
||||
@@ -501,9 +521,11 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
|
||||
m->width += mMargin.right;
|
||||
}
|
||||
|
||||
#if XXX_fix_me
|
||||
// Margin height should affect the max-element height (since
|
||||
// auto top/bottom margins are always zero)
|
||||
m->height += mTopMargin + mBottomMargin;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -28,8 +28,6 @@ class nsLineLayout;
|
||||
struct nsStylePosition;
|
||||
struct nsStyleSpacing;
|
||||
|
||||
#undef SPECULATIVE_TOP_MARGIN
|
||||
|
||||
/**
|
||||
* An encapsulation of the state and algorithm for reflowing block frames.
|
||||
*/
|
||||
@@ -54,34 +52,29 @@ public:
|
||||
|
||||
nsresult ReflowBlock(nsIFrame* aFrame,
|
||||
const nsRect& aSpace,
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
PRBool aIsAdjacentWithTop,
|
||||
nsMargin& aComputedOffsets,
|
||||
nsReflowStatus& aReflowStatus);
|
||||
|
||||
PRBool PlaceBlock(PRBool aForceFit,
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
const nsMargin& aComputedOffsets,
|
||||
nscoord* aBottomMarginResult,
|
||||
nsRect& aInFlowBounds,
|
||||
nsRect& aCombinedRect);
|
||||
|
||||
nscoord GetCollapsedTopMargin() const {
|
||||
return mTopMargin;
|
||||
}
|
||||
//XXX nscoord GetCollapsedTopMargin() const {
|
||||
//XXX return mTopMargin;
|
||||
//XXX }
|
||||
|
||||
nscoord GetCollapsedBottomMargin() const {
|
||||
return mBottomMargin;
|
||||
}
|
||||
//XXX nscoord GetCollapsedBottomMargin() const {
|
||||
//XXX return mBottomMargin;
|
||||
//XXX }
|
||||
|
||||
nscoord GetCarriedOutTopMargin() const {
|
||||
return mMetrics.mCarriedOutTopMargin;
|
||||
}
|
||||
//XXX nscoord GetCarriedOutTopMargin() const {
|
||||
//XXX return mMetrics.mCarriedOutTopMargin;
|
||||
//XXX }
|
||||
|
||||
nscoord GetCarriedOutBottomMargin() const {
|
||||
return mMetrics.mCarriedOutBottomMargin;
|
||||
@@ -138,11 +131,17 @@ protected:
|
||||
nsMargin mMargin;
|
||||
nscoord mX, mY;
|
||||
nsHTMLReflowMetrics mMetrics;
|
||||
nscoord mSpeculativeTopMargin;
|
||||
nscoord mTopMargin;
|
||||
nscoord mBottomMargin;
|
||||
//XXX nscoord mSpeculativeTopMargin;
|
||||
//XXX nscoord mTopMargin;
|
||||
//XXX nscoord mBottomMargin;
|
||||
nsSize mMaxElementSize;
|
||||
PRBool mIsTable;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRInt32 mIndent;
|
||||
#endif
|
||||
|
||||
nscoord ComputeCollapsedTopMargin(nsHTMLReflowState& aRS);
|
||||
};
|
||||
|
||||
#endif /* nsBlockReflowContext_h___ */
|
||||
|
||||
@@ -24,15 +24,16 @@
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#undef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
#undef NOISY_MAX_ELEMENT_SIZE
|
||||
#undef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
#undef NOISY_VERTICAL_MARGINS
|
||||
#else
|
||||
#undef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
#undef NOISY_MAX_ELEMENT_SIZE
|
||||
#undef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
#undef NOISY_VERTICAL_MARGINS
|
||||
#endif
|
||||
|
||||
nsBlockReflowContext::nsBlockReflowContext(nsIPresContext& aPresContext,
|
||||
@@ -44,15 +45,67 @@ nsBlockReflowContext::nsBlockReflowContext(nsIPresContext& aPresContext,
|
||||
{
|
||||
mCompactMarginWidth = 0;
|
||||
mStyleSpacing = nsnull;
|
||||
#ifdef DEBUG
|
||||
mIndent = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsBlockReflowContext::ComputeCollapsedTopMargin(nsHTMLReflowState& aRS)
|
||||
{
|
||||
#ifdef NOISY_VERTICAL_MARGINS
|
||||
mIndent++;
|
||||
#endif
|
||||
|
||||
// Get aFrame's top margin
|
||||
nscoord topMargin = aRS.computedMargin.top;
|
||||
|
||||
// Calculate aFrame's generational top-margin from its child
|
||||
// blocks. Note that if aFrame has a non-zero top-border or
|
||||
// top-padding then this step is skipped because it will be a margin
|
||||
// root.
|
||||
nscoord generationalTopMargin = 0;
|
||||
if (0 == aRS.mComputedBorderPadding.top) {
|
||||
nsBlockFrame* bf;
|
||||
if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf))) {
|
||||
// Ask the block frame for the top block child that we should
|
||||
// try to collapse the top margin with.
|
||||
nsIFrame* childFrame = bf->GetTopBlockChild();
|
||||
if (nsnull != childFrame) {
|
||||
|
||||
// Here is where we recurse. 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.
|
||||
nsSize availSpace(aRS.computedWidth, aRS.computedHeight);
|
||||
nsHTMLReflowState reflowState(mPresContext, aRS, childFrame,
|
||||
availSpace);
|
||||
generationalTopMargin = ComputeCollapsedTopMargin(reflowState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now compute the collapsed top-margin value. At this point we have
|
||||
// the child frames effective top margin value.
|
||||
nscoord collapsedTopMargin = MaxMargin(topMargin, generationalTopMargin);
|
||||
|
||||
#ifdef NOISY_VERTICAL_MARGINS
|
||||
nsFrame::IndentBy(stdout, mIndent);
|
||||
nsFrame::ListTag(stdout, aRS.frame);
|
||||
printf(": topMargin=%d generationalTopMargin=%d => %d\n",
|
||||
topMargin, generationalTopMargin, collapsedTopMargin);
|
||||
mIndent--;
|
||||
#endif
|
||||
|
||||
return collapsedTopMargin;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
const nsRect& aSpace,
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
PRBool aIsAdjacentWithTop,
|
||||
nsMargin& aComputedOffsets,
|
||||
nsReflowStatus& aFrameReflowStatus)
|
||||
@@ -61,27 +114,6 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
mFrame = aFrame;
|
||||
mSpace = aSpace;
|
||||
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
#ifdef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
PRIntn pass = 0;
|
||||
#endif
|
||||
mSpeculativeTopMargin = 0;
|
||||
if (aApplyTopMargin) {
|
||||
// Compute a "speculative" collapsed top-margin value. Its
|
||||
// speculative because we don't yet have the
|
||||
// carried-out-top-margin value so the final collapsed value isn't
|
||||
// knowable yet. We want to pre-apply the collapsed top-margin
|
||||
// value so that when a block is flowing around floaters that we
|
||||
// don't have to reflow it twice (we can't just slide it down when
|
||||
// its flowing around a floater after discovering the final top
|
||||
// margin value).
|
||||
mSpeculativeTopMargin = MaxMargin(mMargin.top, aPrevBottomMargin);
|
||||
}
|
||||
again:
|
||||
#else
|
||||
mSpeculativeTopMargin = 0;
|
||||
#endif
|
||||
|
||||
// Get reflow reason set correctly. It's possible that a child was
|
||||
// created and then it was decided that it could not be reflowed
|
||||
// (for example, a block frame that isn't at the start of a
|
||||
@@ -100,6 +132,7 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
// Setup reflow state for reflowing the frame
|
||||
// XXX subtract out vertical margin?
|
||||
nsSize availSpace(aSpace.width, aSpace.height);
|
||||
nsHTMLReflowState reflowState(mPresContext, mOuterReflowState, aFrame,
|
||||
availSpace, reason);
|
||||
@@ -111,13 +144,38 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
}
|
||||
mIsTable = NS_STYLE_DISPLAY_TABLE == reflowState.mStyleDisplay->mDisplay;
|
||||
|
||||
nscoord topMargin = 0;
|
||||
if (aApplyTopMargin) {
|
||||
// Compute the childs collapsed top margin (its margin collpased
|
||||
// with its first childs top-margin -- recursively).
|
||||
#ifdef NOISY_VERTICAL_MARGINS
|
||||
nsFrame::ListTag(stdout, mOuterReflowState.frame);
|
||||
printf(": prevBottomMargin=%d\n", aPrevBottomMargin);
|
||||
#endif
|
||||
topMargin = ComputeCollapsedTopMargin(reflowState);
|
||||
|
||||
// Collapse that value with the previous bottom margin to perform
|
||||
// the sibling to sibling collaspe.
|
||||
topMargin = MaxMargin(topMargin, aPrevBottomMargin);
|
||||
|
||||
// Adjust the available height if its constrained so that the
|
||||
// child frame doesn't think it can reflow into its margin area.
|
||||
// XXX write me
|
||||
#if 0
|
||||
availSpace.y += topMargin;
|
||||
if (NS_UNCONSTRAINEDSIZE != availHeight) {
|
||||
availSpace.height -= topMargin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Compute x/y coordinate where reflow will begin. Use the rules
|
||||
// from 10.3.3 to determine what to apply. At this point in the
|
||||
// reflow auto left/right margins will have a zero value.
|
||||
mMargin = reflowState.computedMargin;
|
||||
mStyleSpacing = reflowState.mStyleSpacing;
|
||||
nscoord x = aSpace.x + mMargin.left;
|
||||
nscoord y = aSpace.y + mSpeculativeTopMargin;
|
||||
nscoord y = aSpace.y + topMargin;
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
@@ -244,31 +302,6 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||
parent->DeleteChildsNextInFlow(mPresContext, aFrame);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
if (aApplyTopMargin) {
|
||||
// Compute final collapsed margin value
|
||||
CollapseMargins(mMargin, mMetrics.mCarriedOutTopMargin,
|
||||
mMetrics.mCarriedOutBottomMargin,
|
||||
mMetrics.height, aPrevBottomMargin,
|
||||
mTopMargin, mBottomMargin);
|
||||
|
||||
if (mSpeculativeTopMargin != mTopMargin) {
|
||||
// We lost our speculative gamble. Use new computed margin
|
||||
// value as the speculative value and try the reflow again.
|
||||
#ifdef NOISY_SPECULATIVE_TOP_MARGIN
|
||||
nsFrame::ListTag(stdout, mOuterReflowState.frame);
|
||||
printf(": reflowing again: ");
|
||||
nsFrame::ListTag(stdout, aFrame);
|
||||
printf(" guess=%d actual=%d [pass %d]\n",
|
||||
mSpeculativeTopMargin, mTopMargin, pass);
|
||||
pass++;
|
||||
#endif
|
||||
mSpeculativeTopMargin = mTopMargin;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -328,21 +361,15 @@ nsBlockReflowContext::CollapseMargins(const nsMargin& aMargin,
|
||||
*/
|
||||
PRBool
|
||||
nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
const nsMargin& aComputedOffsets,
|
||||
nscoord* aBottomMarginResult,
|
||||
nsRect& aInFlowBounds,
|
||||
nsRect& aCombinedRect)
|
||||
{
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
// Compute final collapsed margin value
|
||||
CollapseMargins(mMargin, mMetrics.mCarriedOutTopMargin,
|
||||
mMetrics.mCarriedOutBottomMargin,
|
||||
mMetrics.height, aPrevBottomMargin,
|
||||
mTopMargin, mBottomMargin);
|
||||
#endif
|
||||
// Compute collapsed bottom margin value
|
||||
nscoord collapsedBottomMargin = MaxMargin(mMetrics.mCarriedOutBottomMargin,
|
||||
mMargin.bottom);
|
||||
*aBottomMarginResult = collapsedBottomMargin;
|
||||
|
||||
// See if the block will fit in the available space
|
||||
PRBool fits = PR_TRUE;
|
||||
@@ -354,20 +381,13 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
|
||||
nsRect r(x, y, 0, 0);
|
||||
mFrame->SetRect(r);
|
||||
aInFlowBounds = r;
|
||||
// Retain combined area information in case we contain a floater
|
||||
// and nothing else.
|
||||
aCombinedRect = mMetrics.mCombinedArea;
|
||||
aCombinedRect.x += x;
|
||||
aCombinedRect.y += y;
|
||||
mTopMargin = 0;
|
||||
mBottomMargin = 0;
|
||||
}
|
||||
else {
|
||||
// Apply top margin unless it's going to be carried out.
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
if (aApplyTopMargin) {
|
||||
y += mTopMargin;
|
||||
}
|
||||
#endif
|
||||
|
||||
// See if the frame fit. If its the first frame then it always
|
||||
// fits.
|
||||
if (aForceFit || (y + mMetrics.height <= mSpace.YMost())) {
|
||||
@@ -501,9 +521,11 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit,
|
||||
m->width += mMargin.right;
|
||||
}
|
||||
|
||||
#if XXX_fix_me
|
||||
// Margin height should affect the max-element height (since
|
||||
// auto top/bottom margins are always zero)
|
||||
m->height += mTopMargin + mBottomMargin;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -28,8 +28,6 @@ class nsLineLayout;
|
||||
struct nsStylePosition;
|
||||
struct nsStyleSpacing;
|
||||
|
||||
#undef SPECULATIVE_TOP_MARGIN
|
||||
|
||||
/**
|
||||
* An encapsulation of the state and algorithm for reflowing block frames.
|
||||
*/
|
||||
@@ -54,34 +52,29 @@ public:
|
||||
|
||||
nsresult ReflowBlock(nsIFrame* aFrame,
|
||||
const nsRect& aSpace,
|
||||
#ifdef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
PRBool aIsAdjacentWithTop,
|
||||
nsMargin& aComputedOffsets,
|
||||
nsReflowStatus& aReflowStatus);
|
||||
|
||||
PRBool PlaceBlock(PRBool aForceFit,
|
||||
#ifndef SPECULATIVE_TOP_MARGIN
|
||||
PRBool aApplyTopMargin,
|
||||
nscoord aPrevBottomMargin,
|
||||
#endif
|
||||
const nsMargin& aComputedOffsets,
|
||||
nscoord* aBottomMarginResult,
|
||||
nsRect& aInFlowBounds,
|
||||
nsRect& aCombinedRect);
|
||||
|
||||
nscoord GetCollapsedTopMargin() const {
|
||||
return mTopMargin;
|
||||
}
|
||||
//XXX nscoord GetCollapsedTopMargin() const {
|
||||
//XXX return mTopMargin;
|
||||
//XXX }
|
||||
|
||||
nscoord GetCollapsedBottomMargin() const {
|
||||
return mBottomMargin;
|
||||
}
|
||||
//XXX nscoord GetCollapsedBottomMargin() const {
|
||||
//XXX return mBottomMargin;
|
||||
//XXX }
|
||||
|
||||
nscoord GetCarriedOutTopMargin() const {
|
||||
return mMetrics.mCarriedOutTopMargin;
|
||||
}
|
||||
//XXX nscoord GetCarriedOutTopMargin() const {
|
||||
//XXX return mMetrics.mCarriedOutTopMargin;
|
||||
//XXX }
|
||||
|
||||
nscoord GetCarriedOutBottomMargin() const {
|
||||
return mMetrics.mCarriedOutBottomMargin;
|
||||
@@ -138,11 +131,17 @@ protected:
|
||||
nsMargin mMargin;
|
||||
nscoord mX, mY;
|
||||
nsHTMLReflowMetrics mMetrics;
|
||||
nscoord mSpeculativeTopMargin;
|
||||
nscoord mTopMargin;
|
||||
nscoord mBottomMargin;
|
||||
//XXX nscoord mSpeculativeTopMargin;
|
||||
//XXX nscoord mTopMargin;
|
||||
//XXX nscoord mBottomMargin;
|
||||
nsSize mMaxElementSize;
|
||||
PRBool mIsTable;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRInt32 mIndent;
|
||||
#endif
|
||||
|
||||
nscoord ComputeCollapsedTopMargin(nsHTMLReflowState& aRS);
|
||||
};
|
||||
|
||||
#endif /* nsBlockReflowContext_h___ */
|
||||
|
||||
Reference in New Issue
Block a user