consider relevant overflow when balancing columns (fixes various crashes and hangs) b=404215 r+sr=roc a=beltzner

This commit is contained in:
fantasai.cvs@inkedblade.net 2008-04-18 00:40:35 -07:00
Родитель 5c9e959219
Коммит c799e1aaed
39 изменённых файлов: 727 добавлений и 90 удалений

Просмотреть файл

@ -2380,6 +2380,66 @@ nsLayoutUtils::GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
return PR_FALSE;
}
static nscoord
CalculateBlockContentBottom(nsBlockFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null ptr");
nscoord contentBottom = 0;
for (nsBlockFrame::line_iterator line = aFrame->begin_lines(),
line_end = aFrame->end_lines();
line != line_end; ++line) {
if (line->IsBlock()) {
nsIFrame* child = line->mFirstChild;
nscoord offset = child->GetRect().y - child->GetRelativeOffset().y;
contentBottom = PR_MAX(contentBottom,
nsLayoutUtils::CalculateContentBottom(child) + offset);
}
else {
contentBottom = PR_MAX(contentBottom, line->mBounds.YMost());
}
}
return contentBottom;
}
/* static */ nscoord
nsLayoutUtils::CalculateContentBottom(nsIFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null ptr");
nscoord contentBottom = aFrame->GetRect().height;
if (aFrame->GetOverflowRect().height > contentBottom) {
nsBlockFrame* blockFrame = GetAsBlock(aFrame);
nsIAtom* childList = nsnull;
PRIntn nextListID = 0;
do {
if (childList == nsnull && blockFrame) {
contentBottom = PR_MAX(contentBottom, CalculateBlockContentBottom(blockFrame));
}
else if (childList != nsGkAtoms::overflowList &&
childList != nsGkAtoms::excessOverflowContainersList &&
childList != nsGkAtoms::overflowOutOfFlowList)
{
for (nsIFrame* child = aFrame->GetFirstChild(childList);
child; child = child->GetNextSibling())
{
nscoord offset = child->GetRect().y - child->GetRelativeOffset().y;
contentBottom = PR_MAX(contentBottom,
CalculateContentBottom(child) + offset);
}
}
childList = aFrame->GetAdditionalChildListName(nextListID);
nextListID++;
} while (childList);
}
return contentBottom;
}
/* static */ nsIFrame*
nsLayoutUtils::GetClosestLayer(nsIFrame* aFrame)
{

Просмотреть файл

@ -705,6 +705,16 @@ public:
*/
static PRBool GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult);
/**
* Returns a y coordinate relative to this frame's origin that represents
* the logical bottom of the frame or its visible content, whichever is lower.
* Relative positioning is ignored and margins and glyph bounds are not
* considered.
* This value will be >= mRect.height() and <= overflowRect.YMost() unless
* relative positioning is applied.
*/
static nscoord CalculateContentBottom(nsIFrame* aFrame);
/**
* Gets the closest frame (the frame passed in or one of its parents) that
* qualifies as a "layer"; used in DOM0 methods that depends upon that

Просмотреть файл

@ -0,0 +1,29 @@
<html>
<head>
<style>
#colset {
-moz-column-count: 3;
}
.a {
height: 3in;
}
.b {
height: 24pt;
}
.c {
height: 336pt;
}
.d {
position: absolute;
}
</style>
</head>
<body onload="document.getElementById('a').className = '';">
<div id="colset"><div><div class="a" id="a"></div><div class="b"><div class="c"></div><div class="d"></div></div></div></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,37 @@
<html>
<head><style>
/* Sets of heights that trigger crash:
100px/50px/51+px
100px/30px/74+px
Get only an assert unless you set ".d { position: absolute; }".
Trigger hang (separate issue, absolute not needed):
10px/10px/9999px
10px/10px/999999px --> "bad height" notreached
*/
#colset { width: 200px;
-moz-column-count: 3; }
#a { height: 100px; }
#b { height: 50px; }
#c { height: 51px; }
#d { position: absolute; }
</style>
<script>
function boom() {
document.getElementById('a').style.height = 'auto';
}
</script>
</head>
<!-- Removing whitespace in body for simpler frame trees -->
<body onload="setTimeout('boom()', 1000)"
><div id="colset"
><div
><div id="a"></div
><div id="b"
><div id="c"></div
><div id="d"></div
></div
></div
></div
></body>
</html>

