LCOV - code coverage report
Current view: top level - layout/tables - nsTableRowFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 702 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 50 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "mozilla/Maybe.h"
       7             : 
       8             : #include "nsTableRowFrame.h"
       9             : #include "nsTableRowGroupFrame.h"
      10             : #include "nsIPresShell.h"
      11             : #include "nsPresContext.h"
      12             : #include "nsStyleContext.h"
      13             : #include "nsStyleConsts.h"
      14             : #include "nsGkAtoms.h"
      15             : #include "nsIContent.h"
      16             : #include "nsTableFrame.h"
      17             : #include "nsTableCellFrame.h"
      18             : #include "nsCSSRendering.h"
      19             : #include "nsHTMLParts.h"
      20             : #include "nsTableColGroupFrame.h"
      21             : #include "nsTableColFrame.h"
      22             : #include "nsCOMPtr.h"
      23             : #include "nsDisplayList.h"
      24             : #include "nsIFrameInlines.h"
      25             : #include <algorithm>
      26             : 
      27             : using namespace mozilla;
      28             : 
      29             : namespace mozilla {
      30             : 
      31             : struct TableCellReflowInput : public ReflowInput
      32             : {
      33           0 :   TableCellReflowInput(nsPresContext*           aPresContext,
      34             :                          const ReflowInput& aParentReflowInput,
      35             :                          nsIFrame*                aFrame,
      36             :                          const LogicalSize&       aAvailableSpace,
      37             :                          uint32_t                 aFlags = 0)
      38           0 :     : ReflowInput(aPresContext, aParentReflowInput, aFrame,
      39           0 :                         aAvailableSpace, nullptr, aFlags)
      40             :   {
      41           0 :   }
      42             : 
      43             :   void FixUp(const LogicalSize& aAvailSpace);
      44             : };
      45             : 
      46             : } // namespace mozilla
      47             : 
      48           0 : void TableCellReflowInput::FixUp(const LogicalSize& aAvailSpace)
      49             : {
      50             :   // fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
      51           0 :   NS_WARNING_ASSERTION(
      52             :     NS_UNCONSTRAINEDSIZE != aAvailSpace.ISize(mWritingMode),
      53             :     "have unconstrained inline-size; this should only result from very large "
      54             :     "sizes, not attempts at intrinsic inline size calculation");
      55           0 :   if (NS_UNCONSTRAINEDSIZE != ComputedISize()) {
      56           0 :     nscoord computedISize = aAvailSpace.ISize(mWritingMode) -
      57           0 :       ComputedLogicalBorderPadding().IStartEnd(mWritingMode);
      58           0 :     computedISize = std::max(0, computedISize);
      59           0 :     SetComputedISize(computedISize);
      60             :   }
      61           0 :   if (NS_UNCONSTRAINEDSIZE != ComputedBSize() &&
      62           0 :       NS_UNCONSTRAINEDSIZE != aAvailSpace.BSize(mWritingMode)) {
      63           0 :     nscoord computedBSize = aAvailSpace.BSize(mWritingMode) -
      64           0 :       ComputedLogicalBorderPadding().BStartEnd(mWritingMode);
      65           0 :     computedBSize = std::max(0, computedBSize);
      66           0 :     SetComputedBSize(computedBSize);
      67             :   }
      68           0 : }
      69             : 
      70             : void
      71           0 : nsTableRowFrame::InitChildReflowInput(nsPresContext&          aPresContext,
      72             :                                       const LogicalSize&      aAvailSize,
      73             :                                       bool                    aBorderCollapse,
      74             :                                       TableCellReflowInput& aReflowInput)
      75             : {
      76           0 :   nsMargin collapseBorder;
      77           0 :   nsMargin* pCollapseBorder = nullptr;
      78           0 :   if (aBorderCollapse) {
      79             :     // we only reflow cells, so don't need to check frame type
      80           0 :     nsBCTableCellFrame* bcCellFrame = (nsBCTableCellFrame*)aReflowInput.mFrame;
      81           0 :     if (bcCellFrame) {
      82           0 :       WritingMode wm = GetWritingMode();
      83           0 :       collapseBorder = bcCellFrame->GetBorderWidth(wm).GetPhysicalMargin(wm);
      84           0 :       pCollapseBorder = &collapseBorder;
      85             :     }
      86             :   }
      87           0 :   aReflowInput.Init(&aPresContext, nullptr, pCollapseBorder);
      88           0 :   aReflowInput.FixUp(aAvailSize);
      89           0 : }
      90             : 
      91             : void
      92           0 : nsTableRowFrame::SetFixedBSize(nscoord aValue)
      93             : {
      94           0 :   nscoord bsize = std::max(0, aValue);
      95           0 :   if (HasFixedBSize()) {
      96           0 :     if (bsize > mStyleFixedBSize) {
      97           0 :       mStyleFixedBSize = bsize;
      98             :     }
      99             :   }
     100             :   else {
     101           0 :     mStyleFixedBSize = bsize;
     102           0 :     if (bsize > 0) {
     103           0 :       SetHasFixedBSize(true);
     104             :     }
     105             :   }
     106           0 : }
     107             : 
     108             : void
     109           0 : nsTableRowFrame::SetPctBSize(float aPctValue,
     110             :                              bool  aForce)
     111             : {
     112           0 :   nscoord bsize = std::max(0, NSToCoordRound(aPctValue * 100.0f));
     113           0 :   if (HasPctBSize()) {
     114           0 :     if ((bsize > mStylePctBSize) || aForce) {
     115           0 :       mStylePctBSize = bsize;
     116             :     }
     117             :   }
     118             :   else {
     119           0 :     mStylePctBSize = bsize;
     120           0 :     if (bsize > 0) {
     121           0 :       SetHasPctBSize(true);
     122             :     }
     123             :   }
     124           0 : }
     125             : 
     126             : /* ----------- nsTableRowFrame ---------- */
     127             : 
     128           0 : NS_QUERYFRAME_HEAD(nsTableRowFrame)
     129           0 :   NS_QUERYFRAME_ENTRY(nsTableRowFrame)
     130           0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
     131             : 
     132           0 : nsTableRowFrame::nsTableRowFrame(nsStyleContext* aContext, ClassID aID)
     133             :   : nsContainerFrame(aContext, aID)
     134             :   , mContentBSize(0)
     135             :   , mStylePctBSize(0)
     136             :   , mStyleFixedBSize(0)
     137             :   , mMaxCellAscent(0)
     138             :   , mMaxCellDescent(0)
     139             :   , mBStartBorderWidth(0)
     140             :   , mBEndBorderWidth(0)
     141             :   , mIEndContBorderWidth(0)
     142             :   , mBStartContBorderWidth(0)
     143           0 :   , mIStartContBorderWidth(0)
     144             : {
     145           0 :   mBits.mRowIndex = 0;
     146           0 :   mBits.mHasFixedBSize = 0;
     147           0 :   mBits.mHasPctBSize = 0;
     148           0 :   mBits.mFirstInserted = 0;
     149           0 :   ResetBSize(0);
     150           0 : }
     151             : 
     152           0 : nsTableRowFrame::~nsTableRowFrame()
     153             : {
     154           0 : }
     155             : 
     156             : void
     157           0 : nsTableRowFrame::Init(nsIContent*       aContent,
     158             :                       nsContainerFrame* aParent,
     159             :                       nsIFrame*         aPrevInFlow)
     160             : {
     161             :   // Let the base class do its initialization
     162           0 :   nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
     163             : 
     164           0 :   NS_ASSERTION(mozilla::StyleDisplay::TableRow == StyleDisplay()->mDisplay,
     165             :                "wrong display on table row frame");
     166             : 
     167           0 :   if (aPrevInFlow) {
     168             :     // Set the row index
     169           0 :     nsTableRowFrame* rowFrame = (nsTableRowFrame*)aPrevInFlow;
     170             : 
     171           0 :     SetRowIndex(rowFrame->GetRowIndex());
     172             :   } else {
     173           0 :     mWritingMode = GetTableFrame()->GetWritingMode();
     174             :   }
     175           0 : }
     176             : 
     177             : void
     178           0 : nsTableRowFrame::DestroyFrom(nsIFrame* aDestructRoot)
     179             : {
     180           0 :   if (HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
     181           0 :     nsTableFrame::UnregisterPositionedTablePart(this, aDestructRoot);
     182             :   }
     183             : 
     184           0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     185           0 : }
     186             : 
     187             : /* virtual */ void
     188           0 : nsTableRowFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     189             : {
     190           0 :   nsContainerFrame::DidSetStyleContext(aOldStyleContext);
     191             : 
     192           0 :   if (!aOldStyleContext) //avoid this on init
     193           0 :     return;
     194             : 
     195           0 :   nsTableFrame* tableFrame = GetTableFrame();
     196           0 :   if (tableFrame->IsBorderCollapse() &&
     197           0 :       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
     198           0 :     TableArea damageArea(0, GetRowIndex(), tableFrame->GetColCount(), 1);
     199           0 :     tableFrame->AddBCDamageArea(damageArea);
     200             :   }
     201             : }
     202             : 
     203             : void
     204           0 : nsTableRowFrame::AppendFrames(ChildListID  aListID,
     205             :                               nsFrameList& aFrameList)
     206             : {
     207           0 :   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
     208             : 
     209           0 :   DrainSelfOverflowList(); // ensure the last frame is in mFrames
     210           0 :   const nsFrameList::Slice& newCells = mFrames.AppendFrames(nullptr, aFrameList);
     211             : 
     212             :   // Add the new cell frames to the table
     213           0 :   nsTableFrame* tableFrame = GetTableFrame();
     214           0 :   for (nsFrameList::Enumerator e(newCells) ; !e.AtEnd(); e.Next()) {
     215           0 :     nsIFrame *childFrame = e.get();
     216           0 :     NS_ASSERTION(IS_TABLE_CELL(childFrame->Type()),
     217             :                  "Not a table cell frame/pseudo frame construction failure");
     218           0 :     tableFrame->AppendCell(static_cast<nsTableCellFrame&>(*childFrame), GetRowIndex());
     219             :   }
     220             : 
     221           0 :   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     222           0 :                                                NS_FRAME_HAS_DIRTY_CHILDREN);
     223           0 :   tableFrame->SetGeometryDirty();
     224           0 : }
     225             : 
     226             : 
     227             : void
     228           0 : nsTableRowFrame::InsertFrames(ChildListID  aListID,
     229             :                               nsIFrame*    aPrevFrame,
     230             :                               nsFrameList& aFrameList)
     231             : {
     232           0 :   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
     233           0 :   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
     234             :                "inserting after sibling frame with different parent");
     235           0 :   DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
     236             :   //Insert Frames in the frame list
     237           0 :   const nsFrameList::Slice& newCells = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
     238             : 
     239             :   // Get the table frame
     240           0 :   nsTableFrame* tableFrame = GetTableFrame();
     241           0 :   LayoutFrameType cellFrameType = tableFrame->IsBorderCollapse()
     242           0 :       ? LayoutFrameType::BCTableCell : LayoutFrameType::TableCell;
     243           0 :   nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, cellFrameType);
     244           0 :   nsTArray<nsTableCellFrame*> cellChildren;
     245           0 :   for (nsFrameList::Enumerator e(newCells); !e.AtEnd(); e.Next()) {
     246           0 :     nsIFrame *childFrame = e.get();
     247           0 :     NS_ASSERTION(IS_TABLE_CELL(childFrame->Type()),
     248             :                  "Not a table cell frame/pseudo frame construction failure");
     249           0 :     cellChildren.AppendElement(static_cast<nsTableCellFrame*>(childFrame));
     250             :   }
     251             :   // insert the cells into the cell map
     252           0 :   int32_t colIndex = -1;
     253           0 :   if (prevCellFrame) {
     254           0 :     prevCellFrame->GetColIndex(colIndex);
     255             :   }
     256           0 :   tableFrame->InsertCells(cellChildren, GetRowIndex(), colIndex);
     257             : 
     258           0 :   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     259           0 :                                                NS_FRAME_HAS_DIRTY_CHILDREN);
     260           0 :   tableFrame->SetGeometryDirty();
     261           0 : }
     262             : 
     263             : void
     264           0 : nsTableRowFrame::RemoveFrame(ChildListID aListID,
     265             :                              nsIFrame*   aOldFrame)
     266             : {
     267           0 :   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
     268             : 
     269           0 :   MOZ_ASSERT((nsTableCellFrame*)do_QueryFrame(aOldFrame));
     270           0 :   nsTableCellFrame* cellFrame = static_cast<nsTableCellFrame*>(aOldFrame);
     271             :   // remove the cell from the cell map
     272           0 :   nsTableFrame* tableFrame = GetTableFrame();
     273           0 :   tableFrame->RemoveCell(cellFrame, GetRowIndex());
     274             : 
     275             :   // Remove the frame and destroy it
     276           0 :   mFrames.DestroyFrame(aOldFrame);
     277             : 
     278           0 :   PresContext()->PresShell()->
     279           0 :     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     280           0 :                      NS_FRAME_HAS_DIRTY_CHILDREN);
     281             : 
     282           0 :   tableFrame->SetGeometryDirty();
     283           0 : }
     284             : 
     285             : /* virtual */ nsMargin
     286           0 : nsTableRowFrame::GetUsedMargin() const
     287             : {
     288           0 :   return nsMargin(0,0,0,0);
     289             : }
     290             : 
     291             : /* virtual */ nsMargin
     292           0 : nsTableRowFrame::GetUsedBorder() const
     293             : {
     294           0 :   return nsMargin(0,0,0,0);
     295             : }
     296             : 
     297             : /* virtual */ nsMargin
     298           0 : nsTableRowFrame::GetUsedPadding() const
     299             : {
     300           0 :   return nsMargin(0,0,0,0);
     301             : }
     302             : 
     303             : nscoord
     304           0 : GetBSizeOfRowsSpannedBelowFirst(nsTableCellFrame& aTableCellFrame,
     305             :                                 nsTableFrame&     aTableFrame,
     306             :                                 const WritingMode aWM)
     307             : {
     308           0 :   nscoord bsize = 0;
     309           0 :   int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(aTableCellFrame);
     310             :   // add in bsize of rows spanned beyond the 1st one
     311           0 :   nsIFrame* nextRow = aTableCellFrame.GetParent()->GetNextSibling();
     312           0 :   for (int32_t rowX = 1; ((rowX < rowSpan) && nextRow);) {
     313           0 :     if (nextRow->IsTableRowFrame()) {
     314           0 :       bsize += nextRow->BSize(aWM);
     315           0 :       rowX++;
     316             :     }
     317           0 :     bsize += aTableFrame.GetRowSpacing(rowX);
     318           0 :     nextRow = nextRow->GetNextSibling();
     319             :   }
     320           0 :   return bsize;
     321             : }
     322             : 
     323             : nsTableCellFrame*
     324           0 : nsTableRowFrame::GetFirstCell()
     325             : {
     326           0 :   for (nsIFrame* childFrame : mFrames) {
     327           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
     328           0 :     if (cellFrame) {
     329           0 :       return cellFrame;
     330             :     }
     331             :   }
     332           0 :   return nullptr;
     333             : }
     334             : 
     335             : /**
     336             :  * Post-reflow hook. This is where the table row does its post-processing
     337             :  */
     338             : void
     339           0 : nsTableRowFrame::DidResize()
     340             : {
     341             :   // Resize and re-align the cell frames based on our row bsize
     342           0 :   nsTableFrame* tableFrame = GetTableFrame();
     343             : 
     344           0 :   WritingMode wm = GetWritingMode();
     345           0 :   ReflowOutput desiredSize(wm);
     346           0 :   desiredSize.SetSize(wm, GetLogicalSize(wm));
     347           0 :   desiredSize.SetOverflowAreasToDesiredBounds();
     348             : 
     349           0 :   nsSize containerSize = mRect.Size();
     350             : 
     351           0 :   for (nsIFrame* childFrame : mFrames) {
     352           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
     353           0 :     if (cellFrame) {
     354           0 :       nscoord cellBSize = BSize(wm) +
     355           0 :         GetBSizeOfRowsSpannedBelowFirst(*cellFrame, *tableFrame, wm);
     356             : 
     357             :       // If the bsize for the cell has changed, we need to reset it;
     358             :       // and in vertical-rl mode, we need to update the cell's block position
     359             :       // to account for the containerSize, which may not have been known
     360             :       // earlier, so we always apply it here.
     361           0 :       LogicalSize cellSize = cellFrame->GetLogicalSize(wm);
     362           0 :       if (cellSize.BSize(wm) != cellBSize || wm.IsVerticalRL()) {
     363           0 :         nsRect cellOldRect = cellFrame->GetRect();
     364           0 :         nsRect cellVisualOverflow = cellFrame->GetVisualOverflowRect();
     365             : 
     366           0 :         if (wm.IsVerticalRL()) {
     367             :           // Get the old position of the cell, as we want to preserve its
     368             :           // inline coordinate.
     369             :           LogicalPoint oldPos =
     370           0 :             cellFrame->GetLogicalPosition(wm, containerSize);
     371             : 
     372             :           // The cell should normally be aligned with the row's block-start,
     373             :           // so set the B component of the position to zero:
     374           0 :           LogicalPoint newPos(wm, oldPos.I(wm), 0);
     375             : 
     376             :           // ...unless relative positioning is in effect, in which case the
     377             :           // cell may have been moved away from the row's block-start
     378           0 :           if (cellFrame->IsRelativelyPositioned()) {
     379             :             // Find out where the cell would have been without relative
     380             :             // positioning.
     381             :             LogicalPoint oldNormalPos =
     382           0 :               cellFrame->GetLogicalNormalPosition(wm, containerSize);
     383             :             // The difference (if any) between oldPos and oldNormalPos reflects
     384             :             // relative positioning that was applied to the cell, and which we
     385             :             // need to incorporate when resetting the position.
     386           0 :             newPos.B(wm) = oldPos.B(wm) - oldNormalPos.B(wm);
     387             :           }
     388             : 
     389           0 :           if (oldPos != newPos) {
     390           0 :             cellFrame->SetPosition(wm, newPos, containerSize);
     391           0 :             nsTableFrame::RePositionViews(cellFrame);
     392             :           }
     393             :         }
     394             : 
     395           0 :         cellSize.BSize(wm) = cellBSize;
     396           0 :         cellFrame->SetSize(wm, cellSize);
     397             : 
     398           0 :         nsTableFrame* tableFrame = GetTableFrame();
     399           0 :         if (tableFrame->IsBorderCollapse()) {
     400             :           nsTableFrame::InvalidateTableFrame(cellFrame, cellOldRect,
     401             :                                              cellVisualOverflow,
     402           0 :                                              false);
     403             :         }
     404             :       }
     405             : 
     406             :       // realign cell content based on the new bsize.  We might be able to
     407             :       // skip this if the bsize didn't change... maybe.  Hard to tell.
     408           0 :       cellFrame->BlockDirAlignChild(wm, mMaxCellAscent);
     409             : 
     410             :       // Always store the overflow, even if the height didn't change, since
     411             :       // we'll lose part of our overflow area otherwise.
     412           0 :       ConsiderChildOverflow(desiredSize.mOverflowAreas, cellFrame);
     413             : 
     414             :       // Note that if the cell's *content* needs to change in response
     415             :       // to this height, it will get a special bsize reflow.
     416             :     }
     417             :   }
     418           0 :   FinishAndStoreOverflow(&desiredSize);
     419           0 :   if (HasView()) {
     420           0 :     nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this, GetView(),
     421           0 :                                                desiredSize.VisualOverflow(), 0);
     422             :   }
     423             :   // Let our base class do the usual work
     424           0 : }
     425             : 
     426             : // returns max-ascent amongst all cells that have 'vertical-align: baseline'
     427             : // *including* cells with rowspans
     428           0 : nscoord nsTableRowFrame::GetMaxCellAscent() const
     429             : {
     430           0 :   return mMaxCellAscent;
     431             : }
     432             : 
     433           0 : nscoord nsTableRowFrame::GetRowBaseline(WritingMode aWM)
     434             : {
     435           0 :   if (mMaxCellAscent) {
     436           0 :     return mMaxCellAscent;
     437             :   }
     438             : 
     439             :   // If we don't have a baseline on any of the cells we go for the lowest
     440             :   // content edge of the inner block frames.
     441             :   // Every table cell has a cell frame with its border and padding. Inside
     442             :   // the cell is a block frame. The cell is as high as the tallest cell in
     443             :   // the parent row. As a consequence the block frame might not touch both
     444             :   // the top and the bottom padding of it parent cell frame at the same time.
     445             :   //
     446             :   // bbbbbbbbbbbbbbbbbb             cell border:  b
     447             :   // bppppppppppppppppb             cell padding: p
     448             :   // bpxxxxxxxxxxxxxxpb             inner block:  x
     449             :   // bpx            xpb
     450             :   // bpx            xpb
     451             :   // bpx            xpb
     452             :   // bpxxxxxxxxxxxxxxpb  base line
     453             :   // bp              pb
     454             :   // bp              pb
     455             :   // bppppppppppppppppb
     456             :   // bbbbbbbbbbbbbbbbbb
     457             : 
     458           0 :   nscoord ascent = 0;
     459           0 :   nsSize containerSize = GetSize();
     460           0 :   for (nsIFrame* childFrame : mFrames) {
     461           0 :     if (IS_TABLE_CELL(childFrame->Type())) {
     462           0 :       nsIFrame* firstKid = childFrame->PrincipalChildList().FirstChild();
     463           0 :       ascent = std::max(ascent,
     464           0 :                         LogicalRect(aWM, firstKid->GetNormalRect(),
     465           0 :                                     containerSize).BEnd(aWM));
     466             :     }
     467             :   }
     468           0 :   return ascent;
     469             : }
     470             : 
     471             : nscoord
     472           0 : nsTableRowFrame::GetInitialBSize(nscoord aPctBasis) const
     473             : {
     474           0 :   nscoord bsize = 0;
     475           0 :   if ((aPctBasis > 0) && HasPctBSize()) {
     476           0 :     bsize = NSToCoordRound(GetPctBSize() * (float)aPctBasis);
     477             :   }
     478           0 :   if (HasFixedBSize()) {
     479           0 :     bsize = std::max(bsize, GetFixedBSize());
     480             :   }
     481           0 :   return std::max(bsize, GetContentBSize());
     482             : }
     483             : 
     484             : void
     485           0 : nsTableRowFrame::ResetBSize(nscoord aFixedBSize)
     486             : {
     487           0 :   SetHasFixedBSize(false);
     488           0 :   SetHasPctBSize(false);
     489           0 :   SetFixedBSize(0);
     490           0 :   SetPctBSize(0);
     491           0 :   SetContentBSize(0);
     492             : 
     493           0 :   if (aFixedBSize > 0) {
     494           0 :     SetFixedBSize(aFixedBSize);
     495             :   }
     496             : 
     497           0 :   mMaxCellAscent = 0;
     498           0 :   mMaxCellDescent = 0;
     499           0 : }
     500             : 
     501             : void
     502           0 : nsTableRowFrame::UpdateBSize(nscoord           aBSize,
     503             :                              nscoord           aAscent,
     504             :                              nscoord           aDescent,
     505             :                              nsTableFrame*     aTableFrame,
     506             :                              nsTableCellFrame* aCellFrame)
     507             : {
     508           0 :   if (!aTableFrame || !aCellFrame) {
     509           0 :     NS_ASSERTION(false , "invalid call");
     510           0 :     return;
     511             :   }
     512             : 
     513           0 :   if (aBSize != NS_UNCONSTRAINEDSIZE) {
     514           0 :     if (!(aCellFrame->HasVerticalAlignBaseline())) { // only the cell's height matters
     515           0 :       if (GetInitialBSize() < aBSize) {
     516           0 :         int32_t rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
     517           0 :         if (rowSpan == 1) {
     518           0 :           SetContentBSize(aBSize);
     519             :         }
     520             :       }
     521             :     }
     522             :     else { // the alignment on the baseline can change the bsize
     523           0 :       NS_ASSERTION((aAscent != NS_UNCONSTRAINEDSIZE) &&
     524             :                    (aDescent != NS_UNCONSTRAINEDSIZE), "invalid call");
     525             :       // see if this is a long ascender
     526           0 :       if (mMaxCellAscent < aAscent) {
     527           0 :         mMaxCellAscent = aAscent;
     528             :       }
     529             :       // see if this is a long descender and without rowspan
     530           0 :       if (mMaxCellDescent < aDescent) {
     531           0 :         int32_t rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
     532           0 :         if (rowSpan == 1) {
     533           0 :           mMaxCellDescent = aDescent;
     534             :         }
     535             :       }
     536             :       // keep the tallest bsize in sync
     537           0 :       if (GetInitialBSize() < mMaxCellAscent + mMaxCellDescent) {
     538           0 :         SetContentBSize(mMaxCellAscent + mMaxCellDescent);
     539             :       }
     540             :     }
     541             :   }
     542             : }
     543             : 
     544             : nscoord
     545           0 : nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput)
     546             : {
     547           0 :   nsTableFrame* tableFrame = GetTableFrame();
     548           0 :   nscoord computedBSize = (NS_UNCONSTRAINEDSIZE == aReflowInput.ComputedBSize())
     549           0 :                             ? 0 : aReflowInput.ComputedBSize();
     550           0 :   ResetBSize(computedBSize);
     551             : 
     552           0 :   WritingMode wm = aReflowInput.GetWritingMode();
     553           0 :   const nsStylePosition* position = StylePosition();
     554           0 :   const nsStyleCoord& bsizeStyleCoord = position->BSize(wm);
     555           0 :   if (bsizeStyleCoord.ConvertsToLength()) {
     556           0 :     SetFixedBSize(nsRuleNode::ComputeCoordPercentCalc(bsizeStyleCoord, 0));
     557             :   }
     558           0 :   else if (eStyleUnit_Percent == bsizeStyleCoord.GetUnit()) {
     559           0 :     SetPctBSize(bsizeStyleCoord.GetPercentValue());
     560             :   }
     561             :   // calc() with percentages is treated like 'auto' on table rows.
     562             : 
     563           0 :   for (nsIFrame* kidFrame : mFrames) {
     564           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
     565           0 :     if (cellFrame) {
     566           0 :       MOZ_ASSERT(cellFrame->GetWritingMode() == wm);
     567           0 :       LogicalSize desSize = cellFrame->GetDesiredSize();
     568           0 :       if ((NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) && !GetPrevInFlow()) {
     569           0 :         CalculateCellActualBSize(cellFrame, desSize.BSize(wm), wm);
     570             :       }
     571             :       // bsize may have changed, adjust descent to absorb any excess difference
     572             :       nscoord ascent;
     573           0 :        if (!kidFrame->PrincipalChildList().FirstChild()->PrincipalChildList().FirstChild())
     574           0 :          ascent = desSize.BSize(wm);
     575             :        else
     576           0 :          ascent = cellFrame->GetCellBaseline();
     577           0 :        nscoord descent = desSize.BSize(wm) - ascent;
     578           0 :        UpdateBSize(desSize.BSize(wm), ascent, descent, tableFrame, cellFrame);
     579             :     }
     580             :   }
     581           0 :   return GetInitialBSize();
     582             : }
     583             : 
     584             : void
     585           0 : nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     586             :                                   const nsRect&           aDirtyRect,
     587             :                                   const nsDisplayListSet& aLists)
     588             : {
     589           0 :   nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
     590           0 : }
     591             : 
     592             : nsIFrame::LogicalSides
     593           0 : nsTableRowFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
     594             : {
     595           0 :   if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
     596             :                      StyleBoxDecorationBreak::Clone)) {
     597           0 :     return LogicalSides();
     598             :   }
     599             : 
     600           0 :   LogicalSides skip;
     601           0 :   if (nullptr != GetPrevInFlow()) {
     602           0 :     skip |= eLogicalSideBitsBStart;
     603             :   }
     604           0 :   if (nullptr != GetNextInFlow()) {
     605           0 :     skip |= eLogicalSideBitsBEnd;
     606             :   }
     607           0 :   return skip;
     608             : }
     609             : 
     610             : // Calculate the cell's actual bsize given its pass2 bsize.
     611             : // Takes into account the specified bsize (in the style).
     612             : // Modifies the desired bsize that is passed in.
     613             : nsresult
     614           0 : nsTableRowFrame::CalculateCellActualBSize(nsTableCellFrame* aCellFrame,
     615             :                                           nscoord&          aDesiredBSize,
     616             :                                           WritingMode       aWM)
     617             : {
     618           0 :   nscoord specifiedBSize = 0;
     619             : 
     620             :   // Get the bsize specified in the style information
     621           0 :   const nsStylePosition* position = aCellFrame->StylePosition();
     622             : 
     623           0 :   int32_t rowSpan = GetTableFrame()->GetEffectiveRowSpan(*aCellFrame);
     624             : 
     625           0 :   const nsStyleCoord& bsizeStyleCoord = position->BSize(aWM);
     626           0 :   switch (bsizeStyleCoord.GetUnit()) {
     627             :     case eStyleUnit_Calc: {
     628           0 :       if (bsizeStyleCoord.CalcHasPercent()) {
     629             :         // Treat this like "auto"
     630           0 :         break;
     631             :       }
     632             :       // Fall through to the coord case
     633             :       MOZ_FALLTHROUGH;
     634             :     }
     635             :     case eStyleUnit_Coord: {
     636             :       // In quirks mode, table cell isize should be content-box, but bsize
     637             :       // should be border-box.
     638             :       // Because of this historic anomaly, we do not use quirk.css
     639             :       // (since we can't specify one value of box-sizing for isize and another
     640             :       // for bsize)
     641           0 :       specifiedBSize = nsRuleNode::ComputeCoordPercentCalc(bsizeStyleCoord, 0);
     642           0 :       if (PresContext()->CompatibilityMode() != eCompatibility_NavQuirks &&
     643           0 :           position->mBoxSizing == StyleBoxSizing::Content) {
     644           0 :         specifiedBSize +=
     645           0 :           aCellFrame->GetLogicalUsedBorderAndPadding(aWM).BStartEnd(aWM);
     646             :       }
     647             : 
     648           0 :       if (1 == rowSpan) {
     649           0 :         SetFixedBSize(specifiedBSize);
     650             :       }
     651           0 :       break;
     652             :     }
     653             :     case eStyleUnit_Percent: {
     654           0 :       if (1 == rowSpan) {
     655           0 :         SetPctBSize(bsizeStyleCoord.GetPercentValue());
     656             :       }
     657             :       // pct bsizes are handled when all of the cells are finished,
     658             :       // so don't set specifiedBSize
     659           0 :       break;
     660             :     }
     661             :     case eStyleUnit_Auto:
     662             :     default:
     663           0 :       break;
     664             :   }
     665             : 
     666             :   // If the specified bsize is greater than the desired bsize,
     667             :   // then use the specified bsize
     668           0 :   if (specifiedBSize > aDesiredBSize) {
     669           0 :     aDesiredBSize = specifiedBSize;
     670             :   }
     671             : 
     672           0 :   return NS_OK;
     673             : }
     674             : 
     675             : // Calculates the available isize for the table cell based on the known
     676             : // column isizes taking into account column spans and column spacing
     677             : static nscoord
     678           0 : CalcAvailISize(nsTableFrame&     aTableFrame,
     679             :                nsTableCellFrame& aCellFrame)
     680             : {
     681           0 :   nscoord cellAvailISize = 0;
     682             :   int32_t colIndex;
     683           0 :   aCellFrame.GetColIndex(colIndex);
     684           0 :   int32_t colspan = aTableFrame.GetEffectiveColSpan(aCellFrame);
     685           0 :   NS_ASSERTION(colspan > 0, "effective colspan should be positive");
     686             :   nsTableFrame* fifTable =
     687           0 :     static_cast<nsTableFrame*>(aTableFrame.FirstInFlow());
     688             : 
     689           0 :   for (int32_t spanX = 0; spanX < colspan; spanX++) {
     690           0 :     cellAvailISize +=
     691           0 :       fifTable->GetColumnISizeFromFirstInFlow(colIndex + spanX);
     692           0 :     if (spanX > 0 &&
     693           0 :         aTableFrame.ColumnHasCellSpacingBefore(colIndex + spanX)) {
     694           0 :       cellAvailISize += aTableFrame.GetColSpacing(colIndex + spanX - 1);
     695             :     }
     696             :   }
     697           0 :   return cellAvailISize;
     698             : }
     699             : 
     700             : nscoord
     701           0 : GetSpaceBetween(int32_t       aPrevColIndex,
     702             :                 int32_t       aColIndex,
     703             :                 int32_t       aColSpan,
     704             :                 nsTableFrame& aTableFrame,
     705             :                 bool          aCheckVisibility)
     706             : {
     707           0 :   nscoord space = 0;
     708             :   int32_t colIdx;
     709             :   nsTableFrame* fifTable =
     710           0 :     static_cast<nsTableFrame*>(aTableFrame.FirstInFlow());
     711           0 :   for (colIdx = aPrevColIndex + 1; aColIndex > colIdx; colIdx++) {
     712           0 :     bool isCollapsed = false;
     713           0 :     if (!aCheckVisibility) {
     714           0 :       space += fifTable->GetColumnISizeFromFirstInFlow(colIdx);
     715             :     }
     716             :     else {
     717           0 :       nsTableColFrame* colFrame = aTableFrame.GetColFrame(colIdx);
     718           0 :       const nsStyleVisibility* colVis = colFrame->StyleVisibility();
     719           0 :       bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible);
     720           0 :       nsIFrame* cgFrame = colFrame->GetParent();
     721           0 :       const nsStyleVisibility* groupVis = cgFrame->StyleVisibility();
     722             :       bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE ==
     723           0 :                               groupVis->mVisible);
     724           0 :       isCollapsed = collapseCol || collapseGroup;
     725           0 :       if (!isCollapsed)
     726           0 :         space += fifTable->GetColumnISizeFromFirstInFlow(colIdx);
     727             :     }
     728           0 :     if (!isCollapsed && aTableFrame.ColumnHasCellSpacingBefore(colIdx)) {
     729           0 :       space += aTableFrame.GetColSpacing(colIdx - 1);
     730             :     }
     731             :   }
     732           0 :   return space;
     733             : }
     734             : 
     735             : // subtract the bsizes of aRow's prev in flows from the unpaginated bsize
     736             : static
     737           0 : nscoord CalcBSizeFromUnpaginatedBSize(nsTableRowFrame& aRow,
     738             :                                       WritingMode      aWM)
     739             : {
     740           0 :   nscoord bsize = 0;
     741             :   nsTableRowFrame* firstInFlow =
     742           0 :     static_cast<nsTableRowFrame*>(aRow.FirstInFlow());
     743           0 :   if (firstInFlow->HasUnpaginatedBSize()) {
     744           0 :     bsize = firstInFlow->GetUnpaginatedBSize();
     745           0 :     for (nsIFrame* prevInFlow = aRow.GetPrevInFlow(); prevInFlow;
     746             :          prevInFlow = prevInFlow->GetPrevInFlow()) {
     747           0 :       bsize -= prevInFlow->BSize(aWM);
     748             :     }
     749             :   }
     750           0 :   return std::max(bsize, 0);
     751             : }
     752             : 
     753             : void
     754           0 : nsTableRowFrame::ReflowChildren(nsPresContext*           aPresContext,
     755             :                                 ReflowOutput&     aDesiredSize,
     756             :                                 const ReflowInput& aReflowInput,
     757             :                                 nsTableFrame&            aTableFrame,
     758             :                                 nsReflowStatus&          aStatus)
     759             : {
     760           0 :   aStatus.Reset();
     761             : 
     762             :   // XXXldb Should we be checking constrained bsize instead?
     763           0 :   const bool isPaginated = aPresContext->IsPaginated();
     764           0 :   const bool borderCollapse = aTableFrame.IsBorderCollapse();
     765             : 
     766           0 :   int32_t cellColSpan = 1;  // must be defined here so it's set properly for non-cell kids
     767             : 
     768             :   // remember the col index of the previous cell to handle rowspans into this row
     769           0 :   int32_t prevColIndex = -1;
     770           0 :   nscoord iCoord = 0; // running total of children inline-coord offset
     771             : 
     772             :   // This computes the max of all cell bsizes
     773           0 :   nscoord cellMaxBSize = 0;
     774             : 
     775             :   // Reflow each of our existing cell frames
     776           0 :   WritingMode wm = aReflowInput.GetWritingMode();
     777             :   nsSize containerSize =
     778           0 :     aReflowInput.ComputedSizeAsContainerIfConstrained();
     779             : 
     780           0 :   for (nsIFrame* kidFrame : mFrames) {
     781           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
     782           0 :     if (!cellFrame) {
     783             :       // XXXldb nsCSSFrameConstructor needs to enforce this!
     784           0 :       NS_NOTREACHED("yikes, a non-row child");
     785             : 
     786             :       // it's an unknown frame type, give it a generic reflow and ignore the results
     787             :       TableCellReflowInput
     788             :         kidReflowInput(aPresContext, aReflowInput, kidFrame,
     789           0 :                        LogicalSize(kidFrame->GetWritingMode(), 0, 0),
     790           0 :                        ReflowInput::CALLER_WILL_INIT);
     791           0 :       InitChildReflowInput(*aPresContext, LogicalSize(wm), false, kidReflowInput);
     792           0 :       ReflowOutput desiredSize(aReflowInput);
     793           0 :       nsReflowStatus  status;
     794           0 :       ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowInput, 0, 0, 0, status);
     795           0 :       kidFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
     796             : 
     797           0 :       continue;
     798             :     }
     799             : 
     800             :     // See if we should only reflow the dirty child frames
     801           0 :     bool doReflowChild = true;
     802           0 :     if (!aReflowInput.ShouldReflowAllKids() &&
     803           0 :         !aTableFrame.IsGeometryDirty() &&
     804           0 :         !NS_SUBTREE_DIRTY(kidFrame)) {
     805           0 :       if (!aReflowInput.mFlags.mSpecialBSizeReflow)
     806           0 :         doReflowChild = false;
     807             :     }
     808           0 :     else if ((NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableBSize())) {
     809             :       // We don't reflow a rowspan >1 cell here with a constrained bsize.
     810             :       // That happens in nsTableRowGroupFrame::SplitSpanningCells.
     811           0 :       if (aTableFrame.GetEffectiveRowSpan(*cellFrame) > 1) {
     812           0 :         doReflowChild = false;
     813             :       }
     814             :     }
     815           0 :     if (aReflowInput.mFlags.mSpecialBSizeReflow) {
     816           0 :       if (!isPaginated &&
     817           0 :           !cellFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
     818           0 :         continue;
     819             :       }
     820             :     }
     821             : 
     822             :     int32_t cellColIndex;
     823           0 :     cellFrame->GetColIndex(cellColIndex);
     824           0 :     cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame);
     825             : 
     826             :     // If the adjacent cell is in a prior row (because of a rowspan) add in the space
     827           0 :     if (prevColIndex != (cellColIndex - 1)) {
     828           0 :       iCoord += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
     829             :                                 false);
     830             :     }
     831             : 
     832             :     // remember the rightmost (ltr) or leftmost (rtl) column this cell spans into
     833           0 :     prevColIndex = cellColIndex + (cellColSpan - 1);
     834             : 
     835             :     // Reflow the child frame
     836           0 :     nsRect kidRect = kidFrame->GetRect();
     837             :     LogicalPoint origKidNormalPosition =
     838           0 :       kidFrame->GetLogicalNormalPosition(wm, containerSize);
     839             :     // All cells' no-relative-positioning position should be snapped to the
     840             :     // row's bstart edge.
     841             :     // This doesn't hold in vertical-rl mode, where we don't yet know the
     842             :     // correct containerSize for the row frame. In that case, we'll have to
     843             :     // fix up child positions later, after determining our desiredSize.
     844           0 :     NS_ASSERTION(origKidNormalPosition.B(wm) == 0 || wm.IsVerticalRL(),
     845             :                  "unexpected kid position");
     846             : 
     847           0 :     nsRect kidVisualOverflow = kidFrame->GetVisualOverflowRect();
     848           0 :     LogicalPoint kidPosition(wm, iCoord, 0);
     849           0 :     bool firstReflow = kidFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
     850             : 
     851           0 :     if (doReflowChild) {
     852             :       // Calculate the available isize for the table cell using the known
     853             :       // column isizes
     854           0 :       nscoord availCellISize = CalcAvailISize(aTableFrame, *cellFrame);
     855             : 
     856           0 :       Maybe<TableCellReflowInput> kidReflowInput;
     857           0 :       ReflowOutput desiredSize(aReflowInput);
     858             : 
     859             :       // If the avail isize is not the same as last time we reflowed the cell or
     860             :       // the cell wants to be bigger than what was available last time or
     861             :       // it is a style change reflow or we are printing, then we must reflow the
     862             :       // cell. Otherwise we can skip the reflow.
     863             :       // XXXldb Why is this condition distinct from doReflowChild above?
     864           0 :       WritingMode wm = aReflowInput.GetWritingMode();
     865           0 :       NS_ASSERTION(cellFrame->GetWritingMode() == wm,
     866             :                    "expected consistent writing-mode within table");
     867           0 :       LogicalSize cellDesiredSize = cellFrame->GetDesiredSize();
     868           0 :       if ((availCellISize != cellFrame->GetPriorAvailISize())           ||
     869           0 :           (cellDesiredSize.ISize(wm) > cellFrame->GetPriorAvailISize()) ||
     870           0 :           HasAnyStateBits(NS_FRAME_IS_DIRTY)                            ||
     871           0 :           isPaginated                                                   ||
     872           0 :           NS_SUBTREE_DIRTY(cellFrame)                                   ||
     873             :           // See if it needs a special reflow, or if it had one that we need to undo.
     874           0 :           cellFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)  ||
     875           0 :           HasPctBSize()) {
     876             :         // Reflow the cell to fit the available isize, bsize
     877             :         // XXX The old IR_ChildIsDirty code used availCellISize here.
     878           0 :         LogicalSize kidAvailSize(wm, availCellISize, aReflowInput.AvailableBSize());
     879             : 
     880             :         // Reflow the child
     881           0 :         kidReflowInput.emplace(aPresContext, aReflowInput, kidFrame,
     882             :                                kidAvailSize,
     883           0 :                                ReflowInput::CALLER_WILL_INIT);
     884           0 :         InitChildReflowInput(*aPresContext, kidAvailSize, borderCollapse,
     885           0 :                              *kidReflowInput);
     886             : 
     887           0 :         nsReflowStatus status;
     888           0 :         ReflowChild(kidFrame, aPresContext, desiredSize, *kidReflowInput,
     889           0 :                     wm, kidPosition, containerSize, 0, status);
     890             : 
     891             :         // allow the table to determine if/how the table needs to be rebalanced
     892             :         // If any of the cells are not complete, then we're not complete
     893           0 :         if (status.IsIncomplete()) {
     894           0 :           aStatus.Reset();
     895           0 :           aStatus.SetIncomplete();
     896             :         }
     897             :       } else {
     898           0 :         if (iCoord != origKidNormalPosition.I(wm)) {
     899           0 :           kidFrame->InvalidateFrameSubtree();
     900             :         }
     901             : 
     902           0 :         desiredSize.SetSize(wm, cellDesiredSize);
     903           0 :         desiredSize.mOverflowAreas = cellFrame->GetOverflowAreas();
     904             : 
     905             :         // if we are in a floated table, our position is not yet established, so we cannot reposition our views
     906             :         // the containing block will do this for us after positioning the table
     907           0 :         if (!aTableFrame.IsFloating()) {
     908             :           // Because we may have moved the frame we need to make sure any views are
     909             :           // positioned properly. We have to do this, because any one of our parent
     910             :           // frames could have moved and we have no way of knowing...
     911           0 :           nsTableFrame::RePositionViews(kidFrame);
     912             :         }
     913             :       }
     914             : 
     915           0 :       if (NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) {
     916           0 :         if (!GetPrevInFlow()) {
     917             :           // Calculate the cell's actual bsize given its pass2 bsize. This
     918             :           // function takes into account the specified bsize (in the style)
     919           0 :           CalculateCellActualBSize(cellFrame, desiredSize.BSize(wm), wm);
     920             :         }
     921             :         // bsize may have changed, adjust descent to absorb any excess difference
     922             :         nscoord ascent;
     923           0 :         if (!kidFrame->PrincipalChildList().FirstChild()->PrincipalChildList().FirstChild()) {
     924           0 :           ascent = desiredSize.BSize(wm);
     925             :         } else {
     926           0 :           ascent = ((nsTableCellFrame *)kidFrame)->GetCellBaseline();
     927             :         }
     928           0 :         nscoord descent = desiredSize.BSize(wm) - ascent;
     929           0 :         UpdateBSize(desiredSize.BSize(wm), ascent, descent, &aTableFrame, cellFrame);
     930             :       } else {
     931           0 :         cellMaxBSize = std::max(cellMaxBSize, desiredSize.BSize(wm));
     932           0 :         int32_t rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
     933           0 :         if (1 == rowSpan) {
     934           0 :           SetContentBSize(cellMaxBSize);
     935             :         }
     936             :       }
     937             : 
     938             :       // Place the child
     939           0 :       desiredSize.ISize(wm) = availCellISize;
     940             : 
     941           0 :       if (kidReflowInput) {
     942             :         // We reflowed. Apply relative positioning in the normal way.
     943           0 :         kidReflowInput->ApplyRelativePositioning(&kidPosition, containerSize);
     944           0 :       } else if (kidFrame->IsRelativelyPositioned()) {
     945             :         // We didn't reflow.  Do the positioning part of what
     946             :         // MovePositionBy does internally.  (This codepath should really
     947             :         // be merged into the else below if we can.)
     948             :         nsMargin* computedOffsetProp =
     949           0 :           kidFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
     950             :         // Bug 975644: a position:sticky kid can end up with a null
     951             :         // property value here.
     952           0 :         LogicalMargin computedOffsets(wm, computedOffsetProp ?
     953           0 :                                             *computedOffsetProp : nsMargin());
     954             :         ReflowInput::ApplyRelativePositioning(kidFrame, wm, computedOffsets,
     955           0 :                                                     &kidPosition, containerSize);
     956             :       }
     957             : 
     958             :       // In vertical-rl mode, we are likely to have containerSize.width = 0
     959             :       // because ComputedWidth() was NS_UNCONSTRAINEDSIZE.
     960             :       // For cases where that's wrong, we will fix up the position later.
     961             :       FinishReflowChild(kidFrame, aPresContext, desiredSize, nullptr,
     962           0 :                         wm, kidPosition, containerSize, 0);
     963             : 
     964           0 :       nsTableFrame* tableFrame = GetTableFrame();
     965           0 :       if (tableFrame->IsBorderCollapse()) {
     966           0 :         nsTableFrame::InvalidateTableFrame(kidFrame, kidRect, kidVisualOverflow,
     967           0 :                                            firstReflow);
     968             :       }
     969             : 
     970           0 :       iCoord += desiredSize.ISize(wm);
     971             :     } else {
     972           0 :       if (iCoord != origKidNormalPosition.I(wm)) {
     973             :         // Invalidate the old position
     974           0 :         kidFrame->InvalidateFrameSubtree();
     975             :         // Move to the new position. As above, we need to account for relative
     976             :         // positioning.
     977           0 :         kidFrame->MovePositionBy(wm,
     978           0 :           LogicalPoint(wm, iCoord - origKidNormalPosition.I(wm), 0));
     979           0 :         nsTableFrame::RePositionViews(kidFrame);
     980             :         // invalidate the new position
     981           0 :         kidFrame->InvalidateFrameSubtree();
     982             :       }
     983             :       // we need to account for the cell's isize even if it isn't reflowed
     984           0 :       iCoord += kidFrame->ISize(wm);
     985             : 
     986           0 :       if (kidFrame->GetNextInFlow()) {
     987           0 :         aStatus.Reset();
     988           0 :         aStatus.SetIncomplete();
     989             :       }
     990             :     }
     991           0 :     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
     992           0 :     iCoord += aTableFrame.GetColSpacing(cellColIndex);
     993             :   }
     994             : 
     995             :   // Just set our isize to what was available.
     996             :   // The table will calculate the isize and not use our value.
     997           0 :   aDesiredSize.ISize(wm) = aReflowInput.AvailableISize();
     998             : 
     999           0 :   if (aReflowInput.mFlags.mSpecialBSizeReflow) {
    1000           0 :     aDesiredSize.BSize(wm) = BSize(wm);
    1001           0 :   } else if (NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) {
    1002           0 :     aDesiredSize.BSize(wm) = CalcBSize(aReflowInput);
    1003           0 :     if (GetPrevInFlow()) {
    1004           0 :       nscoord bsize = CalcBSizeFromUnpaginatedBSize(*this, wm);
    1005           0 :       aDesiredSize.BSize(wm) = std::max(aDesiredSize.BSize(wm), bsize);
    1006             :     } else {
    1007           0 :       if (isPaginated && HasStyleBSize()) {
    1008             :         // set the unpaginated bsize so next in flows can try to honor it
    1009           0 :         SetHasUnpaginatedBSize(true);
    1010           0 :         SetUnpaginatedBSize(aPresContext, aDesiredSize.BSize(wm));
    1011             :       }
    1012           0 :       if (isPaginated && HasUnpaginatedBSize()) {
    1013           0 :         aDesiredSize.BSize(wm) = std::max(aDesiredSize.BSize(wm),
    1014           0 :                                           GetUnpaginatedBSize());
    1015             :       }
    1016             :     }
    1017             :   } else { // constrained bsize, paginated
    1018             :     // Compute the bsize we should have from style (subtracting the
    1019             :     // bsize from our prev-in-flows from the style bsize)
    1020           0 :     nscoord styleBSize = CalcBSizeFromUnpaginatedBSize(*this, wm);
    1021           0 :     if (styleBSize > aReflowInput.AvailableBSize()) {
    1022           0 :       styleBSize = aReflowInput.AvailableBSize();
    1023           0 :       aStatus.SetIncomplete();
    1024             :     }
    1025           0 :     aDesiredSize.BSize(wm) = std::max(cellMaxBSize, styleBSize);
    1026             :   }
    1027             : 
    1028           0 :   if (wm.IsVerticalRL()) {
    1029             :     // Any children whose width was not the same as our final
    1030             :     // aDesiredSize.BSize will have been misplaced earlier at the
    1031             :     // FinishReflowChild stage. So fix them up now.
    1032           0 :     for (nsIFrame* kidFrame : mFrames) {
    1033           0 :       nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
    1034           0 :       if (!cellFrame) {
    1035           0 :         continue;
    1036             :       }
    1037           0 :       if (kidFrame->BSize(wm) != aDesiredSize.BSize(wm)) {
    1038             :         kidFrame->MovePositionBy(wm,
    1039           0 :           LogicalPoint(wm, 0, kidFrame->BSize(wm) - aDesiredSize.BSize(wm)));
    1040           0 :         nsTableFrame::RePositionViews(kidFrame);
    1041             :         // Do we need to InvalidateFrameSubtree() here?
    1042             :       }
    1043             :     }
    1044             :   }
    1045             : 
    1046           0 :   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
    1047           0 :   FinishAndStoreOverflow(&aDesiredSize);
    1048           0 : }
    1049             : 
    1050             : /** Layout the entire row.
    1051             :   * This method stacks cells in the inline dir according to HTML 4.0 rules.
    1052             :   */
    1053             : void
    1054           0 : nsTableRowFrame::Reflow(nsPresContext*           aPresContext,
    1055             :                         ReflowOutput&     aDesiredSize,
    1056             :                         const ReflowInput& aReflowInput,
    1057             :                         nsReflowStatus&          aStatus)
    1058             : {
    1059           0 :   MarkInReflow();
    1060           0 :   DO_GLOBAL_REFLOW_COUNT("nsTableRowFrame");
    1061           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
    1062             : 
    1063           0 :   WritingMode wm = aReflowInput.GetWritingMode();
    1064             : 
    1065           0 :   nsTableFrame* tableFrame = GetTableFrame();
    1066           0 :   const nsStyleVisibility* rowVis = StyleVisibility();
    1067           0 :   bool collapseRow = (NS_STYLE_VISIBILITY_COLLAPSE == rowVis->mVisible);
    1068           0 :   if (collapseRow) {
    1069           0 :     tableFrame->SetNeedToCollapse(true);
    1070             :   }
    1071             : 
    1072             :   // see if a special bsize reflow needs to occur due to having a pct bsize
    1073           0 :   nsTableFrame::CheckRequestSpecialBSizeReflow(aReflowInput);
    1074             : 
    1075             :   // See if we have a cell with specified/pct bsize
    1076           0 :   InitHasCellWithStyleBSize(tableFrame);
    1077             : 
    1078           0 :   ReflowChildren(aPresContext, aDesiredSize, aReflowInput, *tableFrame, aStatus);
    1079             : 
    1080           0 :   if (aPresContext->IsPaginated() && !aStatus.IsFullyComplete() &&
    1081           0 :       ShouldAvoidBreakInside(aReflowInput)) {
    1082           0 :     aStatus.SetInlineLineBreakBeforeAndReset();
    1083             :   }
    1084             : 
    1085             :   // Just set our isize to what was available.
    1086             :   // The table will calculate the isize and not use our value.
    1087           0 :   aDesiredSize.ISize(wm) = aReflowInput.AvailableISize();
    1088             : 
    1089             :   // If our parent is in initial reflow, it'll handle invalidating our
    1090             :   // entire overflow rect.
    1091           0 :   if (!GetParent()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW) &&
    1092           0 :       nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
    1093           0 :     InvalidateFrame();
    1094             :   }
    1095             : 
    1096             :   // Any absolutely-positioned children will get reflowed in
    1097             :   // nsFrame::FixupPositionedTableParts in another pass, so propagate our
    1098             :   // dirtiness to them before our parent clears our dirty bits.
    1099           0 :   PushDirtyBitToAbsoluteFrames();
    1100             : 
    1101           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
    1102           0 : }
    1103             : 
    1104             : /**
    1105             :  * This function is called by the row group frame's SplitRowGroup() code when
    1106             :  * pushing a row frame that has cell frames that span into it. The cell frame
    1107             :  * should be reflowed with the specified height
    1108             :  */
    1109             : nscoord
    1110           0 : nsTableRowFrame::ReflowCellFrame(nsPresContext*           aPresContext,
    1111             :                                  const ReflowInput& aReflowInput,
    1112             :                                  bool                     aIsTopOfPage,
    1113             :                                  nsTableCellFrame*        aCellFrame,
    1114             :                                  nscoord                  aAvailableBSize,
    1115             :                                  nsReflowStatus&          aStatus)
    1116             : {
    1117           0 :   WritingMode wm = aReflowInput.GetWritingMode();
    1118             : 
    1119             :   // Reflow the cell frame with the specified height. Use the existing width
    1120           0 :   nsSize containerSize = aCellFrame->GetSize();
    1121           0 :   LogicalRect cellRect = aCellFrame->GetLogicalRect(wm, containerSize);
    1122           0 :   nsRect cellVisualOverflow = aCellFrame->GetVisualOverflowRect();
    1123             : 
    1124           0 :   LogicalSize cellSize = cellRect.Size(wm);
    1125           0 :   LogicalSize availSize(wm, cellRect.ISize(wm), aAvailableBSize);
    1126           0 :   bool borderCollapse = GetTableFrame()->IsBorderCollapse();
    1127           0 :   NS_ASSERTION(aCellFrame->GetWritingMode() == wm,
    1128             :                "expected consistent writing-mode within table");
    1129             :   TableCellReflowInput
    1130             :     cellReflowInput(aPresContext, aReflowInput, aCellFrame, availSize,
    1131           0 :                     ReflowInput::CALLER_WILL_INIT);
    1132           0 :   InitChildReflowInput(*aPresContext, availSize, borderCollapse, cellReflowInput);
    1133           0 :   cellReflowInput.mFlags.mIsTopOfPage = aIsTopOfPage;
    1134             : 
    1135           0 :   ReflowOutput desiredSize(aReflowInput);
    1136             : 
    1137           0 :   ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowInput,
    1138           0 :               0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
    1139           0 :   bool fullyComplete = aStatus.IsComplete() && !aStatus.IsTruncated();
    1140           0 :   if (fullyComplete) {
    1141           0 :     desiredSize.BSize(wm) = aAvailableBSize;
    1142             :   }
    1143           0 :   aCellFrame->SetSize(wm, LogicalSize(wm, cellSize.ISize(wm),
    1144           0 :                                       desiredSize.BSize(wm)));
    1145             : 
    1146             :   // Note: BlockDirAlignChild can affect the overflow rect.
    1147             :   // XXX What happens if this cell has 'vertical-align: baseline' ?
    1148             :   // XXX Why is it assumed that the cell's ascent hasn't changed ?
    1149           0 :   if (fullyComplete) {
    1150           0 :     aCellFrame->BlockDirAlignChild(wm, mMaxCellAscent);
    1151             :   }
    1152             : 
    1153           0 :   nsTableFrame::InvalidateTableFrame(aCellFrame,
    1154           0 :                                      cellRect.GetPhysicalRect(wm, containerSize),
    1155             :                                      cellVisualOverflow,
    1156             :                                      aCellFrame->
    1157           0 :                                        HasAnyStateBits(NS_FRAME_FIRST_REFLOW));
    1158             : 
    1159           0 :   aCellFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
    1160             : 
    1161           0 :   return desiredSize.BSize(wm);
    1162             : }
    1163             : 
    1164             : nscoord
    1165           0 : nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
    1166             :                                         nscoord aISize,
    1167             :                                         bool    aCollapseGroup,
    1168             :                                         bool&   aDidCollapse)
    1169             : {
    1170           0 :   const nsStyleVisibility* rowVis = StyleVisibility();
    1171           0 :   bool collapseRow = (NS_STYLE_VISIBILITY_COLLAPSE == rowVis->mVisible);
    1172             :   nsTableFrame* tableFrame =
    1173           0 :     static_cast<nsTableFrame*>(GetTableFrame()->FirstInFlow());
    1174           0 :   if (collapseRow) {
    1175           0 :     tableFrame->SetNeedToCollapse(true);
    1176             :   }
    1177             : 
    1178           0 :   if (aRowOffset != 0) {
    1179             :     // We're moving, so invalidate our old position
    1180           0 :     InvalidateFrameSubtree();
    1181             :   }
    1182             : 
    1183           0 :   WritingMode wm = GetWritingMode();
    1184             : 
    1185           0 :   nsSize parentSize = GetParent()->GetSize();
    1186           0 :   LogicalRect rowRect = GetLogicalRect(wm, parentSize);
    1187           0 :   nsRect oldRect = mRect;
    1188           0 :   nsRect oldVisualOverflow = GetVisualOverflowRect();
    1189             : 
    1190           0 :   rowRect.BStart(wm) -= aRowOffset;
    1191           0 :   rowRect.ISize(wm)  = aISize;
    1192           0 :   nsOverflowAreas overflow;
    1193           0 :   nscoord shift = 0;
    1194           0 :   nsSize containerSize = mRect.Size();
    1195             : 
    1196           0 :   if (aCollapseGroup || collapseRow) {
    1197           0 :     aDidCollapse = true;
    1198           0 :     shift = rowRect.BSize(wm);
    1199           0 :     nsTableCellFrame* cellFrame = GetFirstCell();
    1200           0 :     if (cellFrame) {
    1201             :       int32_t rowIndex;
    1202           0 :       cellFrame->GetRowIndex(rowIndex);
    1203           0 :       shift += tableFrame->GetRowSpacing(rowIndex);
    1204           0 :       while (cellFrame) {
    1205           0 :         LogicalRect cRect = cellFrame->GetLogicalRect(wm, containerSize);
    1206             :         // If aRowOffset != 0, there's no point in invalidating the cells, since
    1207             :         // we've already invalidated our overflow area.  Note that we _do_ still
    1208             :         // need to invalidate if our row is not moving, because the cell might
    1209             :         // span out of this row, so invalidating our row rect won't do enough.
    1210           0 :         if (aRowOffset == 0) {
    1211           0 :           InvalidateFrame();
    1212             :         }
    1213           0 :         cRect.BSize(wm) = 0;
    1214           0 :         cellFrame->SetRect(wm, cRect, containerSize);
    1215           0 :         cellFrame = cellFrame->GetNextCell();
    1216             :       }
    1217             :     } else {
    1218           0 :       shift += tableFrame->GetRowSpacing(GetRowIndex());
    1219             :     }
    1220           0 :     rowRect.BSize(wm) = 0;
    1221             :   }
    1222             :   else { // row is not collapsed
    1223             :     // remember the col index of the previous cell to handle rowspans into this
    1224             :     // row
    1225           0 :     int32_t prevColIndex = -1;
    1226           0 :     nscoord iPos = 0; // running total of children inline-axis offset
    1227             :     nsTableFrame* fifTable =
    1228           0 :       static_cast<nsTableFrame*>(tableFrame->FirstInFlow());
    1229             : 
    1230           0 :     for (nsIFrame* kidFrame : mFrames) {
    1231           0 :       nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
    1232           0 :       if (cellFrame) {
    1233             :         int32_t cellColIndex;
    1234           0 :         cellFrame->GetColIndex(cellColIndex);
    1235           0 :         int32_t cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame);
    1236             : 
    1237             :         // If the adjacent cell is in a prior row (because of a rowspan) add in
    1238             :         // the space
    1239           0 :         if (prevColIndex != (cellColIndex - 1)) {
    1240           0 :           iPos += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan,
    1241             :                                   *tableFrame, true);
    1242             :         }
    1243           0 :         LogicalRect cRect(wm, iPos, 0, 0, rowRect.BSize(wm));
    1244             : 
    1245             :         // remember the last (iend-wards-most) column this cell spans into
    1246           0 :         prevColIndex = cellColIndex + cellColSpan - 1;
    1247           0 :         int32_t actualColSpan = cellColSpan;
    1248           0 :         bool isVisible = false;
    1249           0 :         for (int32_t colIdx = cellColIndex; actualColSpan > 0;
    1250             :              colIdx++, actualColSpan--) {
    1251             : 
    1252           0 :           nsTableColFrame* colFrame = tableFrame->GetColFrame(colIdx);
    1253           0 :           const nsStyleVisibility* colVis = colFrame->StyleVisibility();
    1254             :           bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE ==
    1255           0 :                                 colVis->mVisible);
    1256           0 :           nsIFrame* cgFrame = colFrame->GetParent();
    1257           0 :           const nsStyleVisibility* groupVis = cgFrame->StyleVisibility();
    1258             :           bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE ==
    1259           0 :                                   groupVis->mVisible);
    1260           0 :           bool isCollapsed = collapseCol || collapseGroup;
    1261           0 :           if (!isCollapsed) {
    1262           0 :             cRect.ISize(wm) += fifTable->GetColumnISizeFromFirstInFlow(colIdx);
    1263           0 :             isVisible = true;
    1264           0 :             if ((actualColSpan > 1)) {
    1265             :               nsTableColFrame* nextColFrame =
    1266           0 :                 tableFrame->GetColFrame(colIdx + 1);
    1267             :               const nsStyleVisibility* nextColVis =
    1268           0 :               nextColFrame->StyleVisibility();
    1269           0 :               if ( (NS_STYLE_VISIBILITY_COLLAPSE != nextColVis->mVisible) &&
    1270           0 :                   tableFrame->ColumnHasCellSpacingBefore(colIdx + 1)) {
    1271           0 :                 cRect.ISize(wm) += tableFrame->GetColSpacing(cellColIndex);
    1272             :               }
    1273             :             }
    1274             :           }
    1275             :         }
    1276           0 :         iPos += cRect.ISize(wm);
    1277           0 :         if (isVisible) {
    1278           0 :           iPos += tableFrame->GetColSpacing(cellColIndex);
    1279             :         }
    1280           0 :         int32_t actualRowSpan = tableFrame->GetEffectiveRowSpan(*cellFrame);
    1281           0 :         nsTableRowFrame* rowFrame = GetNextRow();
    1282           0 :         for (actualRowSpan--; actualRowSpan > 0 && rowFrame; actualRowSpan--) {
    1283           0 :           const nsStyleVisibility* nextRowVis = rowFrame->StyleVisibility();
    1284             :           bool collapseNextRow = (NS_STYLE_VISIBILITY_COLLAPSE ==
    1285           0 :                                     nextRowVis->mVisible);
    1286           0 :           if (!collapseNextRow) {
    1287             :             LogicalRect nextRect = rowFrame->GetLogicalRect(wm,
    1288           0 :                                                             containerSize);
    1289           0 :             cRect.BSize(wm) +=
    1290           0 :               nextRect.BSize(wm) +
    1291           0 :               tableFrame->GetRowSpacing(rowFrame->GetRowIndex());
    1292             :           }
    1293           0 :           rowFrame = rowFrame->GetNextRow();
    1294             :         }
    1295             : 
    1296           0 :         nsRect oldCellRect = cellFrame->GetRect();
    1297             :         LogicalPoint oldCellNormalPos =
    1298           0 :           cellFrame->GetLogicalNormalPosition(wm, containerSize);
    1299             : 
    1300           0 :         nsRect oldCellVisualOverflow = cellFrame->GetVisualOverflowRect();
    1301             : 
    1302           0 :         if (aRowOffset == 0 && cRect.Origin(wm) != oldCellNormalPos) {
    1303             :           // We're moving the cell.  Invalidate the old overflow area
    1304           0 :           cellFrame->InvalidateFrameSubtree();
    1305             :         }
    1306             : 
    1307           0 :         cellFrame->MovePositionBy(wm, cRect.Origin(wm) - oldCellNormalPos);
    1308           0 :         cellFrame->SetSize(wm, cRect.Size(wm));
    1309             : 
    1310             :         // XXXbz This looks completely bogus in the cases when we didn't
    1311             :         // collapse the cell!
    1312           0 :         LogicalRect cellBounds(wm, 0, 0, cRect.ISize(wm), cRect.BSize(wm));
    1313             :         nsRect cellPhysicalBounds =
    1314           0 :           cellBounds.GetPhysicalRect(wm, containerSize);
    1315           0 :         nsOverflowAreas cellOverflow(cellPhysicalBounds, cellPhysicalBounds);
    1316           0 :         cellFrame->FinishAndStoreOverflow(cellOverflow,
    1317           0 :                                           cRect.Size(wm).GetPhysicalSize(wm));
    1318           0 :         nsTableFrame::RePositionViews(cellFrame);
    1319           0 :         ConsiderChildOverflow(overflow, cellFrame);
    1320             : 
    1321           0 :         if (aRowOffset == 0) {
    1322             :           nsTableFrame::InvalidateTableFrame(cellFrame, oldCellRect,
    1323           0 :                                              oldCellVisualOverflow, false);
    1324             :         }
    1325             :       }
    1326             :     }
    1327             :   }
    1328             : 
    1329           0 :   SetRect(wm, rowRect, containerSize);
    1330           0 :   overflow.UnionAllWith(nsRect(0, 0, rowRect.Width(wm), rowRect.Height(wm)));
    1331           0 :   FinishAndStoreOverflow(overflow, rowRect.Size(wm).GetPhysicalSize(wm));
    1332             : 
    1333           0 :   nsTableFrame::RePositionViews(this);
    1334           0 :   nsTableFrame::InvalidateTableFrame(this, oldRect, oldVisualOverflow, false);
    1335           0 :   return shift;
    1336             : }
    1337             : 
    1338             : /*
    1339             :  * The following method is called by the row group frame's SplitRowGroup()
    1340             :  * when it creates a continuing cell frame and wants to insert it into the
    1341             :  * row's child list.
    1342             :  */
    1343             : void
    1344           0 : nsTableRowFrame::InsertCellFrame(nsTableCellFrame* aFrame,
    1345             :                                  int32_t           aColIndex)
    1346             : {
    1347             :   // Find the cell frame where col index < aColIndex
    1348           0 :   nsTableCellFrame* priorCell = nullptr;
    1349           0 :   for (nsIFrame* child : mFrames) {
    1350           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(child);
    1351           0 :     if (cellFrame) {
    1352             :       int32_t colIndex;
    1353           0 :       cellFrame->GetColIndex(colIndex);
    1354           0 :       if (colIndex < aColIndex) {
    1355           0 :         priorCell = cellFrame;
    1356             :       }
    1357           0 :       else break;
    1358             :     }
    1359             :   }
    1360           0 :   mFrames.InsertFrame(this, priorCell, aFrame);
    1361           0 : }
    1362             : 
    1363             : nsTableRowFrame*
    1364           0 : nsTableRowFrame::GetNextRow() const
    1365             : {
    1366           0 :   nsIFrame* childFrame = GetNextSibling();
    1367           0 :   while (childFrame) {
    1368           0 :     nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
    1369           0 :     if (rowFrame) {
    1370           0 :           NS_ASSERTION(mozilla::StyleDisplay::TableRow == childFrame->StyleDisplay()->mDisplay,
    1371             :                  "wrong display type on rowframe");
    1372           0 :       return rowFrame;
    1373             :     }
    1374           0 :     childFrame = childFrame->GetNextSibling();
    1375             :   }
    1376           0 :   return nullptr;
    1377             : }
    1378             : 
    1379           0 : NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RowUnpaginatedHeightProperty, nscoord)
    1380             : 
    1381             : void
    1382           0 : nsTableRowFrame::SetUnpaginatedBSize(nsPresContext* aPresContext,
    1383             :                                      nscoord        aValue)
    1384             : {
    1385           0 :   NS_ASSERTION(!GetPrevInFlow(), "program error");
    1386             :   // Set the property
    1387           0 :   SetProperty(RowUnpaginatedHeightProperty(), aValue);
    1388           0 : }
    1389             : 
    1390             : nscoord
    1391           0 : nsTableRowFrame::GetUnpaginatedBSize()
    1392             : {
    1393           0 :   return GetProperty(RowUnpaginatedHeightProperty());
    1394             : }
    1395             : 
    1396           0 : void nsTableRowFrame::SetContinuousBCBorderWidth(LogicalSide aForSide,
    1397             :                                                  BCPixelSize aPixelValue)
    1398             : {
    1399           0 :   switch (aForSide) {
    1400             :     case eLogicalSideIEnd:
    1401           0 :       mIEndContBorderWidth = aPixelValue;
    1402           0 :       return;
    1403             :     case eLogicalSideBStart:
    1404           0 :       mBStartContBorderWidth = aPixelValue;
    1405           0 :       return;
    1406             :     case eLogicalSideIStart:
    1407           0 :       mIStartContBorderWidth = aPixelValue;
    1408           0 :       return;
    1409             :     default:
    1410           0 :       NS_ERROR("invalid LogicalSide arg");
    1411             :   }
    1412             : }
    1413             : #ifdef ACCESSIBILITY
    1414             : a11y::AccType
    1415           0 : nsTableRowFrame::AccessibleType()
    1416             : {
    1417           0 :   return a11y::eHTMLTableRowType;
    1418             : }
    1419             : #endif
    1420             : /**
    1421             :  * Sets the NS_ROW_HAS_CELL_WITH_STYLE_BSIZE bit to indicate whether
    1422             :  * this row has any cells that have non-auto-bsize.  (Row-spanning
    1423             :  * cells are ignored.)
    1424             :  */
    1425           0 : void nsTableRowFrame::InitHasCellWithStyleBSize(nsTableFrame* aTableFrame)
    1426             : {
    1427           0 :   WritingMode wm = GetWritingMode();
    1428             : 
    1429           0 :   for (nsIFrame* kidFrame : mFrames) {
    1430           0 :     nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
    1431           0 :     if (!cellFrame) {
    1432           0 :       NS_NOTREACHED("Table row has a non-cell child.");
    1433           0 :       continue;
    1434             :     }
    1435             :     // Ignore row-spanning cells
    1436           0 :     const nsStyleCoord &cellBSize = cellFrame->StylePosition()->BSize(wm);
    1437           0 :     if (aTableFrame->GetEffectiveRowSpan(*cellFrame) == 1 &&
    1438           0 :         cellBSize.GetUnit() != eStyleUnit_Auto &&
    1439             :          /* calc() with percentages treated like 'auto' */
    1440           0 :         (!cellBSize.IsCalcUnit() || !cellBSize.HasPercent())) {
    1441           0 :       AddStateBits(NS_ROW_HAS_CELL_WITH_STYLE_BSIZE);
    1442           0 :       return;
    1443             :     }
    1444             :   }
    1445           0 :   RemoveStateBits(NS_ROW_HAS_CELL_WITH_STYLE_BSIZE);
    1446             : }
    1447             : 
    1448             : void
    1449           0 : nsTableRowFrame::InvalidateFrame(uint32_t aDisplayItemKey)
    1450             : {
    1451           0 :   nsIFrame::InvalidateFrame(aDisplayItemKey);
    1452           0 :   GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
    1453           0 : }
    1454             : 
    1455             : void
    1456           0 : nsTableRowFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
    1457             : {
    1458           0 :   nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
    1459             :   // If we have filters applied that would affects our bounds, then
    1460             :   // we get an inactive layer created and this is computed
    1461             :   // within FrameLayerBuilder
    1462           0 :   GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
    1463           0 : }
    1464             : 
    1465             : /* ----- global methods ----- */
    1466             : 
    1467             : nsTableRowFrame*
    1468           0 : NS_NewTableRowFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    1469             : {
    1470           0 :   return new (aPresShell) nsTableRowFrame(aContext);
    1471             : }
    1472             : 
    1473           0 : NS_IMPL_FRAMEARENA_HELPERS(nsTableRowFrame)
    1474             : 
    1475             : #ifdef DEBUG_FRAME_DUMP
    1476             : nsresult
    1477           0 : nsTableRowFrame::GetFrameName(nsAString& aResult) const
    1478             : {
    1479           0 :   return MakeFrameName(NS_LITERAL_STRING("TableRow"), aResult);
    1480             : }
    1481             : #endif

Generated by: LCOV version 1.13