layout/generic/nsColumnSetFrame.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /* rendering object for css3 multi-column layout */
     8 #include "nsColumnSetFrame.h"
     9 #include "nsCSSRendering.h"
    10 #include "nsDisplayList.h"
    12 using namespace mozilla;
    13 using namespace mozilla::layout;
    15 /**
    16  * Tracking issues:
    17  *
    18  * XXX cursor movement around the top and bottom of colums seems to make the editor
    19  * lose the caret.
    20  *
    21  * XXX should we support CSS columns applied to table elements?
    22  */
    23 nsIFrame*
    24 NS_NewColumnSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, nsFrameState aStateFlags)
    25 {
    26   nsColumnSetFrame* it = new (aPresShell) nsColumnSetFrame(aContext);
    27   it->AddStateBits(aStateFlags | NS_BLOCK_MARGIN_ROOT);
    28   return it;
    29 }
    31 NS_IMPL_FRAMEARENA_HELPERS(nsColumnSetFrame)
    33 nsColumnSetFrame::nsColumnSetFrame(nsStyleContext* aContext)
    34   : nsContainerFrame(aContext), mLastBalanceHeight(NS_INTRINSICSIZE),
    35     mLastFrameStatus(NS_FRAME_COMPLETE)
    36 {
    37 }
    39 nsIAtom*
    40 nsColumnSetFrame::GetType() const
    41 {
    42   return nsGkAtoms::columnSetFrame;
    43 }
    45 static void
    46 PaintColumnRule(nsIFrame* aFrame, nsRenderingContext* aCtx,
    47                 const nsRect& aDirtyRect, nsPoint aPt)
    48 {
    49   static_cast<nsColumnSetFrame*>(aFrame)->PaintColumnRule(aCtx, aDirtyRect, aPt);
    50 }
    52 void
    53 nsColumnSetFrame::PaintColumnRule(nsRenderingContext* aCtx,
    54                                   const nsRect& aDirtyRect,
    55                                   const nsPoint& aPt)
    56 {
    57   nsIFrame* child = mFrames.FirstChild();
    58   if (!child)
    59     return;  // no columns
    61   nsIFrame* nextSibling = child->GetNextSibling();
    62   if (!nextSibling)
    63     return;  // 1 column only - this means no gap to draw on
    65   bool isRTL = StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
    66   const nsStyleColumn* colStyle = StyleColumn();
    68   uint8_t ruleStyle;
    69   // Per spec, inset => ridge and outset => groove
    70   if (colStyle->mColumnRuleStyle == NS_STYLE_BORDER_STYLE_INSET)
    71     ruleStyle = NS_STYLE_BORDER_STYLE_RIDGE;
    72   else if (colStyle->mColumnRuleStyle == NS_STYLE_BORDER_STYLE_OUTSET)
    73     ruleStyle = NS_STYLE_BORDER_STYLE_GROOVE;
    74   else
    75     ruleStyle = colStyle->mColumnRuleStyle;
    77   nsPresContext* presContext = PresContext();
    78   nscoord ruleWidth = colStyle->GetComputedColumnRuleWidth();
    79   if (!ruleWidth)
    80     return;
    82   nscolor ruleColor =
    83     GetVisitedDependentColor(eCSSProperty__moz_column_rule_color);
    85   // In order to re-use a large amount of code, we treat the column rule as a border.
    86   // We create a new border style object and fill in all the details of the column rule as
    87   // the left border. PaintBorder() does all the rendering for us, so we not
    88   // only save an enormous amount of code but we'll support all the line styles that
    89   // we support on borders!
    90   nsStyleBorder border(presContext);
    91   border.SetBorderWidth(NS_SIDE_LEFT, ruleWidth);
    92   border.SetBorderStyle(NS_SIDE_LEFT, ruleStyle);
    93   border.SetBorderColor(NS_SIDE_LEFT, ruleColor);
    95   // Get our content rect as an absolute coordinate, not relative to
    96   // our parent (which is what the X and Y normally is)
    97   nsRect contentRect = GetContentRect() - GetRect().TopLeft() + aPt;
    98   nsSize ruleSize(ruleWidth, contentRect.height);
   100   while (nextSibling) {
   101     // The frame tree goes RTL in RTL
   102     nsIFrame* leftSibling = isRTL ? nextSibling : child;
   103     nsIFrame* rightSibling = isRTL ? child : nextSibling;
   105     // Each child frame's position coordinates is actually relative to this nsColumnSetFrame.
   106     // linePt will be at the top-left edge to paint the line.
   107     nsPoint edgeOfLeftSibling = leftSibling->GetRect().TopRight() + aPt;
   108     nsPoint edgeOfRightSibling = rightSibling->GetRect().TopLeft() + aPt;
   109     nsPoint linePt((edgeOfLeftSibling.x + edgeOfRightSibling.x - ruleWidth) / 2,
   110                    contentRect.y);
   112     nsRect lineRect(linePt, ruleSize);
   113     nsCSSRendering::PaintBorderWithStyleBorder(presContext, *aCtx, this,
   114         aDirtyRect, lineRect, border, StyleContext(),
   115         // Remember, we only have the "left" "border". Skip everything else
   116         (1 << NS_SIDE_TOP | 1 << NS_SIDE_RIGHT | 1 << NS_SIDE_BOTTOM));
   118     child = nextSibling;
   119     nextSibling = nextSibling->GetNextSibling();
   120   }
   121 }
   123 nsresult
   124 nsColumnSetFrame::SetInitialChildList(ChildListID     aListID,
   125                                       nsFrameList&    aChildList)
   126 {
   127   if (aListID == kAbsoluteList) {
   128     return nsContainerFrame::SetInitialChildList(aListID, aChildList);
   129   }
   131   NS_ASSERTION(aListID == kPrincipalList,
   132                "Only default child list supported");
   133   NS_ASSERTION(aChildList.OnlyChild(),
   134                "initial child list must have exaisRevertingctly one child");
   135   // Queue up the frames for the content frame
   136   return nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList);
   137 }
   139 static nscoord
   140 GetAvailableContentWidth(const nsHTMLReflowState& aReflowState)
   141 {
   142   if (aReflowState.AvailableWidth() == NS_INTRINSICSIZE) {
   143     return NS_INTRINSICSIZE;
   144   }
   145   nscoord borderPaddingWidth =
   146     aReflowState.ComputedPhysicalBorderPadding().left +
   147     aReflowState.ComputedPhysicalBorderPadding().right;
   148   return std::max(0, aReflowState.AvailableWidth() - borderPaddingWidth);
   149 }
   151 nscoord
   152 nsColumnSetFrame::GetAvailableContentHeight(const nsHTMLReflowState& aReflowState)
   153 {
   154   if (aReflowState.AvailableHeight() == NS_INTRINSICSIZE) {
   155     return NS_INTRINSICSIZE;
   156   }
   158   nsMargin bp = aReflowState.ComputedPhysicalBorderPadding();
   159   ApplySkipSides(bp, &aReflowState);
   160   bp.bottom = aReflowState.ComputedPhysicalBorderPadding().bottom;
   161   return std::max(0, aReflowState.AvailableHeight() - bp.TopBottom());
   162 }
   164 static nscoord
   165 GetColumnGap(nsColumnSetFrame*    aFrame,
   166              const nsStyleColumn* aColStyle)
   167 {
   168   if (eStyleUnit_Normal == aColStyle->mColumnGap.GetUnit())
   169     return aFrame->StyleFont()->mFont.size;
   170   if (eStyleUnit_Coord == aColStyle->mColumnGap.GetUnit()) {
   171     nscoord colGap = aColStyle->mColumnGap.GetCoordValue();
   172     NS_ASSERTION(colGap >= 0, "negative column gap");
   173     return colGap;
   174   }
   176   NS_NOTREACHED("Unknown gap type");
   177   return 0;
   178 }
   180 nsColumnSetFrame::ReflowConfig
   181 nsColumnSetFrame::ChooseColumnStrategy(const nsHTMLReflowState& aReflowState,
   182                                        bool aForceAuto = false,
   183                                        nscoord aFeasibleHeight = NS_INTRINSICSIZE,
   184                                        nscoord aInfeasibleHeight = 0)
   186 {
   187   nscoord knownFeasibleHeight = aFeasibleHeight;
   188   nscoord knownInfeasibleHeight = aInfeasibleHeight;
   190   const nsStyleColumn* colStyle = StyleColumn();
   191   nscoord availContentWidth = GetAvailableContentWidth(aReflowState);
   192   if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) {
   193     availContentWidth = aReflowState.ComputedWidth();
   194   }
   196   nscoord consumedHeight = GetConsumedHeight();
   198   // The effective computed height is the height of the current continuation
   199   // of the column set frame. This should be the same as the computed height
   200   // if we have an unconstrained available height.
   201   nscoord computedHeight = GetEffectiveComputedHeight(aReflowState,
   202                                                       consumedHeight);
   203   nscoord colHeight = GetAvailableContentHeight(aReflowState);
   205   if (aReflowState.ComputedHeight() != NS_INTRINSICSIZE) {
   206     colHeight = aReflowState.ComputedHeight();
   207   } else if (aReflowState.ComputedMaxHeight() != NS_INTRINSICSIZE) {
   208     colHeight = std::min(colHeight, aReflowState.ComputedMaxHeight());
   209   }
   211   nscoord colGap = GetColumnGap(this, colStyle);
   212   int32_t numColumns = colStyle->mColumnCount;
   214   // If column-fill is set to 'balance', then we want to balance the columns.
   215   const bool isBalancing = colStyle->mColumnFill == NS_STYLE_COLUMN_FILL_BALANCE
   216                            && !aForceAuto;
   217   if (isBalancing) {
   218     const uint32_t MAX_NESTED_COLUMN_BALANCING = 2;
   219     uint32_t cnt = 0;
   220     for (const nsHTMLReflowState* rs = aReflowState.parentReflowState;
   221          rs && cnt < MAX_NESTED_COLUMN_BALANCING; rs = rs->parentReflowState) {
   222       if (rs->mFlags.mIsColumnBalancing) {
   223         ++cnt;
   224       }
   225     }
   226     if (cnt == MAX_NESTED_COLUMN_BALANCING) {
   227       numColumns = 1;
   228     }
   229   }
   231   nscoord colWidth;
   232   if (colStyle->mColumnWidth.GetUnit() == eStyleUnit_Coord) {
   233     colWidth = colStyle->mColumnWidth.GetCoordValue();
   234     NS_ASSERTION(colWidth >= 0, "negative column width");
   235     // Reduce column count if necessary to make columns fit in the
   236     // available width. Compute max number of columns that fit in
   237     // availContentWidth, satisfying colGap*(maxColumns - 1) +
   238     // colWidth*maxColumns <= availContentWidth
   239     if (availContentWidth != NS_INTRINSICSIZE && colGap + colWidth > 0
   240         && numColumns > 0) {
   241       // This expression uses truncated rounding, which is what we
   242       // want
   243       int32_t maxColumns =
   244         std::min(nscoord(nsStyleColumn::kMaxColumnCount),
   245                  (availContentWidth + colGap)/(colGap + colWidth));
   246       numColumns = std::max(1, std::min(numColumns, maxColumns));
   247     }
   248   } else if (numColumns > 0 && availContentWidth != NS_INTRINSICSIZE) {
   249     nscoord widthMinusGaps = availContentWidth - colGap*(numColumns - 1);
   250     colWidth = widthMinusGaps/numColumns;
   251   } else {
   252     colWidth = NS_INTRINSICSIZE;
   253   }
   254   // Take care of the situation where there's only one column but it's
   255   // still too wide
   256   colWidth = std::max(1, std::min(colWidth, availContentWidth));
   258   nscoord expectedWidthLeftOver = 0;
   260   if (colWidth != NS_INTRINSICSIZE && availContentWidth != NS_INTRINSICSIZE) {
   261     // distribute leftover space
   263     // First, determine how many columns will be showing if the column
   264     // count is auto
   265     if (numColumns <= 0) {
   266       // choose so that colGap*(nominalColumnCount - 1) +
   267       // colWidth*nominalColumnCount is nearly availContentWidth
   268       // make sure to round down
   269       if (colGap + colWidth > 0) {
   270         numColumns = (availContentWidth + colGap)/(colGap + colWidth);
   271         // The number of columns should never exceed kMaxColumnCount.
   272         numColumns = std::min(nscoord(nsStyleColumn::kMaxColumnCount),
   273                               numColumns);
   274       }
   275       if (numColumns <= 0) {
   276         numColumns = 1;
   277       }
   278     }
   280     // Compute extra space and divide it among the columns
   281     nscoord extraSpace =
   282       std::max(0, availContentWidth - (colWidth*numColumns + colGap*(numColumns - 1)));
   283     nscoord extraToColumns = extraSpace/numColumns;
   284     colWidth += extraToColumns;
   285     expectedWidthLeftOver = extraSpace - (extraToColumns*numColumns);
   286   }
   288   if (isBalancing) {
   289     if (numColumns <= 0) {
   290       // Hmm, auto column count, column width or available width is unknown,
   291       // and balancing is required. Let's just use one column then.
   292       numColumns = 1;
   293     }
   294     colHeight = std::min(mLastBalanceHeight, colHeight);
   295   } else {
   296     // This is the case when the column-fill property is set to 'auto'.
   297     // No balancing, so don't limit the column count
   298     numColumns = INT32_MAX;
   300     // XXX_jwir3: If a page's height is set to 0, we could continually
   301     //            create continuations, resulting in an infinite loop, since
   302     //            no progress is ever made. This is an issue with the spec
   303     //            (css3-multicol, css3-page, and css3-break) that is
   304     //            unresolved as of 27 Feb 2013. For the time being, we set this
   305     //            to have a minimum of 1 css px. Once a resolution is made
   306     //            on what minimum to have for a page height, we may need to
   307     //            change this value to match the appropriate spec(s).
   308     colHeight = std::max(colHeight, nsPresContext::CSSPixelsToAppUnits(1));
   309   }
   311 #ifdef DEBUG_roc
   312   printf("*** nsColumnSetFrame::ChooseColumnStrategy: numColumns=%d, colWidth=%d, expectedWidthLeftOver=%d, colHeight=%d, colGap=%d\n",
   313          numColumns, colWidth, expectedWidthLeftOver, colHeight, colGap);
   314 #endif
   315   ReflowConfig config = { numColumns, colWidth, expectedWidthLeftOver, colGap,
   316                           colHeight, isBalancing, knownFeasibleHeight,
   317                           knownInfeasibleHeight, computedHeight, consumedHeight };
   318   return config;
   319 }
   321 bool
   322 nsColumnSetFrame::ReflowColumns(nsHTMLReflowMetrics& aDesiredSize,
   323                                 const nsHTMLReflowState& aReflowState,
   324                                 nsReflowStatus& aReflowStatus,
   325                                 ReflowConfig& aConfig,
   326                                 bool aLastColumnUnbounded,
   327                                 nsCollapsingMargin* aCarriedOutBottomMargin,
   328                                 ColumnBalanceData& aColData)
   329 {
   330   bool feasible = ReflowChildren(aDesiredSize, aReflowState,
   331                                  aReflowStatus, aConfig, aLastColumnUnbounded,
   332                                  aCarriedOutBottomMargin, aColData);
   334   if (aColData.mHasExcessHeight) {
   335     aConfig = ChooseColumnStrategy(aReflowState, true);
   337     // We need to reflow our children again one last time, otherwise we might
   338     // end up with a stale column height for some of our columns, since we
   339     // bailed out of balancing.
   340     feasible = ReflowChildren(aDesiredSize, aReflowState, aReflowStatus,
   341                               aConfig, aLastColumnUnbounded,
   342                               aCarriedOutBottomMargin, aColData);
   343   }
   345   return feasible;
   346 }
   348 static void MoveChildTo(nsIFrame* aParent, nsIFrame* aChild, nsPoint aOrigin) {
   349   if (aChild->GetPosition() == aOrigin) {
   350     return;
   351   }
   353   aChild->SetPosition(aOrigin);
   354   nsContainerFrame::PlaceFrameView(aChild);
   355 }
   357 nscoord
   358 nsColumnSetFrame::GetMinWidth(nsRenderingContext *aRenderingContext) {
   359   nscoord width = 0;
   360   DISPLAY_MIN_WIDTH(this, width);
   361   if (mFrames.FirstChild()) {
   362     width = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
   363   }
   364   const nsStyleColumn* colStyle = StyleColumn();
   365   nscoord colWidth;
   366   if (colStyle->mColumnWidth.GetUnit() == eStyleUnit_Coord) {
   367     colWidth = colStyle->mColumnWidth.GetCoordValue();
   368     // As available width reduces to zero, we reduce our number of columns
   369     // to one, and don't enforce the column width, so just return the min
   370     // of the child's min-width with any specified column width.
   371     width = std::min(width, colWidth);
   372   } else {
   373     NS_ASSERTION(colStyle->mColumnCount > 0,
   374                  "column-count and column-width can't both be auto");
   375     // As available width reduces to zero, we still have mColumnCount columns,
   376     // so multiply the child's min-width by the number of columns.
   377     colWidth = width;
   378     width *= colStyle->mColumnCount;
   379     // The multiplication above can make 'width' negative (integer overflow),
   380     // so use std::max to protect against that.
   381     width = std::max(width, colWidth);
   382   }
   383   // XXX count forced column breaks here? Maybe we should return the child's
   384   // min-width times the minimum number of columns.
   385   return width;
   386 }
   388 nscoord
   389 nsColumnSetFrame::GetPrefWidth(nsRenderingContext *aRenderingContext) {
   390   // Our preferred width is our desired column width, if specified, otherwise
   391   // the child's preferred width, times the number of columns, plus the width
   392   // of any required column gaps
   393   // XXX what about forced column breaks here?
   394   nscoord result = 0;
   395   DISPLAY_PREF_WIDTH(this, result);
   396   const nsStyleColumn* colStyle = StyleColumn();
   397   nscoord colGap = GetColumnGap(this, colStyle);
   399   nscoord colWidth;
   400   if (colStyle->mColumnWidth.GetUnit() == eStyleUnit_Coord) {
   401     colWidth = colStyle->mColumnWidth.GetCoordValue();
   402   } else if (mFrames.FirstChild()) {
   403     colWidth = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
   404   } else {
   405     colWidth = 0;
   406   }
   408   int32_t numColumns = colStyle->mColumnCount;
   409   if (numColumns <= 0) {
   410     // if column-count is auto, assume one column
   411     numColumns = 1;
   412   }
   414   nscoord width = colWidth*numColumns + colGap*(numColumns - 1);
   415   // The multiplication above can make 'width' negative (integer overflow),
   416   // so use std::max to protect against that.
   417   result = std::max(width, colWidth);
   418   return result;
   419 }
   421 bool
   422 nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics&     aDesiredSize,
   423                                  const nsHTMLReflowState& aReflowState,
   424                                  nsReflowStatus&          aStatus,
   425                                  const ReflowConfig&      aConfig,
   426                                  bool                     aUnboundedLastColumn,
   427                                  nsCollapsingMargin*      aBottomMarginCarriedOut,
   428                                  ColumnBalanceData&       aColData)
   429 {
   430   aColData.Reset();
   431   bool allFit = true;
   432   bool RTL = StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
   433   bool shrinkingHeightOnly = !NS_SUBTREE_DIRTY(this) &&
   434     mLastBalanceHeight > aConfig.mColMaxHeight;
   436 #ifdef DEBUG_roc
   437   printf("*** Doing column reflow pass: mLastBalanceHeight=%d, mColMaxHeight=%d, RTL=%d\n, mBalanceColCount=%d, mColWidth=%d, mColGap=%d\n",
   438          mLastBalanceHeight, aConfig.mColMaxHeight, RTL, aConfig.mBalanceColCount,
   439          aConfig.mColWidth, aConfig.mColGap);
   440 #endif
   442   DrainOverflowColumns();
   444   const bool colHeightChanged = mLastBalanceHeight != aConfig.mColMaxHeight;
   446   if (colHeightChanged) {
   447     mLastBalanceHeight = aConfig.mColMaxHeight;
   448     // XXX Seems like this could fire if incremental reflow pushed the column set
   449     // down so we reflow incrementally with a different available height.
   450     // We need a way to do an incremental reflow and be sure availableHeight
   451     // changes are taken account of! Right now I think block frames with absolute
   452     // children might exit early.
   453     //NS_ASSERTION(aKidReason != eReflowReason_Incremental,
   454     //             "incremental reflow should not have changed the balance height");
   455   }
   457   // get our border and padding
   458   nsMargin borderPadding = aReflowState.ComputedPhysicalBorderPadding();
   459   ApplySkipSides(borderPadding, &aReflowState);
   461   nsRect contentRect(0, 0, 0, 0);
   462   nsOverflowAreas overflowRects;
   464   nsIFrame* child = mFrames.FirstChild();
   465   nsPoint childOrigin = nsPoint(borderPadding.left, borderPadding.top);
   466   // For RTL, figure out where the last column's left edge should be. Since the
   467   // columns might not fill the frame exactly, we need to account for the
   468   // slop. Otherwise we'll waste time moving the columns by some tiny
   469   // amount unnecessarily.
   470   if (RTL) {
   471     nscoord availWidth = aReflowState.AvailableWidth();
   472     if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) {
   473       availWidth = aReflowState.ComputedWidth();
   474     }
   475     if (availWidth != NS_INTRINSICSIZE) {
   476       childOrigin.x += availWidth - aConfig.mColWidth;
   477 #ifdef DEBUG_roc
   478       printf("*** childOrigin.x = %d\n", childOrigin.x);
   479 #endif
   480     }
   481   }
   482   int columnCount = 0;
   483   int contentBottom = 0;
   484   bool reflowNext = false;
   486   while (child) {
   487     // Try to skip reflowing the child. We can't skip if the child is dirty. We also can't
   488     // skip if the next column is dirty, because the next column's first line(s)
   489     // might be pullable back to this column. We can't skip if it's the last child
   490     // because we need to obtain the bottom margin. We can't skip
   491     // if this is the last column and we're supposed to assign unbounded
   492     // height to it, because that could change the available height from
   493     // the last time we reflowed it and we should try to pull all the
   494     // content from its next sibling. (Note that it might be the last
   495     // column, but not be the last child because the desired number of columns
   496     // has changed.)
   497     bool skipIncremental = !aReflowState.ShouldReflowAllKids()
   498       && !NS_SUBTREE_DIRTY(child)
   499       && child->GetNextSibling()
   500       && !(aUnboundedLastColumn && columnCount == aConfig.mBalanceColCount - 1)
   501       && !NS_SUBTREE_DIRTY(child->GetNextSibling());
   502     // If we need to pull up content from the prev-in-flow then this is not just
   503     // a height shrink. The prev in flow will have set the dirty bit.
   504     // Check the overflow rect YMost instead of just the child's content height. The child
   505     // may have overflowing content that cares about the available height boundary.
   506     // (It may also have overflowing content that doesn't care about the available height
   507     // boundary, but if so, too bad, this optimization is defeated.)
   508     // We want scrollable overflow here since this is a calculation that
   509     // affects layout.
   510     bool skipResizeHeightShrink = shrinkingHeightOnly
   511       && child->GetScrollableOverflowRect().YMost() <= aConfig.mColMaxHeight;
   513     nscoord childContentBottom = 0;
   514     if (!reflowNext && (skipIncremental || skipResizeHeightShrink)) {
   515       // This child does not need to be reflowed, but we may need to move it
   516       MoveChildTo(this, child, childOrigin);
   518       // If this is the last frame then make sure we get the right status
   519       nsIFrame* kidNext = child->GetNextSibling();
   520       if (kidNext) {
   521         aStatus = (kidNext->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)
   522                   ? NS_FRAME_OVERFLOW_INCOMPLETE
   523                   : NS_FRAME_NOT_COMPLETE;
   524       } else {
   525         aStatus = mLastFrameStatus;
   526       }
   527       childContentBottom = nsLayoutUtils::CalculateContentBottom(child);
   528 #ifdef DEBUG_roc
   529       printf("*** Skipping child #%d %p (incremental %d, resize height shrink %d): status = %d\n",
   530              columnCount, (void*)child, skipIncremental, skipResizeHeightShrink, aStatus);
   531 #endif
   532     } else {
   533       nsSize availSize(aConfig.mColWidth, aConfig.mColMaxHeight);
   535       if (aUnboundedLastColumn && columnCount == aConfig.mBalanceColCount - 1) {
   536         availSize.height = GetAvailableContentHeight(aReflowState);
   537       }
   539       if (reflowNext)
   540         child->AddStateBits(NS_FRAME_IS_DIRTY);
   542       nsHTMLReflowState kidReflowState(PresContext(), aReflowState, child,
   543                                        availSize, availSize.width,
   544                                        aReflowState.ComputedHeight());
   545       kidReflowState.mFlags.mIsTopOfPage = true;
   546       kidReflowState.mFlags.mTableIsSplittable = false;
   547       kidReflowState.mFlags.mIsColumnBalancing = aConfig.mBalanceColCount < INT32_MAX;
   549       // We need to reflow any float placeholders, even if our column height
   550       // hasn't changed.
   551       kidReflowState.mFlags.mMustReflowPlaceholders = !colHeightChanged;
   553 #ifdef DEBUG_roc
   554       printf("*** Reflowing child #%d %p: availHeight=%d\n",
   555              columnCount, (void*)child,availSize.height);
   556 #endif
   558       // Note if the column's next in flow is not being changed by this incremental reflow.
   559       // This may allow the current column to avoid trying to pull lines from the next column.
   560       if (child->GetNextSibling() &&
   561           !(GetStateBits() & NS_FRAME_IS_DIRTY) &&
   562         !(child->GetNextSibling()->GetStateBits() & NS_FRAME_IS_DIRTY)) {
   563         kidReflowState.mFlags.mNextInFlowUntouched = true;
   564       }
   566       nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode(),
   567                                          aDesiredSize.mFlags);
   569       // XXX it would be cool to consult the float manager for the
   570       // previous block to figure out the region of floats from the
   571       // previous column that extend into this column, and subtract
   572       // that region from the new float manager.  So you could stick a
   573       // really big float in the first column and text in following
   574       // columns would flow around it.
   576       // Reflow the frame
   577       ReflowChild(child, PresContext(), kidDesiredSize, kidReflowState,
   578                   childOrigin.x + kidReflowState.ComputedPhysicalMargin().left,
   579                   childOrigin.y + kidReflowState.ComputedPhysicalMargin().top,
   580                   0, aStatus);
   582       reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0;
   584 #ifdef DEBUG_roc
   585       printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d CarriedOutBottomMargin=%d\n",
   586              columnCount, (void*)child, aStatus, kidDesiredSize.Width(), kidDesiredSize.Height(),
   587              kidDesiredSize.mCarriedOutBottomMargin.get());
   588 #endif
   590       NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus);
   592       *aBottomMarginCarriedOut = kidDesiredSize.mCarriedOutBottomMargin;
   594       FinishReflowChild(child, PresContext(), kidDesiredSize,
   595                         &kidReflowState, childOrigin.x, childOrigin.y, 0);
   597       childContentBottom = nsLayoutUtils::CalculateContentBottom(child);
   598       if (childContentBottom > aConfig.mColMaxHeight) {
   599         allFit = false;
   600       }
   601       if (childContentBottom > availSize.height) {
   602         aColData.mMaxOverflowingHeight = std::max(childContentBottom,
   603             aColData.mMaxOverflowingHeight);
   604       }
   605     }
   607     contentRect.UnionRect(contentRect, child->GetRect());
   609     ConsiderChildOverflow(overflowRects, child);
   610     contentBottom = std::max(contentBottom, childContentBottom);
   611     aColData.mLastHeight = childContentBottom;
   612     aColData.mSumHeight += childContentBottom;
   614     // Build a continuation column if necessary
   615     nsIFrame* kidNextInFlow = child->GetNextInFlow();
   617     if (NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus)) {
   618       NS_ASSERTION(!kidNextInFlow, "next in flow should have been deleted");
   619       child = nullptr;
   620       break;
   621     } else {
   622       ++columnCount;
   623       // Make sure that the column has a next-in-flow. If not, we must
   624       // create one to hold the overflowing stuff, even if we're just
   625       // going to put it on our overflow list and let *our*
   626       // next in flow handle it.
   627       if (!kidNextInFlow) {
   628         NS_ASSERTION(aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
   629                      "We have to create a continuation, but the block doesn't want us to reflow it?");
   631         // We need to create a continuing column
   632         nsresult rv = CreateNextInFlow(child, kidNextInFlow);
   634         if (NS_FAILED(rv)) {
   635           NS_NOTREACHED("Couldn't create continuation");
   636           child = nullptr;
   637           break;
   638         }
   639       }
   641       // Make sure we reflow a next-in-flow when it switches between being
   642       // normal or overflow container
   643       if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
   644         if (!(kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
   645           aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
   646           reflowNext = true;
   647           kidNextInFlow->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
   648         }
   649       }
   650       else if (kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
   651         aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
   652         reflowNext = true;
   653         kidNextInFlow->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
   654       }
   656       if ((contentBottom > aReflowState.ComputedMaxHeight() ||
   657            contentBottom > aReflowState.ComputedHeight()) &&
   658            aConfig.mBalanceColCount < INT32_MAX) {
   659         // We overflowed vertically, but have not exceeded the number of
   660         // columns. We're going to go into overflow columns now, so balancing
   661         // no longer applies.
   662         aColData.mHasExcessHeight = true;
   663       }
   665       if (columnCount >= aConfig.mBalanceColCount) {
   666         // No more columns allowed here. Stop.
   667         aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
   668         kidNextInFlow->AddStateBits(NS_FRAME_IS_DIRTY);
   669         // Move any of our leftover columns to our overflow list. Our
   670         // next-in-flow will eventually pick them up.
   671         const nsFrameList& continuationColumns = mFrames.RemoveFramesAfter(child);
   672         if (continuationColumns.NotEmpty()) {
   673           SetOverflowFrames(continuationColumns);
   674         }
   675         child = nullptr;
   676         break;
   677       }
   678     }
   680     if (PresContext()->HasPendingInterrupt()) {
   681       // Stop the loop now while |child| still points to the frame that bailed
   682       // out.  We could keep going here and condition a bunch of the code in
   683       // this loop on whether there's an interrupt, or even just keep going and
   684       // trying to reflow the blocks (even though we know they'll interrupt
   685       // right after their first line), but stopping now is conceptually the
   686       // simplest (and probably fastest) thing.
   687       break;
   688     }
   690     // Advance to the next column
   691     child = child->GetNextSibling();
   693     if (child) {
   694       if (!RTL) {
   695         childOrigin.x += aConfig.mColWidth + aConfig.mColGap;
   696       } else {
   697         childOrigin.x -= aConfig.mColWidth + aConfig.mColGap;
   698       }
   700 #ifdef DEBUG_roc
   701       printf("*** NEXT CHILD ORIGIN.x = %d\n", childOrigin.x);
   702 #endif
   703     }
   704   }
   706   if (PresContext()->CheckForInterrupt(this) &&
   707       (GetStateBits() & NS_FRAME_IS_DIRTY)) {
   708     // Mark all our kids starting with |child| dirty
   710     // Note that this is a CheckForInterrupt call, not a HasPendingInterrupt,
   711     // because we might have interrupted while reflowing |child|, and since
   712     // we're about to add a dirty bit to |child| we need to make sure that
   713     // |this| is scheduled to have dirty bits marked on it and its ancestors.
   714     // Otherwise, when we go to mark dirty bits on |child|'s ancestors we'll
   715     // bail out immediately, since it'll already have a dirty bit.
   716     for (; child; child = child->GetNextSibling()) {
   717       child->AddStateBits(NS_FRAME_IS_DIRTY);
   718     }
   719   }
   721   aColData.mMaxHeight = contentBottom;
   722   contentRect.height = std::max(contentRect.height, contentBottom);
   723   mLastFrameStatus = aStatus;
   725   // contentRect included the borderPadding.left,borderPadding.top of the child rects
   726   contentRect -= nsPoint(borderPadding.left, borderPadding.top);
   728   nsSize contentSize = nsSize(contentRect.XMost(), contentRect.YMost());
   730   // Apply computed and min/max values
   731   if (aConfig.mComputedHeight != NS_INTRINSICSIZE) {
   732     if (aReflowState.AvailableHeight() != NS_INTRINSICSIZE) {
   733       contentSize.height = std::min(contentSize.height,
   734                                     aConfig.mComputedHeight);
   735     } else {
   736       contentSize.height = aConfig.mComputedHeight;
   737     }
   738   } else {
   739     // We add the "consumed" height back in so that we're applying
   740     // constraints to the correct height value, then subtract it again
   741     // after we've finished with the min/max calculation. This prevents us from
   742     // having a last continuation that is smaller than the min height. but which
   743     // has prev-in-flows, trigger a larger height than actually required.
   744     contentSize.height = aReflowState.ApplyMinMaxHeight(contentSize.height,
   745                                                         aConfig.mConsumedHeight);
   746   }
   747   if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) {
   748     contentSize.width = aReflowState.ComputedWidth();
   749   } else {
   750     contentSize.width = aReflowState.ApplyMinMaxWidth(contentSize.width);
   751   }
   753   aDesiredSize.Height() = contentSize.height +
   754                         borderPadding.TopBottom();
   755   aDesiredSize.Width() = contentSize.width +
   756                        borderPadding.LeftRight();
   757   aDesiredSize.mOverflowAreas = overflowRects;
   758   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
   760 #ifdef DEBUG_roc
   761   printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
   762          && !NS_FRAME_IS_TRUNCATED(aStatus));
   763 #endif
   764   return allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
   765     && !NS_FRAME_IS_TRUNCATED(aStatus);
   766 }
   768 void
   769 nsColumnSetFrame::DrainOverflowColumns()
   770 {
   771   // First grab the prev-in-flows overflows and reparent them to this
   772   // frame.
   773   nsPresContext* presContext = PresContext();
   774   nsColumnSetFrame* prev = static_cast<nsColumnSetFrame*>(GetPrevInFlow());
   775   if (prev) {
   776     AutoFrameListPtr overflows(presContext, prev->StealOverflowFrames());
   777     if (overflows) {
   778       nsContainerFrame::ReparentFrameViewList(*overflows, prev, this);
   780       mFrames.InsertFrames(this, nullptr, *overflows);
   781     }
   782   }
   784   // Now pull back our own overflows and append them to our children.
   785   // We don't need to reparent them since we're already their parent.
   786   AutoFrameListPtr overflows(presContext, StealOverflowFrames());
   787   if (overflows) {
   788     // We're already the parent for these frames, so no need to set
   789     // their parent again.
   790     mFrames.AppendFrames(nullptr, *overflows);
   791   }
   792 }
   794 void
   795 nsColumnSetFrame::FindBestBalanceHeight(const nsHTMLReflowState& aReflowState,
   796                                         nsPresContext* aPresContext,
   797                                         ReflowConfig& aConfig,
   798                                         ColumnBalanceData& aColData,
   799                                         nsHTMLReflowMetrics& aDesiredSize,
   800                                         nsCollapsingMargin& aOutMargin,
   801                                         bool& aUnboundedLastColumn,
   802                                         bool& aRunWasFeasible,
   803                                         nsReflowStatus& aStatus)
   804 {
   805   bool feasible = aRunWasFeasible;
   807   nsMargin bp = aReflowState.ComputedPhysicalBorderPadding();
   808   ApplySkipSides(bp);
   809   bp.bottom = aReflowState.ComputedPhysicalBorderPadding().bottom;
   811   nscoord availableContentHeight =
   812     GetAvailableContentHeight(aReflowState);
   814   // Termination of the algorithm below is guaranteed because
   815   // aConfig.knownFeasibleHeight - aConfig.knownInfeasibleHeight decreases in every
   816   // iteration.
   818   // We set this flag when we detect that we may contain a frame
   819   // that can break anywhere (thus foiling the linear decrease-by-one
   820   // search)
   821   bool maybeContinuousBreakingDetected = false;
   823   while (!aPresContext->HasPendingInterrupt()) {
   824     nscoord lastKnownFeasibleHeight = aConfig.mKnownFeasibleHeight;
   826     // Record what we learned from the last reflow
   827     if (feasible) {
   828       // maxHeight is feasible. Also, mLastBalanceHeight is feasible.
   829       aConfig.mKnownFeasibleHeight = std::min(aConfig.mKnownFeasibleHeight,
   830                                               aColData.mMaxHeight);
   831       aConfig.mKnownFeasibleHeight = std::min(aConfig.mKnownFeasibleHeight,
   832                                               mLastBalanceHeight);
   834       // Furthermore, no height less than the height of the last
   835       // column can ever be feasible. (We might be able to reduce the
   836       // height of a non-last column by moving content to a later column,
   837       // but we can't do that with the last column.)
   838       if (mFrames.GetLength() == aConfig.mBalanceColCount) {
   839         aConfig.mKnownInfeasibleHeight = std::max(aConfig.mKnownInfeasibleHeight,
   840                                        aColData.mLastHeight - 1);
   841       }
   842     } else {
   843       aConfig.mKnownInfeasibleHeight = std::max(aConfig.mKnownInfeasibleHeight,
   844                                                 mLastBalanceHeight);
   845       // If a column didn't fit in its available height, then its current
   846       // height must be the minimum height for unbreakable content in
   847       // the column, and therefore no smaller height can be feasible.
   848       aConfig.mKnownInfeasibleHeight = std::max(aConfig.mKnownInfeasibleHeight,
   849                                          aColData.mMaxOverflowingHeight - 1);
   851       if (aUnboundedLastColumn) {
   852         // The last column is unbounded, so all content got reflowed, so the
   853         // mColMaxHeight is feasible.
   854         aConfig.mKnownFeasibleHeight = std::min(aConfig.mKnownFeasibleHeight,
   855                                                 aColData.mMaxHeight);
   856       }
   857     }
   859 #ifdef DEBUG_roc
   860     printf("*** nsColumnSetFrame::Reflow balancing knownInfeasible=%d knownFeasible=%d\n",
   861            aConfig.mKnownInfeasibleHeight, aConfig.mKnownFeasibleHeight);
   862 #endif
   865     if (aConfig.mKnownInfeasibleHeight >= aConfig.mKnownFeasibleHeight - 1) {
   866       // aConfig.mKnownFeasibleHeight is where we want to be
   867       break;
   868     }
   870     if (aConfig.mKnownInfeasibleHeight >= availableContentHeight) {
   871       break;
   872     }
   874     if (lastKnownFeasibleHeight - aConfig.mKnownFeasibleHeight == 1) {
   875       // We decreased the feasible height by one twip only. This could
   876       // indicate that there is a continuously breakable child frame
   877       // that we are crawling through.
   878       maybeContinuousBreakingDetected = true;
   879     }
   881     nscoord nextGuess = (aConfig.mKnownFeasibleHeight + aConfig.mKnownInfeasibleHeight)/2;
   882     // The constant of 600 twips is arbitrary. It's about two line-heights.
   883     if (aConfig.mKnownFeasibleHeight - nextGuess < 600 &&
   884         !maybeContinuousBreakingDetected) {
   885       // We're close to our target, so just try shrinking just the
   886       // minimum amount that will cause one of our columns to break
   887       // differently.
   888       nextGuess = aConfig.mKnownFeasibleHeight - 1;
   889     } else if (aUnboundedLastColumn) {
   890       // Make a guess by dividing that into N columns. Add some slop
   891       // to try to make it on the feasible side.  The constant of
   892       // 600 twips is arbitrary. It's about two line-heights.
   893       nextGuess = aColData.mSumHeight/aConfig.mBalanceColCount + 600;
   894       // Sanitize it
   895       nextGuess = clamped(nextGuess, aConfig.mKnownInfeasibleHeight + 1,
   896                                      aConfig.mKnownFeasibleHeight - 1);
   897     } else if (aConfig.mKnownFeasibleHeight == NS_INTRINSICSIZE) {
   898       // This can happen when we had a next-in-flow so we didn't
   899       // want to do an unbounded height measuring step. Let's just increase
   900       // from the infeasible height by some reasonable amount.
   901       nextGuess = aConfig.mKnownInfeasibleHeight*2 + 600;
   902     }
   903     // Don't bother guessing more than our height constraint.
   904     nextGuess = std::min(availableContentHeight, nextGuess);
   906 #ifdef DEBUG_roc
   907     printf("*** nsColumnSetFrame::Reflow balancing choosing next guess=%d\n", nextGuess);
   908 #endif
   910     aConfig.mColMaxHeight = nextGuess;
   912     aUnboundedLastColumn = false;
   913     AddStateBits(NS_FRAME_IS_DIRTY);
   914     feasible = ReflowColumns(aDesiredSize, aReflowState, aStatus, aConfig, false,
   915                              &aOutMargin, aColData);
   917     if (!aConfig.mIsBalancing) {
   918       // Looks like we had excess height when balancing, so we gave up on
   919       // trying to balance.
   920       break;
   921     }
   922   }
   924   if (aConfig.mIsBalancing && !feasible &&
   925       !aPresContext->HasPendingInterrupt()) {
   926     // We may need to reflow one more time at the feasible height to
   927     // get a valid layout.
   928     bool skip = false;
   929     if (aConfig.mKnownInfeasibleHeight >= availableContentHeight) {
   930       aConfig.mColMaxHeight = availableContentHeight;
   931       if (mLastBalanceHeight == availableContentHeight) {
   932         skip = true;
   933       }
   934     } else {
   935       aConfig.mColMaxHeight = aConfig.mKnownFeasibleHeight;
   936     }
   937     if (!skip) {
   938       // If our height is unconstrained, make sure that the last column is
   939       // allowed to have arbitrary height here, even though we were balancing.
   940       // Otherwise we'd have to split, and it's not clear what we'd do with
   941       // that.
   942       AddStateBits(NS_FRAME_IS_DIRTY);
   943       feasible = ReflowColumns(aDesiredSize, aReflowState, aStatus, aConfig,
   944                                availableContentHeight == NS_UNCONSTRAINEDSIZE,
   945                                &aOutMargin, aColData);
   946     }
   947   }
   949   aRunWasFeasible = feasible;
   950 }
   952 nsresult 
   953 nsColumnSetFrame::Reflow(nsPresContext*           aPresContext,
   954                          nsHTMLReflowMetrics&     aDesiredSize,
   955                          const nsHTMLReflowState& aReflowState,
   956                          nsReflowStatus&          aStatus)
   957 {
   958   // Don't support interruption in columns
   959   nsPresContext::InterruptPreventer noInterrupts(aPresContext);
   961   DO_GLOBAL_REFLOW_COUNT("nsColumnSetFrame");
   962   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   964   // Initialize OUT parameter
   965   aStatus = NS_FRAME_COMPLETE;
   967   // Our children depend on our height if we have a fixed height.
   968   if (aReflowState.ComputedHeight() != NS_AUTOHEIGHT) {
   969     NS_ASSERTION(aReflowState.ComputedHeight() != NS_INTRINSICSIZE,
   970                  "Unexpected computed height");
   971     AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
   972   }
   973   else {
   974     RemoveStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
   975   }
   977   //------------ Handle Incremental Reflow -----------------
   979   ReflowConfig config = ChooseColumnStrategy(aReflowState);
   981   // If balancing, then we allow the last column to grow to unbounded
   982   // height during the first reflow. This gives us a way to estimate
   983   // what the average column height should be, because we can measure
   984   // the heights of all the columns and sum them up. But don't do this
   985   // if we have a next in flow because we don't want to suck all its
   986   // content back here and then have to push it out again!
   987   nsIFrame* nextInFlow = GetNextInFlow();
   988   bool unboundedLastColumn = config.mIsBalancing && !nextInFlow;
   989   nsCollapsingMargin carriedOutBottomMargin;
   990   ColumnBalanceData colData;
   991   colData.mHasExcessHeight = false;
   993   bool feasible = ReflowColumns(aDesiredSize, aReflowState, aStatus, config,
   994                                 unboundedLastColumn, &carriedOutBottomMargin,
   995                                 colData);
   997   // If we're not balancing, then we're already done, since we should have
   998   // reflown all of our children, and there is no need for a binary search to
   999   // determine proper column height.
  1000   if (config.mIsBalancing && !aPresContext->HasPendingInterrupt()) {
  1001     FindBestBalanceHeight(aReflowState, aPresContext, config, colData,
  1002                           aDesiredSize, carriedOutBottomMargin,
  1003                           unboundedLastColumn, feasible, aStatus);
  1006   if (aPresContext->HasPendingInterrupt() &&
  1007       aReflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE) {
  1008     // In this situation, we might be lying about our reflow status, because
  1009     // our last kid (the one that got interrupted) was incomplete.  Fix that.
  1010     aStatus = NS_FRAME_COMPLETE;
  1013   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, false);
  1015   aDesiredSize.mCarriedOutBottomMargin = carriedOutBottomMargin;
  1017   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
  1019   NS_ASSERTION(NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
  1020                aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE,
  1021                "Column set should be complete if the available height is unconstrained");
  1023   return NS_OK;
  1026 void
  1027 nsColumnSetFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
  1028                                    const nsRect&           aDirtyRect,
  1029                                    const nsDisplayListSet& aLists) {
  1030   DisplayBorderBackgroundOutline(aBuilder, aLists);
  1032   if (IsVisibleForPainting(aBuilder)) {
  1033     aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
  1034       nsDisplayGenericOverflow(aBuilder, this, ::PaintColumnRule, "ColumnRule",
  1035                                nsDisplayItem::TYPE_COLUMN_RULE));
  1038   // Our children won't have backgrounds so it doesn't matter where we put them.
  1039   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
  1040     BuildDisplayListForChild(aBuilder, e.get(), aDirtyRect, aLists);
  1044 nsresult
  1045 nsColumnSetFrame::AppendFrames(ChildListID     aListID,
  1046                                nsFrameList&    aFrameList)
  1048   if (aListID == kAbsoluteList) {
  1049     return nsContainerFrame::AppendFrames(aListID, aFrameList);
  1052   NS_ERROR("unexpected child list");
  1053   return NS_ERROR_INVALID_ARG;
  1056 nsresult
  1057 nsColumnSetFrame::InsertFrames(ChildListID     aListID,
  1058                                nsIFrame*       aPrevFrame,
  1059                                nsFrameList&    aFrameList)
  1061   if (aListID == kAbsoluteList) {
  1062     return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
  1065   NS_ERROR("unexpected child list");
  1066   return NS_ERROR_INVALID_ARG;
  1069 nsresult
  1070 nsColumnSetFrame::RemoveFrame(ChildListID     aListID,
  1071                               nsIFrame*       aOldFrame)
  1073   if (aListID == kAbsoluteList) {
  1074     return nsContainerFrame::RemoveFrame(aListID, aOldFrame);
  1077   NS_ERROR("unexpected child list");
  1078   return NS_ERROR_INVALID_ARG;

mercurial