Просмотреть файл

@ -0,0 +1,32 @@
<html>
<head><style>
/* Sets of heights that trigger crash:
100px/50px/51+px
100px/30px/74+px
Get only an assert unless you set ".d { position: absolute; }".
Trigger hang (separate issue, absolute not needed):
10px/10px/9999px
10px/10px/999999px --> "bad height" notreached
*/
#colset { width: 200px;
-moz-column-count: 3; }
#a { height: 10px; }
#b { height: 10px; }
#c { height: 999999px; }
</style>
</head>
<!-- Removing whitespace in body for simpler frame trees -->
<body
><div id="colset"
><div
><div id="a"></div
><div id="b"
><div id="c"></div
><div id="d"></div
></div
></div
></div
></body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body style="position: fixed;">
<div style="position: absolute; -moz-column-width: 20em;"><div style="white-space: pre; float: right; height: 50px;"><div style="width: 100px; height: 12em;"></div>
</div></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,14 @@
<html>
<head><style>
#colset { -moz-column-count: 1; }
#short { height: 0px; }
#tall { height: 10000px; }
</style></head>
<body>
<div id="colset">
<div id="short">
<div id="tall"></div>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,14 @@
<html>
<head><style>
#colset { -moz-column-count: 1; }
#short { height: 10px; }
#tall { height: 100000px; }
</style></head>
<body>
<div id="colset">
<div id="short">
<div id="tall"></div>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -105,8 +105,14 @@ load 403576-1.html
load 404140-1.html
load 404146-1.html
load 404204-1.html
load 404215-1.html
load 404215-2.html
load 404215-3.html
load 406380.html
load 407009-1.xhtml
load 408602-1.html
load 408737-1.html
load 408737-2.html
load 408749-1.xhtml
load 408883-1.html
load 410228-1.html
@ -114,4 +120,3 @@ load 414719-1.html
load 415685-1.html
load 421404-1.html
load 425253-1.html

Просмотреть файл

@ -2960,7 +2960,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
// Reflow the block into the available space
nsMargin computedOffsets;
// construct the html reflow state for the block. ReflowBlock
// will initialize it
nsHTMLReflowState blockHtmlRS(aState.mPresContext, aState.mReflowState, frame,
@ -2977,7 +2976,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
nsReflowStatus frameReflowStatus = NS_FRAME_COMPLETE;
rv = brc.ReflowBlock(availSpace, applyTopMargin, aState.mPrevBottomMargin,
clearance, aState.IsAdjacentWithTop(), computedOffsets,
clearance, aState.IsAdjacentWithTop(),
aLine.get(), blockHtmlRS, frameReflowStatus, aState);
// If this was a second-pass reflow and the block's vertical position
@ -3023,7 +3022,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
nsCollapsingMargin collapsedBottomMargin;
nsRect combinedArea(0,0,0,0);
*aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(),
computedOffsets, collapsedBottomMargin,
collapsedBottomMargin,
aLine->mBounds, combinedArea, frameReflowStatus);
if (aLine->SetCarriedOutBottomMargin(collapsedBottomMargin)) {
line_iterator nextLine = aLine;
@ -5699,11 +5698,9 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
}
}
nsMargin offsets; // Don't bother returning this to the caller; it's stored
// on a frame property anyawy
rv = brc.ReflowBlock(availSpace, PR_TRUE, margin,
0, isAdjacentWithTop,
offsets, nsnull, floatRS,
nsnull, floatRS,
aReflowStatus, aState);
} while (NS_SUCCEEDED(rv) && clearanceFrame);

Просмотреть файл

