Bug 724978: Make nsColumnSetFrame handle absolutely positioned children without crashing. [p=ehsan, r=fantasai]

This commit is contained in:
Scott Johnson 2013-02-28 19:56:48 -08:00
parent 999eeb2111
commit aa7f8f28f4
7 changed files with 299 additions and 33 deletions

View File

@ -0,0 +1,234 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>Multi-column Layout: AbsPos Pagination (Interlaced Dynamic Height)</title>
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#the-height-property"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#length-units"/>
<style type="text/css">
html {
background: white;
}
.container {
background: red;
height: 24pt;
position: relative;
-moz-column-count: 2;
-moz-column-gap: 0;
}
.overflow {
width: 10pt;
border-bottom: lime 8px solid;
top: 0;
}
.following {
position: relative;
background: white;
width: 100pt;
}
#colset {
padding-top: 1px;
width: 300pt;
height: 2in;
-moz-column-count: 3;
-moz-column-gap: 0;
border: silver 2pt;
border-style: none solid;
}
#redline {
width: 303pt;
border-top: 8px solid red;
margin-top: -1in;
position: relative;
z-index: -1;
}
.ocontainer {
height: 0;
position: relative;
-moz-column-count: 2;
-moz-column-gap: 0;
}
.o1 { /* 3rd col */
height: 10in;
}
.a1 { /* 1st col */
position: absolute;
height: 2in;
width: 33pt;
}
.a2 { /* 2nd col */
position: absolute;
height: 6in;
width: 25pt;
margin-left: 25pt;
}
.a3 { /* 3rd col */
position: absolute;
height: 10in;
margin-left: 10pt;
}
.a4 { /* 2nd col */
width: 25pt;
height: 6in;
}
.b1 { /* 3rd col */
position: absolute;
height: 672pt;
margin-left: 20pt;
}
.b2 { /* 2nd col */
position: absolute;
height: 384pt;
width: 25pt;
margin-left: 50pt;
}
.b3 { /* 3rd col */
position: absolute;
height: 672pt;
margin-left: 30pt;
}
.b4 { /* 1st col, but no border */
position: absolute;
height: 96pt;
border-bottom: none;
}
.b4 .child1 { /* 1st col */
position: absolute;
height: 200%;
width: 33pt;
margin-left: 33pt;
}
.b4 .child2 { /* 3rd col */
height: 672pt;
margin-left: 40pt;
}
.b5 { /* 1st col */
position: absolute;
height: 96pt;
width: 34pt;
margin-left: 66pt;
}
.b6 { /* 3rd col */
height: 672pt;
margin-left: 50pt;
}
.c1 { /* 3rd col */
position: absolute;
height: 6in;
margin-left: 60pt;
}
.c2 { /* 2nd col */
position: absolute;
height: 2in;
width: 25pt;
margin-left: 75pt;
}
.c3 { /* 3rd col */
position: absolute;
height: 6in;
margin-left: 70pt;
}
.c4 { /* 3rd col */
height: 6in;
width: 20pt;
margin-left: 80pt;
}
.f1 {
margin-top: -48pt;
height: 96pt;
margin-bottom: 96pt;
}
.f2 {
margin-top: -24pt;
height: 48pt;
}
.centerline {
margin: 0 auto;
top: 0;
left: 0;
right: 0;
position: absolute;
width: 8px;
height: 6in;
background: aqua;
}
#dynamo {
background: transparent;
border-bottom: 8px solid orange;
z-index: 10;
height: 384pt;
}
</style>
</head>
<body onload="document.getElementById('dynamo').style.height = '96pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '672pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '96pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '384pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '3000pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '96pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '384pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '672pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '384pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '96pt';
document.getElementById('dynamo').offsetHeight;
document.getElementById('dynamo').style.height = '384pt';
document.documentElement.className = ''
">
<div id="colset">
<div>
<div class="ocontainer">
<div class="centerline"></div>
<div class="overflow o1"></div>
</div>
<div class="container">
<div class="overflow a1"></div>
<div class="overflow a2"></div>
<div class="overflow a3"></div>
<div class="overflow a4"></div>
</div>
<div class="ocontainer">
<div id="dynamo" class="centerline"></div>
</div>
<div class="container">
<div class="overflow b1"></div>
<div class="overflow b2"></div>
<div class="overflow b3"></div>
<div class="overflow b4">
<div class="overflow child1"></div>
<div class="overflow child2"></div>
</div>
<div class="overflow b5"></div>
<div class="overflow b6"></div>
</div>
</div>
<p class="following f1">
</p>
<div class="container">
<div class="overflow c1"></div>
<div class="overflow c2"></div>
<div class="overflow c3"></div>
<div class="overflow c4"></div>
</div>
<div class="following f2"></div>
</div>
<div id="redline"></div>
</body>
</html>

