tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsTableFrame.h (35636B)


      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 #ifndef nsTableFrame_h__
      6 #define nsTableFrame_h__
      7 
      8 #include "TableArea.h"
      9 #include "celldata.h"
     10 #include "nsCellMap.h"
     11 #include "nsContainerFrame.h"
     12 #include "nsDisplayList.h"
     13 #include "nsGkAtoms.h"
     14 #include "nsStyleConsts.h"
     15 #include "nscore.h"
     16 
     17 struct BCPaintBorderAction;
     18 class nsTableCellFrame;
     19 class nsTableCellMap;
     20 class nsTableColFrame;
     21 class nsTableRowGroupFrame;
     22 class nsTableRowFrame;
     23 class nsTableColGroupFrame;
     24 class nsITableLayoutStrategy;
     25 
     26 namespace mozilla {
     27 class LogicalMargin;
     28 class PresShell;
     29 class WritingMode;
     30 struct TableBCData;
     31 struct TableReflowInput;
     32 
     33 namespace layers {
     34 class StackingContextHelper;
     35 }
     36 
     37 // An input to nsTableFrame::ReflowTable() and TableReflowInput.
     38 enum class TableReflowMode : uint8_t {
     39  // A reflow to measure the block-size of the table. We use this value to
     40  // request an unconstrained available block in the first reflow if a second
     41  // special block-size reflow is needed later.
     42  Measuring,
     43 
     44  // A final reflow with the available block-size in the table frame's
     45  // ReflowInput.
     46  Final,
     47 };
     48 
     49 class nsDisplayTableItem : public nsPaintedDisplayItem {
     50 public:
     51  nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     52      : nsPaintedDisplayItem(aBuilder, aFrame) {}
     53 
     54  // With collapsed borders, parts of the collapsed border can extend outside
     55  // the table part frames, so allow this display element to blow out to our
     56  // overflow rect. This is also useful for row frames that have spanning
     57  // cells extending outside them.
     58  nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
     59 };
     60 
     61 class nsDisplayTableBackgroundSet {
     62 public:
     63  nsDisplayList* ColGroupBackgrounds() { return &mColGroupBackgrounds; }
     64 
     65  nsDisplayList* ColBackgrounds() { return &mColBackgrounds; }
     66 
     67  nsDisplayTableBackgroundSet(nsDisplayListBuilder* aBuilder, nsIFrame* aTable);
     68 
     69  ~nsDisplayTableBackgroundSet() {
     70    mozilla::DebugOnly<nsDisplayTableBackgroundSet*> result =
     71        mBuilder->SetTableBackgroundSet(mPrevTableBackgroundSet);
     72    MOZ_ASSERT(result == this);
     73  }
     74 
     75  /**
     76   * Move all display items in our lists to top of the corresponding lists in
     77   * the destination.
     78   */
     79  void MoveTo(const nsDisplayListSet& aDestination) {
     80    aDestination.BorderBackground()->AppendToTop(ColGroupBackgrounds());
     81    aDestination.BorderBackground()->AppendToTop(ColBackgrounds());
     82  }
     83 
     84  void AddColumn(nsTableColFrame* aFrame) { mColumns.AppendElement(aFrame); }
     85 
     86  nsTableColFrame* GetColForIndex(int32_t aIndex) { return mColumns[aIndex]; }
     87 
     88  const nsPoint& TableToReferenceFrame() { return mToReferenceFrame; }
     89 
     90  const nsRect& GetDirtyRect() { return mDirtyRect; }
     91 
     92  const DisplayItemClipChain* GetTableClipChain() {
     93    return mCombinedTableClipChain;
     94  }
     95 
     96  const ActiveScrolledRoot* GetTableASR() { return mTableASR; }
     97 
     98 private:
     99  // This class is only used on stack, so we don't have to worry about leaking
    100  // it.  Don't let us be heap-allocated!
    101  void* operator new(size_t sz) noexcept(true);
    102 
    103 protected:
    104  nsDisplayListBuilder* mBuilder;
    105  nsDisplayTableBackgroundSet* mPrevTableBackgroundSet;
    106 
    107  nsDisplayList mColGroupBackgrounds;
    108  nsDisplayList mColBackgrounds;
    109 
    110  nsTArray<nsTableColFrame*> mColumns;
    111  nsPoint mToReferenceFrame;
    112  nsRect mDirtyRect;
    113 
    114  const DisplayItemClipChain* mCombinedTableClipChain;
    115  const ActiveScrolledRoot* mTableASR;
    116 };
    117 
    118 }  // namespace mozilla
    119 
    120 /* ========================================================================== */
    121 
    122 enum nsTableColType {
    123  eColContent = 0,            // there is real col content associated
    124  eColAnonymousCol = 1,       // the result of a span on a col
    125  eColAnonymousColGroup = 2,  // the result of a span on a col group
    126  eColAnonymousCell = 3       // the result of a cell alone
    127 };
    128 
    129 /**
    130 * nsTableFrame maps the inner portion of a table (everything except captions.)
    131 * Used as a pseudo-frame within nsTableWrapperFrame, it may also be used
    132 * stand-alone as the top-level frame.
    133 *
    134 * The principal child list contains row group frames. There is also an
    135 * additional child list, FrameChildListID::ColGroup, which contains the col
    136 * group frames.
    137 */
    138 class nsTableFrame : public nsContainerFrame {
    139  typedef mozilla::image::ImgDrawResult ImgDrawResult;
    140  typedef mozilla::WritingMode WritingMode;
    141  typedef mozilla::LogicalMargin LogicalMargin;
    142 
    143 public:
    144  NS_DECL_FRAMEARENA_HELPERS(nsTableFrame)
    145 
    146  using TablePartsArray = nsTArray<nsContainerFrame*>;
    147  NS_DECLARE_FRAME_PROPERTY_DELETABLE(PositionedTablePartsProperty,
    148                                      TablePartsArray)
    149 
    150  /** nsTableWrapperFrame has intimate knowledge of the inner table frame */
    151  friend class nsTableWrapperFrame;
    152 
    153  /**
    154   * instantiate a new instance of nsTableRowFrame.
    155   *
    156   * @param aPresShell the pres shell for this frame
    157   *
    158   * @return           the frame that was created
    159   */
    160  friend nsTableFrame* NS_NewTableFrame(mozilla::PresShell* aPresShell,
    161                                        ComputedStyle* aStyle);
    162 
    163  /** sets defaults for table-specific style.
    164   * @see nsIFrame::Init
    165   */
    166  void Init(nsIContent* aContent, nsContainerFrame* aParent,
    167            nsIFrame* aPrevInFlow) override;
    168 
    169  // Return true if aParentReflowInput.frame or any of its ancestors within
    170  // the containing table have non-auto bsize. (e.g. pct or fixed bsize)
    171  static bool AncestorsHaveStyleBSize(const ReflowInput& aParentReflowInput);
    172 
    173  // See if a special bsize reflow will occur due to having a pct bsize when
    174  // the pct bsize basis may not yet be valid.
    175  static void CheckRequestSpecialBSizeReflow(const ReflowInput& aReflowInput);
    176 
    177  // Notify the frame and its ancestors (up to the containing table) that a
    178  // special height reflow will occur.
    179  static void RequestSpecialBSizeReflow(const ReflowInput& aReflowInput);
    180 
    181  static bool PageBreakAfter(nsIFrame* aSourceFrame, nsIFrame* aNextFrame);
    182 
    183  // Register or deregister a positioned table part with its nsTableFrame.
    184  // These objects will be visited by FixupPositionedTableParts after reflow is
    185  // complete. (See that function for more explanation.) Should be called
    186  // during style recalculation.
    187  static void PositionedTablePartMaybeChanged(
    188      nsContainerFrame*, mozilla::ComputedStyle* aOldStyle);
    189 
    190  // Unregister a positioned table part with its nsTableFrame, if needed.
    191  static void MaybeUnregisterPositionedTablePart(nsContainerFrame* aFrame);
    192 
    193  /*
    194   * Notification that rowspan or colspan has changed for content inside a
    195   * table cell
    196   */
    197  void RowOrColSpanChanged(nsTableCellFrame* aCellFrame);
    198 
    199  /** @see nsIFrame::DestroyFrom */
    200  void Destroy(DestroyContext&) override;
    201 
    202  /** @see nsIFrame::DidSetComputedStyle */
    203  void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
    204 
    205  void SetInitialChildList(ChildListID aListID,
    206                           nsFrameList&& aChildList) override;
    207  void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
    208  void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
    209                    const nsLineList::iterator* aPrevFrameLine,
    210                    nsFrameList&& aFrameList) override;
    211  void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override;
    212 
    213  nsMargin GetUsedBorder() const override;
    214  nsMargin GetUsedPadding() const override;
    215  nsMargin GetUsedMargin() const override;
    216 
    217  /** helper method to find the table parent of any table frame object */
    218  static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame);
    219 
    220  // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
    221  // of type aChildType.
    222  static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
    223                                      nsIFrame* aPriorChildFrame,
    224                                      mozilla::LayoutFrameType aChildType);
    225  bool IsAutoBSize(mozilla::WritingMode aWM);
    226 
    227  /** @return true if aDisplayType represents a rowgroup of any sort
    228   * (header, footer, or body)
    229   */
    230  bool IsRowGroup(mozilla::StyleDisplay aDisplayType) const;
    231 
    232  const nsFrameList& GetChildList(ChildListID aListID) const override;
    233  void GetChildLists(nsTArray<ChildList>* aLists) const override;
    234 
    235  void BuildDisplayList(nsDisplayListBuilder* aBuilder,
    236                        const nsDisplayListSet& aLists) override;
    237 
    238  /** Get the outer half (i.e., the part outside the height and width of
    239   *  the table) of the largest segment (?) of border-collapsed border on
    240   *  the table on each side, or 0 for non border-collapsed tables.
    241   */
    242  LogicalMargin GetOuterBCBorder(const WritingMode aWM) const;
    243 
    244  /**
    245   * Emplace our border and padding in aBorder and aPadding if we are
    246   * border-collapsed. Otherwise, do nothing.
    247   */
    248  void GetCollapsedBorderPadding(
    249      mozilla::Maybe<mozilla::LogicalMargin>& aBorder,
    250      mozilla::Maybe<mozilla::LogicalMargin>& aPadding) const;
    251 
    252  friend class nsDelayedCalcBCBorders;
    253 
    254  void AddBCDamageArea(const mozilla::TableArea& aValue);
    255  bool BCRecalcNeeded(ComputedStyle* aOldComputedStyle,
    256                      ComputedStyle* aNewComputedStyle);
    257  void PaintBCBorders(DrawTarget& aDrawTarget, const nsRect& aDirtyRect);
    258  void CreateWebRenderCommandsForBCBorders(
    259      mozilla::wr::DisplayListBuilder& aBuilder,
    260      const mozilla::layers::StackingContextHelper& aSc,
    261      const nsRect& aVisibleRect, const nsPoint& aOffsetToReferenceFrame);
    262 
    263  void MarkIntrinsicISizesDirty() override;
    264  // For border-collapse tables, the caller must not add padding and
    265  // border to the results of these functions.
    266  nscoord IntrinsicISize(const mozilla::IntrinsicSizeInput& aInput,
    267                         mozilla::IntrinsicISizeType aType) override;
    268  IntrinsicSizeOffsetData IntrinsicISizeOffsets(
    269      nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override;
    270 
    271  SizeComputationResult ComputeSize(
    272      const SizeComputationInput& aSizingInput, mozilla::WritingMode aWM,
    273      const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
    274      const mozilla::LogicalSize& aMargin,
    275      const mozilla::LogicalSize& aBorderPadding,
    276      const mozilla::StyleSizeOverrides& aSizeOverrides,
    277      mozilla::ComputeSizeFlags aFlags) override;
    278 
    279  mozilla::LogicalSize ComputeAutoSize(
    280      const SizeComputationInput& aSizingInput, mozilla::WritingMode aWM,
    281      const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
    282      const mozilla::LogicalSize& aMargin,
    283      const mozilla::LogicalSize& aBorderPadding,
    284      const mozilla::StyleSizeOverrides& aSizeOverrides,
    285      mozilla::ComputeSizeFlags aFlags) override;
    286 
    287  /**
    288   * A copy of nsIFrame::ShrinkISizeToFit that calls a different
    289   * GetPrefISize, since tables have two different ones.
    290   */
    291  nscoord TableShrinkISizeToFit(gfxContext* aRenderingContext,
    292                                nscoord aWidthInCB);
    293 
    294  // XXXldb REWRITE THIS COMMENT!
    295  // clang-format off
    296  /**
    297   * Inner tables are reflowed in two steps.
    298   * <pre>
    299   * if mFirstPassValid is false, this is our first time through since content was last changed
    300   *   set pass to 1
    301   *   do pass 1
    302   *     get min/max info for all cells in an infinite space
    303   *   do column balancing
    304   *   set mFirstPassValid to true
    305   *   do pass 2
    306   *     use column widths to Reflow cells
    307   * </pre>
    308   *
    309   * @see nsIFrame::Reflow
    310   */
    311  // clang-format on
    312  void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
    313              const ReflowInput& aReflowInput,
    314              nsReflowStatus& aStatus) override;
    315 
    316  void ReflowTable(ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
    317                   const LogicalMargin& aBorderPadding,
    318                   mozilla::TableReflowMode aReflowMode,
    319                   nsIFrame*& aLastChildReflowed, nsReflowStatus& aStatus);
    320 
    321  nsFrameList& GetColGroups();
    322 
    323  ComputedStyle* GetParentComputedStyle(
    324      nsIFrame** aProviderFrame) const override;
    325 
    326 #ifdef DEBUG_FRAME_DUMP
    327  /** @see nsIFrame::GetFrameName */
    328  nsresult GetFrameName(nsAString& aResult) const override;
    329 #endif
    330 
    331  /** Return the isize of the column at aColIndex.
    332   *  This may only be called on the table's first-in-flow.
    333   */
    334  nscoord GetColumnISizeFromFirstInFlow(int32_t aColIndex);
    335 
    336  /** Helper to get the column spacing style value.
    337   *  The argument refers to the space between column aColIndex and column
    338   *  aColIndex + 1.  An index of -1 indicates the padding between the table
    339   *  and the left border, an index equal to the number of columns indicates
    340   *  the padding between the table and the right border.
    341   *
    342   *  Although in this class cell spacing does not depend on the index, it
    343   *  may be important for overriding classes.
    344   */
    345  virtual nscoord GetColSpacing(int32_t aColIndex);
    346 
    347  /** Helper to find the sum of the cell spacing between arbitrary columns.
    348   *  The argument refers to the space between column aColIndex and column
    349   *  aColIndex + 1.  An index of -1 indicates the padding between the table
    350   *  and the left border, an index equal to the number of columns indicates
    351   *  the padding between the table and the right border.
    352   *
    353   *  This method is equivalent to
    354   *  nscoord result = 0;
    355   *  for (i = aStartColIndex; i < aEndColIndex; i++) {
    356   *    result += GetColSpacing(i);
    357   *  }
    358   *  return result;
    359   */
    360  virtual nscoord GetColSpacing(int32_t aStartColIndex, int32_t aEndColIndex);
    361 
    362  /** Helper to get the row spacing style value.
    363   *  The argument refers to the space between row aRowIndex and row
    364   *  aRowIndex + 1.  An index of -1 indicates the padding between the table
    365   *  and the top border, an index equal to the number of rows indicates
    366   *  the padding between the table and the bottom border.
    367   *
    368   *  Although in this class cell spacing does not depend on the index, it
    369   *  may be important for overriding classes.
    370   */
    371  virtual nscoord GetRowSpacing(int32_t aRowIndex);
    372 
    373  /** Helper to find the sum of the cell spacing between arbitrary rows.
    374   *  The argument refers to the space between row aRowIndex and row
    375   *  aRowIndex + 1.  An index of -1 indicates the padding between the table
    376   *  and the top border, an index equal to the number of rows indicates
    377   *  the padding between the table and the bottom border.
    378   *
    379   *  This method is equivalent to
    380   *  nscoord result = 0;
    381   *  for (i = aStartRowIndex; i < aEndRowIndex; i++) {
    382   *    result += GetRowSpacing(i);
    383   *  }
    384   *  return result;
    385   */
    386  virtual nscoord GetRowSpacing(int32_t aStartRowIndex, int32_t aEndRowIndex);
    387 
    388 private:
    389  /* For the base implementation of nsTableFrame, cell spacing does not depend
    390   * on row/column indexing.
    391   */
    392  nscoord GetColSpacing();
    393  nscoord GetRowSpacing();
    394 
    395 public:
    396  nscoord SynthesizeFallbackBaseline(
    397      mozilla::WritingMode aWM,
    398      BaselineSharingGroup aBaselineGroup) const override;
    399  Maybe<nscoord> GetNaturalBaselineBOffset(
    400      mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup,
    401      BaselineExportContext) const override;
    402 
    403  /** return the row span of a cell, taking into account row span magic at the
    404   * bottom of a table. The row span equals the number of rows spanned by aCell
    405   * starting at aStartRowIndex, and can be smaller if aStartRowIndex is greater
    406   * than the row index in which aCell originates.
    407   *
    408   * @param aStartRowIndex the cell
    409   * @param aCell          the cell
    410   *
    411   * @return  the row span, correcting for row spans that extend beyond the
    412   * bottom of the table.
    413   */
    414  int32_t GetEffectiveRowSpan(int32_t aStartRowIndex,
    415                              const nsTableCellFrame& aCell) const;
    416  int32_t GetEffectiveRowSpan(const nsTableCellFrame& aCell,
    417                              nsCellMap* aCellMap = nullptr);
    418 
    419  /** return the col span of a cell, taking into account col span magic at the
    420   * edge of a table.
    421   *
    422   * @param aCell      the cell
    423   *
    424   * @return  the col span, correcting for col spans that extend beyond the edge
    425   *          of the table.
    426   */
    427  int32_t GetEffectiveColSpan(const nsTableCellFrame& aCell,
    428                              nsCellMap* aCellMap = nullptr) const;
    429 
    430  /** indicate whether the row has more than one cell that either originates
    431   * or is spanned from the rows above
    432   */
    433  bool HasMoreThanOneCell(int32_t aRowIndex) const;
    434 
    435  /** return the column frame associated with aColIndex
    436   * returns nullptr if the col frame has not yet been allocated, or if
    437   * aColIndex is out of range
    438   */
    439  nsTableColFrame* GetColFrame(int32_t aColIndex) const;
    440 
    441  /** Insert a col frame reference into the colframe cache and adapt the cellmap
    442   * @param aColFrame    - the column frame
    443   * @param aColIndex    - index where the column should be inserted into the
    444   *                       colframe cache
    445   */
    446  void InsertCol(nsTableColFrame& aColFrame, int32_t aColIndex);
    447 
    448  nsTableColGroupFrame* CreateSyntheticColGroupFrame();
    449 
    450  int32_t DestroyAnonymousColFrames(int32_t aNumFrames);
    451 
    452  // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our
    453  // last synthetic colgroup.  If we have no such colgroup, then create one.
    454  void AppendAnonymousColFrames(int32_t aNumColsToAdd);
    455 
    456  // Append aNumColsToAdd anonymous col frames of type aColType to
    457  // aColGroupFrame.  If aAddToTable is true, also call AddColsToTable on the
    458  // new cols.
    459  void AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame,
    460                                int32_t aNumColsToAdd, nsTableColType aColType,
    461                                bool aAddToTable);
    462 
    463  void MatchCellMapToColCache(nsTableCellMap* aCellMap);
    464 
    465  void DidResizeColumns();
    466 
    467  void AppendCell(nsTableCellFrame& aCellFrame, int32_t aRowIndex);
    468 
    469  void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, int32_t aRowIndex,
    470                   int32_t aColIndexBefore);
    471 
    472  void RemoveCell(nsTableCellFrame* aCellFrame, int32_t aRowIndex);
    473 
    474  void AppendRows(nsTableRowGroupFrame* aRowGroupFrame, int32_t aRowIndex,
    475                  nsTArray<nsTableRowFrame*>& aRowFrames);
    476 
    477  int32_t InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
    478                     nsTArray<nsTableRowFrame*>& aFrames, int32_t aRowIndex,
    479                     bool aConsiderSpans);
    480 
    481  void RemoveRows(nsTableRowFrame& aFirstRowFrame, int32_t aNumRowsToRemove,
    482                  bool aConsiderSpans);
    483 
    484  /** Insert multiple rowgroups into the table cellmap handling
    485   * @param aRowGroups - iterator that iterates over the rowgroups to insert
    486   */
    487  void InsertRowGroups(const nsFrameList::Slice& aRowGroups);
    488 
    489  void InsertColGroups(int32_t aStartColIndex,
    490                       const nsFrameList::Slice& aColgroups);
    491 
    492  void RemoveCol(nsTableColGroupFrame* aColGroupFrame, int32_t aColIndex,
    493                 bool aRemoveFromCache, bool aRemoveFromCellMap);
    494 
    495  bool ColumnHasCellSpacingBefore(int32_t aColIndex) const;
    496 
    497  bool HasPctCol() const;
    498  void SetHasPctCol(bool aValue);
    499 
    500  bool HasCellSpanningPctCol() const;
    501  void SetHasCellSpanningPctCol(bool aValue);
    502 
    503  /**
    504   * To be called on a frame by its parent after setting its size/position and
    505   * calling DidReflow (possibly via FinishReflowChild()).  This can also be
    506   * used for child frames which are not being reflowed but did have their size
    507   * or position changed.
    508   *
    509   * @param aFrame The frame to invalidate
    510   * @param aOrigRect The original rect of aFrame (before the change).
    511   * @param aOrigInkOverflow The original overflow rect of aFrame.
    512   * @param aIsFirstReflow True if the size/position change is due to the
    513   *                       first reflow of aFrame.
    514   */
    515  static void InvalidateTableFrame(nsIFrame* aFrame, const nsRect& aOrigRect,
    516                                   const nsRect& aOrigInkOverflow,
    517                                   bool aIsFirstReflow);
    518 
    519  bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
    520 
    521  // Return our wrapper frame.
    522  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
    523 
    524 protected:
    525  static void UpdateStyleOfOwnedAnonBoxesForTableWrapper(
    526      nsIFrame* aOwningFrame, nsIFrame* aWrapperFrame,
    527      mozilla::ServoRestyleState& aRestyleState);
    528 
    529  /** protected constructor.
    530   * @see NewFrame
    531   */
    532  explicit nsTableFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
    533                        ClassID aID = kClassID);
    534 
    535  virtual ~nsTableFrame();
    536 
    537  void InitChildReflowInput(ReflowInput& aReflowInput);
    538 
    539  LogicalSides GetLogicalSkipSides() const override;
    540 
    541  void IterateBCBorders(BCPaintBorderAction& aAction, const nsRect& aDirtyRect);
    542 
    543 public:
    544  bool IsRowInserted() const;
    545  void SetRowInserted(bool aValue);
    546 
    547 protected:
    548  // A helper function to reflow a header or footer with unconstrained
    549  // block-size to see if it should be made repeatable.
    550  // @return the desired block-size for a header or footer.
    551  nscoord SetupHeaderFooterChild(const mozilla::TableReflowInput& aReflowInput,
    552                                 nsTableRowGroupFrame* aFrame);
    553 
    554  void ReflowChildren(mozilla::TableReflowInput& aReflowInput,
    555                      nsReflowStatus& aStatus, nsIFrame*& aLastChildReflowed,
    556                      mozilla::OverflowAreas& aOverflowAreas);
    557 
    558  // This calls the col group and column reflow methods, which do two things:
    559  //  (1) set all the dimensions to 0
    560  //  (2) notify the table about colgroups or columns with hidden visibility
    561  void ReflowColGroups(gfxContext* aRenderingContext);
    562 
    563  /** return the isize of the table taking into account visibility collapse
    564   * on columns and colgroups
    565   * @param aBorderPadding  the border and padding of the table
    566   */
    567  nscoord GetCollapsedISize(const WritingMode aWM,
    568                            const LogicalMargin& aBorderPadding);
    569 
    570  /** Adjust the table for visibility.collapse set on rowgroups, rows,
    571   * colgroups and cols
    572   * @param aDesiredSize    the metrics of the table
    573   * @param aBorderPadding  the border and padding of the table
    574   */
    575  void AdjustForCollapsingRowsCols(ReflowOutput& aDesiredSize,
    576                                   const WritingMode aWM,
    577                                   const LogicalMargin& aBorderPadding);
    578 
    579  /** FixupPositionedTableParts is called at the end of table reflow to reflow
    580   *  the absolutely positioned descendants of positioned table parts. This is
    581   *  necessary because the dimensions of table parts may change after they've
    582   *  been reflowed (e.g. in AdjustForCollapsingRowsCols).
    583   */
    584  void FixupPositionedTableParts(nsPresContext* aPresContext,
    585                                 ReflowOutput& aDesiredSize,
    586                                 const ReflowInput& aReflowInput);
    587 
    588  nsITableLayoutStrategy* LayoutStrategy() const {
    589    return static_cast<nsTableFrame*>(FirstInFlow())
    590        ->mTableLayoutStrategy.get();
    591  }
    592 
    593  // Helper for InsertFrames.
    594  void HomogenousInsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
    595                              nsFrameList& aFrameList);
    596 
    597 private:
    598  /* Handle a row that got inserted during reflow.  aNewHeight is the
    599     new height of the table after reflow. */
    600  void ProcessRowInserted(nscoord aNewHeight);
    601 
    602 protected:
    603  // Calculate the border-box block-size of this table, with the min-block-size,
    604  // max-block-size, and intrinsic border-box block considered.
    605  nscoord CalcBorderBoxBSize(const ReflowInput& aReflowInput,
    606                             const LogicalMargin& aBorderPadding,
    607                             nscoord aIntrinsicBorderBoxBSize);
    608 
    609  // Calculate the desired block-size of this table.
    610  //
    611  // Note: this method is accurate after the children are reflowed. It might
    612  // distribute extra block-size to table rows if the table has a specified
    613  // block-size larger than the intrinsic block-size.
    614  nscoord CalcDesiredBSize(const ReflowInput& aReflowInput,
    615                           const LogicalMargin& aBorderPadding,
    616                           const nsReflowStatus& aStatus);
    617 
    618  // The following is a helper for CalcDesiredBSize
    619  void DistributeBSizeToRows(const ReflowInput& aReflowInput, nscoord aAmount);
    620 
    621  void PlaceChild(mozilla::TableReflowInput& aReflowInput, nsIFrame* aKidFrame,
    622                  const ReflowInput& aKidReflowInput,
    623                  const mozilla::LogicalPoint& aKidPosition,
    624                  const nsSize& aContainerSize, ReflowOutput& aKidDesiredSize,
    625                  const nsRect& aOriginalKidRect,
    626                  const nsRect& aOriginalKidInkOverflow);
    627  void PlaceRepeatedFooter(mozilla::TableReflowInput& aReflowInput,
    628                           nsTableRowGroupFrame* aTfoot, nscoord aFooterBSize);
    629 
    630 public:
    631  using RowGroupArray = AutoTArray<nsTableRowGroupFrame*, 8>;
    632 
    633 protected:
    634  // Push all our non-repeatable child frames from the aRowGroups array, in
    635  // order, starting from the frame at aPushFrom to the end of the array. The
    636  // pushed frames are put on our overflow list. This is a table specific
    637  // version that takes into account repeated header and footer frames when
    638  // continuing table frames.
    639  void PushChildrenToOverflow(const RowGroupArray& aRowGroups,
    640                              size_t aPushFrom);
    641 
    642 public:
    643  // Return the children frames in the display order (e.g. thead before tbodies
    644  // before tfoot). If there are multiple theads or tfoots, all but the first
    645  // one are treated as tbodies instead.
    646  //
    647  // @param aHead Outparam for the first thead if there is any.
    648  // @param aFoot Outparam for the first tfoot if there is any.
    649  RowGroupArray OrderedRowGroups(nsTableRowGroupFrame** aHead = nullptr,
    650                                 nsTableRowGroupFrame** aFoot = nullptr) const;
    651 
    652  // Returns true if there are any cells above the row at
    653  // aRowIndex and spanning into the row at aRowIndex, the number of
    654  // effective columns limits the search up to that column
    655  bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols);
    656 
    657  // Returns true if there is a cell originating in aRowIndex
    658  // which spans into the next row,  the number of effective
    659  // columns limits the search up to that column
    660  bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols);
    661 
    662 protected:
    663  bool HaveReflowedColGroups() const;
    664  void SetHaveReflowedColGroups(bool aValue);
    665 
    666 public:
    667  bool IsBorderCollapse() const;
    668 
    669  bool NeedToCalcBCBorders() const;
    670  void SetNeedToCalcBCBorders(bool aValue);
    671 
    672  bool NeedToCollapse() const;
    673  void SetNeedToCollapse(bool aValue);
    674 
    675  bool NeedToCalcHasBCBorders() const;
    676  void SetNeedToCalcHasBCBorders(bool aValue);
    677 
    678  void CalcHasBCBorders();
    679  bool HasBCBorders();
    680  void SetHasBCBorders(bool aValue);
    681 
    682  /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
    683   * state bit, which implies that all descendants are dirty.  The
    684   * GeometryDirty still implies that all the parts of the table are
    685   * dirty, but resizing optimizations should still apply to the
    686   * contents of the individual cells.
    687   */
    688  void SetGeometryDirty() { mBits.mGeometryDirty = true; }
    689  void ClearGeometryDirty() { mBits.mGeometryDirty = false; }
    690  bool IsGeometryDirty() const { return mBits.mGeometryDirty; }
    691 
    692  /** Get the cell map for this table frame.  It is not always mCellMap.
    693   * Only the firstInFlow has a legit cell map
    694   */
    695  nsTableCellMap* GetCellMap() const;
    696 
    697  /** Iterate over the row groups and adjust the row indices of all rows
    698   * whose index is >= aRowIndex.
    699   * @param aRowIndex   - start adjusting with this index
    700   * @param aAdjustment - shift the row index by this amount
    701   */
    702  void AdjustRowIndices(int32_t aRowIndex, int32_t aAdjustment);
    703 
    704  /** Reset the rowindices of all rows as they might have changed due to
    705   * rowgroup reordering, exclude new row group frames that show in the
    706   * reordering but are not yet inserted into the cellmap
    707   * @param aRowGroupsToExclude - an iterator that will produce the row groups
    708   *                              to exclude.
    709   */
    710  void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
    711 
    712  nsTArray<nsTableColFrame*>& GetColCache();
    713 
    714  mozilla::TableBCData* GetTableBCData() const;
    715 
    716 protected:
    717  void SetBorderCollapse(bool aValue);
    718 
    719  mozilla::TableBCData* GetOrCreateTableBCData();
    720  void SetFullBCDamageArea();
    721  void CalcBCBorders();
    722 
    723  void ExpandBCDamageArea(mozilla::TableArea& aRect) const;
    724 
    725  void SetColumnDimensions(nscoord aHeight, WritingMode aWM,
    726                           const LogicalMargin& aBorderPadding,
    727                           const nsSize& aContainerSize);
    728 
    729  int32_t CollectRows(nsIFrame* aFrame,
    730                      nsTArray<nsTableRowFrame*>& aCollection);
    731 
    732 public: /* ----- Cell Map public methods ----- */
    733  int32_t GetStartRowIndex(const nsTableRowGroupFrame* aRowGroupFrame) const;
    734 
    735  /** returns the number of rows in this table.
    736   */
    737  int32_t GetRowCount() const { return GetCellMap()->GetRowCount(); }
    738 
    739  /** returns the number of columns in this table after redundant columns have
    740   * been removed
    741   */
    742  int32_t GetEffectiveColCount() const;
    743 
    744  /* return the col count including dead cols */
    745  int32_t GetColCount() const { return GetCellMap()->GetColCount(); }
    746 
    747  // return the last col index which isn't of type eColAnonymousCell
    748  int32_t GetIndexOfLastRealCol();
    749 
    750  /** returns true if table-layout:auto  */
    751  bool IsAutoLayout();
    752 
    753 public:
    754  /* ---------- Row index management methods ------------ */
    755 
    756  /** Add the given index to the existing ranges of
    757   *  deleted row indices and merge ranges if, with the addition of the new
    758   *  index, they become consecutive.
    759   *  @param aDeletedRowStoredIndex - index of the row that was deleted
    760   *  Note - 'stored' index here refers to the index that was assigned to
    761   *  the row before any remove row operations were performed i.e. the
    762   *  value of mRowIndex and not the value returned by GetRowIndex()
    763   */
    764  void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex);
    765 
    766  /** Calculate the change that aStoredIndex must be increased/decreased by
    767   *  to get new index.
    768   *  Note that aStoredIndex is always the index of an undeleted row (since
    769   *  rows that have already been deleted can never call this method).
    770   *  @param aStoredIndex - The stored index value that must be adjusted
    771   *  Note - 'stored' index here refers to the index that was assigned to
    772   *  the row before any remove row operations were performed i.e. the
    773   *  value of mRowIndex and not the value returned by GetRowIndex()
    774   */
    775  int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex);
    776 
    777  /** Returns whether mDeletedRowIndexRanges is empty
    778   */
    779  bool IsDeletedRowIndexRangesEmpty() const {
    780    return mDeletedRowIndexRanges.empty();
    781  }
    782 
    783  bool IsDestroying() const { return mBits.mIsDestroying; }
    784 
    785 public:
    786 #ifdef DEBUG
    787  void Dump(bool aDumpRows, bool aDumpCols, bool aDumpCellMap);
    788 #endif
    789 
    790 protected:
    791  /**
    792   * Helper method for RemoveFrame.
    793   */
    794  void DoRemoveFrame(DestroyContext&, ChildListID, nsIFrame*);
    795 #ifdef DEBUG
    796  void DumpRowGroup(nsIFrame* aChildFrame);
    797 #endif
    798  // DATA MEMBERS
    799  AutoTArray<nsTableColFrame*, 8> mColFrames;
    800 
    801  struct TableBits {
    802    uint32_t mHaveReflowedColGroups : 1;  // have the col groups gotten their
    803                                          // initial reflow
    804    uint32_t mHasPctCol : 1;        // does any cell or col have a pct width
    805    uint32_t mCellSpansPctCol : 1;  // does any cell span a col with a pct width
    806                                    // (or containing a cell with a pct width)
    807    uint32_t mIsBorderCollapse : 1;  // border collapsing model vs. separate
    808                                     // model
    809    uint32_t mRowInserted : 1;
    810    uint32_t mNeedToCalcBCBorders : 1;
    811    uint32_t mGeometryDirty : 1;
    812    uint32_t mNeedToCollapse : 1;  // rows, cols that have visibility:collapse
    813                                   // need to be collapsed
    814    uint32_t mResizedColumns : 1;  // have we resized columns since last reflow?
    815    uint32_t mNeedToCalcHasBCBorders : 1;
    816    uint32_t mHasBCBorders : 1;
    817    uint32_t mIsDestroying : 1;  // Whether we're in the process of destroying
    818                                 // this table frame.
    819  } mBits;
    820 
    821  std::map<int32_t, int32_t> mDeletedRowIndexRanges;  // maintains ranges of row
    822                                                      // indices of deleted rows
    823  mozilla::UniquePtr<nsTableCellMap> mCellMap;  // maintains the relationships
    824                                                // between rows, cols, and cells
    825  // the layout strategy for this frame
    826  mozilla::UniquePtr<nsITableLayoutStrategy> mTableLayoutStrategy;
    827  nsFrameList mColGroups;  // the list of colgroup frames
    828 };
    829 
    830 inline bool nsTableFrame::IsRowGroup(mozilla::StyleDisplay aDisplayType) const {
    831  return mozilla::StyleDisplay::TableHeaderGroup == aDisplayType ||
    832         mozilla::StyleDisplay::TableFooterGroup == aDisplayType ||
    833         mozilla::StyleDisplay::TableRowGroup == aDisplayType;
    834 }
    835 
    836 inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue) {
    837  mBits.mHaveReflowedColGroups = aValue;
    838 }
    839 
    840 inline bool nsTableFrame::HaveReflowedColGroups() const {
    841  return (bool)mBits.mHaveReflowedColGroups;
    842 }
    843 
    844 inline bool nsTableFrame::HasPctCol() const { return (bool)mBits.mHasPctCol; }
    845 
    846 inline void nsTableFrame::SetHasPctCol(bool aValue) {
    847  mBits.mHasPctCol = (unsigned)aValue;
    848 }
    849 
    850 inline bool nsTableFrame::HasCellSpanningPctCol() const {
    851  return (bool)mBits.mCellSpansPctCol;
    852 }
    853 
    854 inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue) {
    855  mBits.mCellSpansPctCol = (unsigned)aValue;
    856 }
    857 
    858 inline bool nsTableFrame::IsRowInserted() const {
    859  return (bool)mBits.mRowInserted;
    860 }
    861 
    862 inline void nsTableFrame::SetRowInserted(bool aValue) {
    863  mBits.mRowInserted = (unsigned)aValue;
    864 }
    865 
    866 inline void nsTableFrame::SetNeedToCollapse(bool aValue) {
    867  static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse =
    868      (unsigned)aValue;
    869 }
    870 
    871 inline bool nsTableFrame::NeedToCollapse() const {
    872  return (bool)static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse;
    873 }
    874 
    875 inline nsFrameList& nsTableFrame::GetColGroups() {
    876  return static_cast<nsTableFrame*>(FirstInFlow())->mColGroups;
    877 }
    878 
    879 inline nsTArray<nsTableColFrame*>& nsTableFrame::GetColCache() {
    880  return mColFrames;
    881 }
    882 
    883 inline bool nsTableFrame::IsBorderCollapse() const {
    884  return (bool)mBits.mIsBorderCollapse;
    885 }
    886 
    887 inline void nsTableFrame::SetBorderCollapse(bool aValue) {
    888  mBits.mIsBorderCollapse = aValue;
    889 }
    890 
    891 inline bool nsTableFrame::NeedToCalcBCBorders() const {
    892  return (bool)mBits.mNeedToCalcBCBorders;
    893 }
    894 
    895 inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue) {
    896  mBits.mNeedToCalcBCBorders = (unsigned)aValue;
    897 }
    898 
    899 inline bool nsTableFrame::NeedToCalcHasBCBorders() const {
    900  return (bool)mBits.mNeedToCalcHasBCBorders;
    901 }
    902 
    903 inline void nsTableFrame::SetNeedToCalcHasBCBorders(bool aValue) {
    904  mBits.mNeedToCalcHasBCBorders = (unsigned)aValue;
    905 }
    906 
    907 inline bool nsTableFrame::HasBCBorders() {
    908  if (NeedToCalcHasBCBorders()) {
    909    CalcHasBCBorders();
    910    SetNeedToCalcHasBCBorders(false);
    911  }
    912  return (bool)mBits.mHasBCBorders;
    913 }
    914 
    915 inline void nsTableFrame::SetHasBCBorders(bool aValue) {
    916  mBits.mHasBCBorders = (unsigned)aValue;
    917 }
    918 
    919 #define ABORT0()                                       \
    920  {                                                    \
    921    NS_ASSERTION(false, "CellIterator program error"); \
    922    return;                                            \
    923  }
    924 
    925 #define ABORT1(aReturn)                                \
    926  {                                                    \
    927    NS_ASSERTION(false, "CellIterator program error"); \
    928    return aReturn;                                    \
    929  }
    930 
    931 #endif