@ -233,21 +233,12 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
return dirtiedLine;
}
static void
nsPointDtor(void *aFrame, nsIAtom *aPropertyName,
void *aPropertyValue, void *aDtorData)
{
nsPoint *point = static_cast<nsPoint*>(aPropertyValue);
delete point;
}
nsresult
nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
PRBool aApplyTopMargin,
nsCollapsingMargin& aPrevMargin,
nscoord aClearance,
PRBool aIsAdjacentWithTop,
nsMargin& aComputedOffsets,
nsLineBox* aLine,
nsHTMLReflowState& aFrameRS,
nsReflowStatus& aFrameReflowStatus,
@ -257,25 +248,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
mFrame = aFrameRS.frame;
mSpace = aSpace;
const nsStyleDisplay* display = mFrame->GetStyleDisplay();
aComputedOffsets = aFrameRS.mComputedOffsets;
if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
nsPropertyTable *propTable = mPresContext->PropertyTable();
nsPoint *offsets = static_cast<nsPoint*>
(propTable->GetProperty(mFrame, nsGkAtoms::computedOffsetProperty));
if (offsets)
offsets->MoveTo(aComputedOffsets.left, aComputedOffsets.top);
else {
offsets = new nsPoint(aComputedOffsets.left, aComputedOffsets.top);
if (offsets)
propTable->SetProperty(mFrame, nsGkAtoms::computedOffsetProperty,
offsets, nsPointDtor, nsnull);
}
}
if (!aIsAdjacentWithTop) {
aFrameRS.mFlags.mIsTopOfPage = PR_FALSE; // make sure this is cleared
}
@ -397,7 +369,6 @@ PRBool
nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
PRBool aForceFit,
nsLineBox* aLine,
const nsMargin& aComputedOffsets,
nsCollapsingMargin& aBottomMarginResult,
nsRect& aInFlowBounds,
nsRect& aCombinedRect,
@ -478,8 +449,8 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
// Apply CSS relative positioning
const nsStyleDisplay* styleDisp = mFrame->GetStyleDisplay();
if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
x += aComputedOffsets.left;
y += aComputedOffsets.top;
x += aReflowState.mComputedOffsets.left;
y += aReflowState.mComputedOffsets.top;
}
// Now place the frame and complete the reflow process

Просмотреть файл

@ -68,7 +68,6 @@ public:
nsCollapsingMargin& aPrevMargin,
nscoord aClearance,
PRBool aIsAdjacentWithTop,
nsMargin& aComputedOffsets,
nsLineBox* aLine,
nsHTMLReflowState& aReflowState,
nsReflowStatus& aReflowStatus,
@ -77,7 +76,6 @@ public:
PRBool PlaceBlock(const nsHTMLReflowState& aReflowState,
PRBool aForceFit,
nsLineBox* aLine,
const nsMargin& aComputedOffsets,
nsCollapsingMargin& aBottomMarginResult /* out */,
nsRect& aInFlowBounds,
nsRect& aCombinedRect,

Просмотреть файл

@ -1013,13 +1013,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
borderPadding.top + floatMargin.top + floatY);
// If float is relatively positioned, factor that in as well
if (NS_STYLE_POSITION_RELATIVE == floatDisplay->mPosition) {
nsPoint *offsets = static_cast<nsPoint*>
(floatFrame->GetProperty(nsGkAtoms::computedOffsetProperty));
if (offsets) {
origin += *offsets;
}
}
origin += floatFrame->GetRelativeOffset(floatDisplay);
// Position the float and make sure and views are properly
// positioned. We need to explicitly position its child views as

Просмотреть файл