View File

@ -425,6 +425,7 @@ load 683712.html
load text-overflow-bug713610.html
load 700031.xhtml
load 718516.html
load 724978.xhtml
load first-letter-638937.html
load first-letter-638937-2.html
load 734777.html

View File

@ -64,6 +64,12 @@ public:
return nsContainerFrame::StealFrame(aPresContext, aChild, true);
}
virtual bool IsFrameOfType(uint32_t aFlags) const
{
return nsContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eCanContainOverflowContainers));
}
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
@ -132,7 +138,8 @@ protected:
* style. This function will also be responsible for implementing
* the state machine that controls column balancing.
*/
ReflowConfig ChooseColumnStrategy(const nsHTMLReflowState& aReflowState);
ReflowConfig ChooseColumnStrategy(const nsHTMLReflowState& aReflowState,
bool aForceAuto);
/**
* Reflow column children. Returns true iff the content that was reflowed
@ -259,10 +266,14 @@ NS_IMETHODIMP
nsColumnSetFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList)
{
if (aListID == kAbsoluteList) {
return nsContainerFrame::SetInitialChildList(aListID, aChildList);
}
NS_ASSERTION(aListID == kPrincipalList,
"Only default child list supported");
NS_ASSERTION(aChildList.OnlyChild(),
"initial child list must have exactly one child");
"initial child list must have exaisRevertingctly one child");
// Queue up the frames for the content frame
return nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList);
}
@ -308,7 +319,8 @@ GetColumnGap(nsColumnSetFrame* aFrame,
}
nsColumnSetFrame::ReflowConfig
nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState)
nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState,
bool aForceAuto = false)
{
const nsStyleColumn* colStyle = StyleColumn();
nscoord availContentWidth = GetAvailableContentWidth(aReflowState);
@ -326,7 +338,8 @@ nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState)
int32_t numColumns = colStyle->mColumnCount;
// If column-fill is set to 'balance', then we want to balance the columns.
const bool isBalancing = colStyle->mColumnFill == NS_STYLE_COLUMN_FILL_BALANCE;
const bool isBalancing = colStyle->mColumnFill == NS_STYLE_COLUMN_FILL_BALANCE
&& !aForceAuto;
if (isBalancing) {
const uint32_t MAX_NESTED_COLUMN_BALANCING = 2;
uint32_t cnt = 0;
@ -404,6 +417,16 @@ nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState)
// This is the case when the column-fill property is set to 'auto'.
// No balancing, so don't limit the column count
numColumns = INT32_MAX;
// XXX_jwir3: If a page's height is set to 0, we could continually
// create continuations, resulting in an infinite loop, since
// no progress is ever made. This is an issue with the spec
// (css3-multicol, css3-page, and css3-break) that is
// unresolved as of 27 Feb 2013. For the time being, we set this
// to have a minimum of 1 css px. Once a resolution is made
// on what minimum to have for a page height, we may need to
// change this value to match the appropriate spec(s).
colHeight = std::max(colHeight, nsPresContext::CSSPixelsToAppUnits(1));
}
#ifdef DEBUG_roc
@ -611,7 +634,7 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
if (aUnboundedLastColumn && columnCount == aConfig.mBalanceColCount - 1) {
availSize.height = GetAvailableContentHeight(aReflowState);
}
if (reflowNext)
child->AddStateBits(NS_FRAME_IS_DIRTY);
@ -919,9 +942,8 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
// children, we were balancing and we overflowed in the block direction.
do {
if (colData.mShouldRevertToAuto) {
config = ChooseColumnStrategy(aReflowState);
config = ChooseColumnStrategy(aReflowState, true);
isBalancing = false;
config.mBalanceColCount = INT32_MAX;
}
bool feasible = ReflowChildren(aDesiredSize, aReflowState,
@ -1067,10 +1089,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
}
// XXXjwir3: This call should be replaced with FinishWithAbsoluteFrames
// when bug 724978 is fixed and nsColumnSetFrame is a full absolute
// container.
FinishAndStoreOverflow(&aDesiredSize);
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, false);
aDesiredSize.mCarriedOutBottomMargin = carriedOutBottomMargin;
@ -1103,8 +1122,12 @@ NS_IMETHODIMP
nsColumnSetFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList)
{
NS_NOTREACHED("AppendFrames not supported");
return NS_ERROR_NOT_IMPLEMENTED;
if (aListID == kAbsoluteList) {
return nsContainerFrame::AppendFrames(aListID, aFrameList);
}
NS_ERROR("unexpected child list");
return NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP
@ -1112,14 +1135,22 @@ nsColumnSetFrame::InsertFrames(ChildListID aListID,
nsIFrame* aPrevFrame,
nsFrameList& aFrameList)
{
NS_NOTREACHED("InsertFrames not supported");
return NS_ERROR_NOT_IMPLEMENTED;
if (aListID == kAbsoluteList) {
return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
}
NS_ERROR("unexpected child list");
return NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP
nsColumnSetFrame::RemoveFrame(ChildListID aListID,
nsIFrame* aOldFrame)
{
NS_NOTREACHED("RemoveFrame not supported");
return NS_ERROR_NOT_IMPLEMENTED;
if (aListID == kAbsoluteList) {
return nsContainerFrame::RemoveFrame(aListID, aOldFrame);
}
NS_ERROR("unexpected child list");
return NS_ERROR_INVALID_ARG;
}

View File

@ -4196,9 +4196,10 @@ void
nsFrame::FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsReflowStatus& aStatus,
bool aConstrainHeight)
{
ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, aConstrainHeight);
FinishAndStoreOverflow(&aDesiredSize);
}
@ -4207,7 +4208,8 @@ void
nsFrame::ReflowAbsoluteFrames(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsReflowStatus& aStatus,
bool aConstrainHeight)
{
if (HasAbsolutelyPositionedChildren()) {
nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock();
@ -4228,7 +4230,7 @@ nsFrame::ReflowAbsoluteFrames(nsPresContext* aPresContext,
absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus,
containingBlockWidth, containingBlockHeight,
true, true, true, // XXX could be optimized
aConstrainHeight, true, true, // XXX could be optimized
&aDesiredSize.mOverflowAreas);
}
}

View File

@ -336,11 +336,13 @@ public:
void ReflowAbsoluteFrames(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
nsReflowStatus& aStatus,
bool aConstrainHeight = true);
void FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
nsReflowStatus& aStatus,
bool aConstrainHeight = true);
virtual bool CanContinueTextRun() const;
virtual bool UpdateOverflow();

View File

@ -13,8 +13,6 @@ fuzzy-if(gtk2Widget,1,8) == select-1.html select-1-ref.html
fuzzy-if(gtk2Widget,1,8) == select-1-dynamic.html select-1-ref.html
== select-2.html select-2-ref.html
fuzzy-if(gtk2Widget,1,19) fuzzy-if(Android||B2G,17,726) == select-3.html select-3-ref.html
# Fails due to bug 724978. Should be re-enabled once this is fixed.
fails == multi-column-1.html multi-column-1-ref.html
== multi-column-1.html multi-column-1-ref.html
== button-1.html button-1-ref.html
== button-2.html button-2-ref.html

View File

@ -683,13 +683,11 @@ skip-if(B2G) == 378937-1.html 378937-1-ref.html
== 379316-1.html 379316-1-ref.html
skip-if(B2G) fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(gtk2Widget,1,191) == 379316-2.html 379316-2-ref.html # bug 379786
== 379328-1.html 379328-1-ref.html
# The next set of reftests all fail until bug 724978 has been fixed, and the
# overflow container ability of nsColumnSetFrame is restored.
fails == 379349-1a.xhtml 379349-1-ref.xhtml
fails == 379349-1b.xhtml 379349-1-ref.xhtml
fails == 379349-1c.xhtml 379349-1-ref.xhtml
fails == 379349-2a.xhtml 379349-2-ref.xhtml
fails == 379349-2b.xhtml 379349-2-ref.xhtml
== 379349-1a.xhtml 379349-1-ref.xhtml
== 379349-1b.xhtml 379349-1-ref.xhtml
== 379349-1c.xhtml 379349-1-ref.xhtml
== 379349-2a.xhtml 379349-2-ref.xhtml
== 379349-2b.xhtml 379349-2-ref.xhtml
skip-if(B2G) == 379349-3a.xhtml 379349-3-ref.xhtml
skip-if(B2G) == 379349-3b.xhtml 379349-3-ref.xhtml
== 379361-1.html 379361-1-ref.html