Bug 724978 - nsColumnSetFrame should be an absolute container; r=roc a=lsblakk
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 09 Apr 2012 11:21:00 -0400
changeset 95551 740245b70266a796699493802e31c76734385144
parent 95550 7525533b3e42c8d7e47c1f8850518f640824cf2b
child 95552 c584e12ad1bd02034bc9aca3f863eba427e27804
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, lsblakk
bugs724978
milestone14.0a2
Bug 724978 - nsColumnSetFrame should be an absolute container; r=roc a=lsblakk
layout/generic/crashtests/724978.xhtml
layout/generic/crashtests/crashtests.list
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/reftests/abs-pos/reftest.list
layout/reftests/bugs/reftest.list
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/724978.xhtml
@@ -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>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -380,13 +380,14 @@ load 679933-1.html
 load 682649-1.html
 load 683702-1.xhtml
 load 688996-1.html
 load 688996-2.html
 load 683712.html
 load text-overflow-bug713610.html
 load 700031.xhtml
 load 718516.html
+load 724978.xhtml
 load first-letter-638937.html
 asserts(2) load first-letter-638937-2.html
 load 737313-1.html
 load 737313-2.html
 load 737313-3.html
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -295,16 +295,20 @@ nsColumnSetFrame::PaintColumnRule(nsRend
     nextSibling = nextSibling->GetNextSibling();
   }
 }
 
 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");
   // Queue up the frames for the content frame
   return nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList);
 }
 
@@ -1095,20 +1099,17 @@ nsColumnSetFrame::Reflow(nsPresContext* 
       aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
     // In this situation, we might be lying about our reflow status, because
     // our last kid (the one that got interrupted) was incomplete.  Fix that.
     aStatus = NS_FRAME_COMPLETE;
   }
   
   CheckInvalidateSizeChange(aDesiredSize);
 
-  // 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;
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
 
   NS_ASSERTION(NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
                aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE,
                "Column set should be complete if the available height is unconstrained");
@@ -1142,28 +1143,40 @@ nsColumnSetFrame::GetSkipSides() const
 {
   return 0;
 }
 
 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
 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;
 }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3969,36 +3969,38 @@ nsFrame::DidReflow(nsPresContext*       
 
   return NS_OK;
 }
 
 void
 nsFrame::FinishReflowWithAbsoluteFrames(nsPresContext*           aPresContext,
                                         nsHTMLReflowMetrics&     aDesiredSize,
                                         const nsHTMLReflowState& aReflowState,
-                                        nsReflowStatus&          aStatus)
-{
-  ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
+                                        nsReflowStatus&          aStatus,
+                                        bool                     aConstrainHeight)
+{
+  ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, aConstrainHeight);
 
   FinishAndStoreOverflow(&aDesiredSize);
 }
 
 void
 nsFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot)
 {
   if (IsAbsoluteContainer()) {
     GetAbsoluteContainingBlock()->DestroyFrames(this, aDestructRoot);
   }
 }
 
 void
 nsFrame::ReflowAbsoluteFrames(nsPresContext*           aPresContext,
                               nsHTMLReflowMetrics&     aDesiredSize,
                               const nsHTMLReflowState& aReflowState,
-                              nsReflowStatus&          aStatus)
+                              nsReflowStatus&          aStatus,
+                              bool                     aConstrainHeight)
 {
   if (HasAbsolutelyPositionedChildren()) {
     nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock();
 
     // Let the absolutely positioned container reflow any absolutely positioned
     // child frames that need to be reflowed
 
     // The containing block for the abs pos kids is formed by our padding edge.
@@ -4009,17 +4011,17 @@ nsFrame::ReflowAbsoluteFrames(nsPresCont
     nscoord containingBlockHeight =
       aDesiredSize.height - computedBorder.TopBottom();
 
     nsContainerFrame* container = do_QueryFrame(this);
     NS_ASSERTION(container, "Abs-pos children only supported on container frames for now");
 
     absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus,
                               containingBlockWidth, containingBlockHeight,
-                              true, true, true, // XXX could be optimized
+                              aConstrainHeight, true, true, // XXX could be optimized
                               &aDesiredSize.mOverflowAreas);
   }
 }
 
 /* virtual */ bool
 nsFrame::CanContinueTextRun() const
 {
   // By default, a frame will *not* allow a text run to be continued
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -334,21 +334,23 @@ public:
                      const nsHTMLReflowState& aReflowState,
                      nsReflowStatus&          aStatus);
   NS_IMETHOD  DidReflow(nsPresContext*           aPresContext,
                         const nsHTMLReflowState*  aReflowState,
                         nsDidReflowStatus         aStatus);
   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);
   void DestroyAbsoluteFrames(nsIFrame* aDestructRoot);
   virtual bool CanContinueTextRun() const;
 
   virtual bool UpdateOverflow();
 
   // Selection Methods
   // XXX Doc me... (in nsIFrame.h puhleeze)
   // XXX If these are selection specific, then the name should imply selection
--- a/layout/reftests/abs-pos/reftest.list
+++ b/layout/reftests/abs-pos/reftest.list
@@ -8,13 +8,11 @@ fails-if(/^Windows\x20NT\x206\.1/.test(h
 == continuation-positioned-inline-1.html continuation-positioned-inline-ref.html
 == continuation-positioned-inline-2.html continuation-positioned-inline-ref.html
 == scrollframe-1.html scrollframe-1-ref.html
 == scrollframe-2.html scrollframe-2-ref.html
 == select-1.html select-1-ref.html
 == select-1-dynamic.html select-1-ref.html
 == select-2.html select-2-ref.html
 == 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
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -678,23 +678,21 @@ fails-if(Android) != 376532-3.html 37653
 == 378935-1.html 378935-1-ref.html
 == 378937-1.html 378937-1-ref.html
 == 379178-xhtml.xhtml 379178-xhtml-ref.xhtml
 == 379178-html.html 379178-html-ref.html
 == 379178-svg.svg 379178-svg-ref.svg
 == 379316-1.html 379316-1-ref.html
 fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 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
 == 379349-3a.xhtml 379349-3-ref.xhtml
 == 379349-3b.xhtml 379349-3-ref.xhtml
 == 379361-1.html 379361-1-ref.html
 == 379361-2.html 379361-2-ref.html
 == 379361-3.html 379361-3-ref.html
 == 379461-1.xhtml 379461-1.html
 == 379461-2.xhtml 379461-2.html
 == 379461-3-container-xhtml.html 379461-3-container-html.html