@ -118,6 +118,18 @@ protected:
nscoord mColGap;
nscoord mColMaxHeight;
};
/**
* Some data that is better calculated during reflow
*/
struct ColumnBalanceData {
nscoord mMaxHeight;
nscoord mSumHeight;
nscoord mLastHeight;
void Reset() {
mMaxHeight = mSumHeight = mLastHeight = 0;
}
};
/**
* Similar to nsBlockFrame::DrainOverflowLines. Locate any columns not
@ -144,7 +156,8 @@ protected:
nsReflowStatus& aStatus,
const ReflowConfig& aConfig,
PRBool aLastColumnUnbounded,
nsCollapsingMargin* aCarriedOutBottomMargin);
nsCollapsingMargin* aCarriedOutBottomMargin,
ColumnBalanceData& aColData);
};
/**
@ -416,7 +429,10 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
nsReflowStatus& aStatus,
const ReflowConfig& aConfig,
PRBool aUnboundedLastColumn,
nsCollapsingMargin* aBottomMarginCarriedOut) {
nsCollapsingMargin* aBottomMarginCarriedOut,
ColumnBalanceData& aColData)
{
aColData.Reset();
PRBool allFit = PR_TRUE;
PRBool RTL = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
PRBool shrinkingHeightOnly = !NS_SUBTREE_DIRTY(this) &&
@ -467,7 +483,8 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
#endif
}
}
int columnCount = 0; // ignores overflow container columns; they don't affect balancing
int columnCount = 0;
int contentBottom = 0;
PRBool reflowNext = PR_FALSE;
while (child) {
@ -487,6 +504,8 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
// boundary, but if so, too bad, this optimization is defeated.)
PRBool skipResizeHeightShrink = shrinkingHeightOnly
&& child->GetOverflowRect().YMost() <= aConfig.mColMaxHeight;
nscoord childContentBottom = 0;
if (!reflowNext && (skipIncremental || skipResizeHeightShrink)) {
// This child does not need to be reflowed, but we may need to move it
MoveChildTo(this, child, childOrigin);
@ -500,6 +519,7 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
} else {
aStatus = mLastFrameStatus;
}
childContentBottom = nsLayoutUtils::CalculateContentBottom(child);
#ifdef DEBUG_roc
printf("*** Skipping child #%d %p (incremental %d, resize height shrink %d): status = %d\n",
columnCount, (void*)child, skipIncremental, skipResizeHeightShrink, aStatus);
@ -548,10 +568,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
childOrigin.y + kidReflowState.mComputedMargin.top,
0, aStatus);
if (kidDesiredSize.height > aConfig.mColMaxHeight) {
allFit = PR_FALSE;
}
reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0;
#ifdef DEBUG_roc
@ -565,11 +581,19 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
FinishReflowChild(child, PresContext(), &kidReflowState,
kidDesiredSize, childOrigin.x, childOrigin.y, 0);
childContentBottom = nsLayoutUtils::CalculateContentBottom(child);
if (childContentBottom > aConfig.mColMaxHeight) {
allFit = PR_FALSE;
}
}
contentRect.UnionRect(contentRect, child->GetRect());
ConsiderChildOverflow(overflowRect, child);
contentBottom = PR_MAX(contentBottom, childContentBottom);
aColData.mLastHeight = childContentBottom;
aColData.mSumHeight += childContentBottom;
// Build a continuation column if necessary
nsIFrame* kidNextInFlow = child->GetNextInFlow();
@ -578,8 +602,7 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
NS_ASSERTION(!kidNextInFlow, "next in flow should have been deleted");
break;
} else {
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) // don't increment for overflow containers
++columnCount;
++columnCount;
// Make sure that the column has a next-in-flow. If not, we must
// create one to hold the overflowing stuff, even if we're just
// going to put it on our overflow list and let *our*
@ -658,7 +681,8 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
contentRect.UnionRect(contentRect, child->GetRect());
}
}
aColData.mMaxHeight = contentBottom;
contentRect.height = PR_MAX(contentRect.height, contentBottom);
mLastFrameStatus = aStatus;
// contentRect included the borderPadding.left,borderPadding.top of the child rects
@ -695,23 +719,13 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
aDesiredSize.mOverflowArea = overflowRect;
#ifdef DEBUG_roc
printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_COMPLETE(aStatus)
printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
&& !NS_FRAME_IS_TRUNCATED(aStatus));
#endif
return allFit && NS_FRAME_IS_COMPLETE(aStatus)
return allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
&& !NS_FRAME_IS_TRUNCATED(aStatus);
}
static nscoord ComputeSumOfChildHeights(nsIFrame* aFrame) {
nscoord totalHeight = 0;
for (nsIFrame* f = aFrame->GetFirstChild(nsnull); f; f = f->GetNextSibling()) {
// individual columns don't have borders or padding so this is a
// reasonable way to get their content height
totalHeight += f->GetSize().height;
}
return totalHeight;
}
void
nsColumnSetFrame::DrainOverflowColumns()
{
@ -775,8 +789,9 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
nsIFrame* nextInFlow = GetNextInFlow();
PRBool unboundedLastColumn = isBalancing && !nextInFlow;
nsCollapsingMargin carriedOutBottomMargin;
ColumnBalanceData colData;
PRBool feasible = ReflowChildren(aDesiredSize, aReflowState,
aStatus, config, unboundedLastColumn, &carriedOutBottomMargin);
aStatus, config, unboundedLastColumn, &carriedOutBottomMargin, colData);
if (isBalancing) {
nscoord availableContentHeight = GetAvailableContentHeight(aReflowState);
@ -794,19 +809,10 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
while (1) {
nscoord lastKnownFeasibleHeight = knownFeasibleHeight;
nscoord maxHeight = 0;
for (nsIFrame* f = mFrames.FirstChild(); f; f = f->GetNextSibling()) {
// There could be out-of-flow content which is respecting height
// constraints ... so an available height which is greater than
// the in-flow frame height but less than the overflow height might
// not be enough to fit the content.
maxHeight = PR_MAX(maxHeight, f->GetOverflowRect().YMost());
}
// Record what we learned from the last reflow
if (feasible) {
// maxHeight is feasible. Also, mLastBalanceHeight is feasible.
knownFeasibleHeight = PR_MIN(knownFeasibleHeight, maxHeight);
knownFeasibleHeight = PR_MIN(knownFeasibleHeight, colData.mMaxHeight);
knownFeasibleHeight = PR_MIN(knownFeasibleHeight, mLastBalanceHeight);
// Furthermore, no height less than the height of the last
@ -815,15 +821,16 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
// but we can't do that with the last column.)
if (mFrames.GetLength() == config.mBalanceColCount) {
knownInfeasibleHeight = PR_MAX(knownInfeasibleHeight,
mFrames.LastChild()->GetSize().height - 1);
colData.mLastHeight - 1);
}
} else {
knownInfeasibleHeight = PR_MAX(knownInfeasibleHeight, mLastBalanceHeight);
if (unboundedLastColumn) {
// The last column is unbounded, so all content got reflowed, so the
// maxHeight is feasible.
knownFeasibleHeight = PR_MIN(knownFeasibleHeight, maxHeight);
// mColMaxHeight is feasible.
knownFeasibleHeight = PR_MIN(knownFeasibleHeight,
colData.mMaxHeight);
}
}
@ -860,7 +867,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
// Make a guess by dividing that into N columns. Add some slop
// to try to make it on the feasible side. The constant of
// 600 twips is arbitrary. It's about two line-heights.
nextGuess = ComputeSumOfChildHeights(this)/config.mBalanceColCount + 600;
nextGuess = colData.mSumHeight/config.mBalanceColCount + 600;
// Sanitize it
nextGuess = PR_MIN(PR_MAX(nextGuess, knownInfeasibleHeight + 1),
knownFeasibleHeight - 1);
@ -883,7 +890,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
AddStateBits(NS_FRAME_IS_DIRTY);
feasible = ReflowChildren(aDesiredSize, aReflowState,
aStatus, config, PR_FALSE,
&carriedOutBottomMargin);
&carriedOutBottomMargin, colData);
}
if (!feasible) {
@ -900,8 +907,8 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
}
if (!skip) {
AddStateBits(NS_FRAME_IS_DIRTY);
ReflowChildren(aDesiredSize, aReflowState,
aStatus, config, PR_FALSE, &carriedOutBottomMargin);
ReflowChildren(aDesiredSize, aReflowState, aStatus, config,
PR_FALSE, &carriedOutBottomMargin, colData);
}
}
}

Просмотреть файл

@ -3656,6 +3656,19 @@ static nsRect ComputeOutlineRect(const nsIFrame* aFrame, PRBool* aAnyOutline,
return r;
}
nsPoint
nsIFrame::GetRelativeOffset(const nsStyleDisplay* aDisplay) const
{
if (!aDisplay || NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition) {
nsPoint *offsets = static_cast<nsPoint*>
(GetProperty(nsGkAtoms::computedOffsetProperty));
if (offsets) {
return *offsets;
}
}
return nsPoint(0,0);
}
nsRect
nsIFrame::GetOverflowRect() const
{

Просмотреть файл

@ -575,10 +575,19 @@ nsHTMLReflowState::InitFrameType()
mFrameType = frameType;
}
static void
nsPointDtor(void *aFrame, nsIAtom *aPropertyName,
void *aPropertyValue, void *aDtorData)
{
nsPoint *point = static_cast<nsPoint*>(aPropertyValue);
delete point;
}
void
nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight)
nscoord aContainingBlockHeight,
nsPresContext* aPresContext)
{
// Compute the 'left' and 'right' values. 'Left' moves the boxes to the right,
// and 'right' moves the boxes to the left. The computed values are always:
@ -681,6 +690,19 @@ nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs,
// Computed value for 'bottom' is minus the value of 'top'
mComputedOffsets.bottom = -mComputedOffsets.top;
}
// Store the offset
nsPropertyTable* propTable = aPresContext->PropertyTable();
nsPoint* offsets = static_cast<nsPoint*>
(propTable->GetProperty(frame, nsGkAtoms::computedOffsetProperty));
if (offsets)
offsets->MoveTo(mComputedOffsets.left, mComputedOffsets.top);
else {
offsets = new nsPoint(mComputedOffsets.left, mComputedOffsets.top);
if (offsets)
propTable->SetProperty(frame, nsGkAtoms::computedOffsetProperty,
offsets, nsPointDtor, nsnull);
}
}
nsIFrame*
@ -1707,7 +1729,7 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
// the correct containing block width and height here, which is why we need
// to do it after all the quirks-n-such above.
if (NS_STYLE_POSITION_RELATIVE == mStyleDisplay->mPosition) {
ComputeRelativeOffsets(cbrs, aContainingBlockWidth, aContainingBlockHeight);
ComputeRelativeOffsets(cbrs, aContainingBlockWidth, aContainingBlockHeight, aPresContext);
} else {
// Initialize offsets to 0
mComputedOffsets.SizeTo(0, 0, 0, 0);

Просмотреть файл

@ -506,7 +506,8 @@ protected:
void ComputeRelativeOffsets(const nsHTMLReflowState* cbrs,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight);
nscoord aContainingBlockHeight,
nsPresContext* aPresContext);
// Calculates the computed values for the 'min-Width', 'max-Width',
// 'min-Height', and 'max-Height' properties, and stores them in the assorted

Просмотреть файл

@ -704,6 +704,11 @@ public:
void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
void SetSize(const nsSize& aSize) { mRect.SizeTo(aSize); }
/**
* Return frame's computed offset due to relative positioning
*/
nsPoint GetRelativeOffset(const nsStyleDisplay* aDisplay = nsnull) const;
virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
{ return aChild->GetPosition(); }

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
</style>
<div class="colset">
<p>one two three four five</p>
</div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
display: table;
border-collapse: separate;
border-spacing: 0;
border: solid silver;
}
p { width: 3em; display: table-cell;}
</style>
<div class="colset">
<p>one two</p>
<p>three four</p>
<p>five</p>
</div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
</style>
<div class="colset">
one two three four five
</div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
</style>
<div class="colset">
one two three four five six
</div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
display: table;
border-collapse: separate;
border-spacing: 0;
border: solid silver;
}
p { width: 3em; display: table-cell;}
</style>
<div class="colset">
<p>one two</p>
<p>three four</p>
<p>five six</p>
</div>

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
</style>
<div class="colset">
<p>one</p>
<p>two three</p>
<p>four five</p>
</div>

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; min-height: 1.5em; }
</style>
<div class="colset">
<p>one</p>
<p>two three</p>
<p>four five</p>
</div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
display: table;
border-collapse: separate;
border-spacing: 0;
border: solid silver;
}
p { width: 3em; display: table-cell;}
</style>
<div class="colset">
<p>one</p>
<p>two three</p>
<p>four five</p>
</div>

