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