Просмотреть файл

@ -0,0 +1,21 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { height: 1em; border : solid}
p:first-child { height: 6em; }
</style>
<div class="colset">
<p></p>
<p></p>
<p></p>
</div>

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
.short { height: 5px; }
</style>
<div class="colset">
<div class="short"><p>one two three four five</p></div>
</div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
</style>
<div class="colset">
<p>one two three four five</p>
</div>

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
.short { height: 5px; }
</style>
<div class="colset">
<p class="short">one two three four five</p>
</div>

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
p { margin: 0; }
.short { height: 5px; }
.table { display: table; }
</style>
<div class="colset">
<div class="table">
<div class="short">
<p>one two three four five</p>
</div>
</div>
</div>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
border: solid silver;
width: 9em;
}
p { margin: 0; width: 3em;}
</style>
<div class="colset">
<p>one two three four five</p>
</div>

Просмотреть файл

@ -0,0 +1,21 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
.short { height: 5px; }
img { display: block;
width: 3em;
height: 3em;}
</style>
<div class="colset">
<div class="short"><img src="image-short.png"></div>
</div>

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
-moz-column-count: 3;
-moz-column-gap: 0;
border: solid silver;
width: 9em;
}
img { display: block;
width: 3em;
height: 3em;}
</style>
<div class="colset">
<img src="image-short.png">
</div>

Просмотреть файл

@ -0,0 +1,43 @@
<html class="reftest-wait">
<head><style>
/* Sets of heights that trigger crash:
100px/50px/51+px
100px/30px/74+px
Get only an assert unless you set ".d { position: absolute; }".
Trigger hang (separate issue, absolute not needed):
10px/10px/9999px
10px/10px/999999px --> "bad height" notreached
*/
/* Note: The -moz-column-gap and the backgrounds
are just added here for easier visualization */
#colset { width: 200px;
padding: 2px;
-moz-column-count: 3;
-moz-column-gap: 2px; }
#a { height: 100px; background: lightblue;}
#b { height: 50px; background: lightgreen;}
#c { height: 51px; background: orange;}
</style>
<script>
function boom() {
document.getElementById('colset').offsetHeight;
document.getElementById('a').style.height = 'auto';
document.documentElement.className = ''
}
</script>
</head>
<!-- Removing whitespace in body for simpler frame trees -->
<body onload="boom()"
><div id="colset"
><div
><div id="a"></div
><div id="b"
><div id="c"></div
><div id="d"></div
></div
></div
></div
></body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
display: table;
border-collapse: separate;
border-spacing: 2px;
width: 204px;
}
p { background: orange; display: table-cell; height: 17px}
</style>
<div class="colset">
<p></p>
<p></p>
<p></p>
</div>

Просмотреть файл

@ -0,0 +1,13 @@
<html><head>
<style>
#colset { width: 200px;
-moz-column-count: 3;
-moz-column-gap: 4px;
padding: 4px;
outline: 1px orange solid; }
#b { height: 12px;
outline: 1px green dotted;}
#c { height: 13px;
background: yellow;}
</style></head><body><div id="colset"><div id="b"><div id="c"></div></div></div>
</body></html>

Просмотреть файл

@ -0,0 +1,25 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Balancing Overflow</title>
<style type="text/css">
.colset {
display: table;
border-collapse: separate;
border-spacing: 4px;
width: 208px;
border: solid 1px orange;
margin: -1px;
}
p {
display: table-cell;
background: yellow;
height: 4px;
outline: 1px green dotted;
}
</style>
<div class="colset">
<p></p>
<p></p>
<p></p>
</div>

Просмотреть файл

@ -5,3 +5,14 @@
== min-width-1a.html min-width-1-ref.html
== min-width-1b.html min-width-1-ref.html
== min-width-1c.html min-width-1-ref.html
== column-balancing-overflow-000.html column-balancing-overflow-000.ref.html
== column-balancing-overflow-001.html column-balancing-overflow-000.ref.html
== column-balancing-overflow-002.html column-balancing-overflow-002.ref.html
== column-balancing-overflow-003.html column-balancing-overflow-003.ref.html
== column-balancing-overflow-004.html column-balancing-overflow-004.ref.html
== column-balancing-overflow-005.html column-balancing-overflow-005.ref.html
== column-balancing-000.html column-balancing-000.ref.html
== column-balancing-001.html column-balancing-000.ref.html
== column-balancing-002.html column-balancing-002.ref.html
== column-balancing-003.html column-balancing-000.ref.html
== column-balancing-004.html column-balancing-004.ref.html