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"
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
;
21 class nsTableColFrame
;
22 class nsTableRowGroupFrame
;
23 class nsTableRowFrame
;
24 class nsTableColGroupFrame
;
25 class nsITableLayoutStrategy
;
32 struct TableReflowInput
;
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.
45 // A final reflow with the available block-size in the table frame's
50 class nsDisplayTableItem
: public nsPaintedDisplayItem
{
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
{
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);
77 * Move all display items in our lists to top of the corresponding lists in
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
;
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);
108 nsDisplayListBuilder
* mBuilder
;
109 nsDisplayTableBackgroundSet
* mPrevTableBackgroundSet
;
111 nsDisplayList mColGroupBackgrounds
;
112 nsDisplayList mColBackgrounds
;
114 nsTArray
<nsTableColFrame
*> mColumns
;
115 nsPoint mToReferenceFrame
;
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
143 class nsTableFrame
: public nsContainerFrame
{
144 typedef mozilla::image::ImgDrawResult ImgDrawResult
;
145 typedef mozilla::WritingMode WritingMode
;
146 typedef mozilla::LogicalMargin LogicalMargin
;
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
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
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;
272 * In quirks mode, the size of the table background is reduced
273 * by the outer BC border. Compute the reduction needed.
275 nsMargin
GetDeflationForBackground(nsPresContext
* aPresContext
) const;
277 /** Get width of table + colgroup + col collapse: elements that
278 * continue along the length of the whole iStart side.
279 * see nsTablePainter about continuous borders
281 nscoord
GetContinuousIStartBCBorderWidth() const;
282 void SetContinuousIStartBCBorderWidth(nscoord aValue
);
284 friend class nsDelayedCalcBCBorders
;
286 void AddBCDamageArea(const mozilla::TableArea
& aValue
);
287 bool BCRecalcNeeded(ComputedStyle
* aOldComputedStyle
,
288 ComputedStyle
* aNewComputedStyle
);
289 void PaintBCBorders(DrawTarget
& aDrawTarget
, const nsRect
& aDirtyRect
);
290 void CreateWebRenderCommandsForBCBorders(
291 mozilla::wr::DisplayListBuilder
& aBuilder
,
292 const mozilla::layers::StackingContextHelper
& aSc
,
293 const nsRect
& aVisibleRect
, const nsPoint
& aOffsetToReferenceFrame
);
295 void MarkIntrinsicISizesDirty() override
;
296 // For border-collapse tables, the caller must not add padding and
297 // border to the results of these functions.
298 nscoord
GetMinISize(gfxContext
* aRenderingContext
) override
;
299 nscoord
GetPrefISize(gfxContext
* aRenderingContext
) override
;
300 IntrinsicSizeOffsetData
IntrinsicISizeOffsets(
301 nscoord aPercentageBasis
= NS_UNCONSTRAINEDSIZE
) override
;
303 SizeComputationResult
ComputeSize(
304 gfxContext
* aRenderingContext
, mozilla::WritingMode aWM
,
305 const mozilla::LogicalSize
& aCBSize
, nscoord aAvailableISize
,
306 const mozilla::LogicalSize
& aMargin
,
307 const mozilla::LogicalSize
& aBorderPadding
,
308 const mozilla::StyleSizeOverrides
& aSizeOverrides
,
309 mozilla::ComputeSizeFlags aFlags
) override
;
311 mozilla::LogicalSize
ComputeAutoSize(
312 gfxContext
* aRenderingContext
, mozilla::WritingMode aWM
,
313 const mozilla::LogicalSize
& aCBSize
, nscoord aAvailableISize
,
314 const mozilla::LogicalSize
& aMargin
,
315 const mozilla::LogicalSize
& aBorderPadding
,
316 const mozilla::StyleSizeOverrides
& aSizeOverrides
,
317 mozilla::ComputeSizeFlags aFlags
) override
;
320 * A copy of nsIFrame::ShrinkISizeToFit that calls a different
321 * GetPrefISize, since tables have two different ones.
323 nscoord
TableShrinkISizeToFit(gfxContext
* aRenderingContext
,
326 // XXXldb REWRITE THIS COMMENT!
329 * Inner tables are reflowed in two steps.
331 * if mFirstPassValid is false, this is our first time through since content was last changed
334 * get min/max info for all cells in an infinite space
335 * do column balancing
336 * set mFirstPassValid to true
338 * use column widths to Reflow cells
341 * @see nsIFrame::Reflow
344 void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
345 const ReflowInput
& aReflowInput
,
346 nsReflowStatus
& aStatus
) override
;
348 void ReflowTable(ReflowOutput
& aDesiredSize
, const ReflowInput
& aReflowInput
,
349 const LogicalMargin
& aBorderPadding
,
350 mozilla::TableReflowMode aReflowMode
,
351 nsIFrame
*& aLastChildReflowed
, nsReflowStatus
& aStatus
);
353 nsFrameList
& GetColGroups();
355 ComputedStyle
* GetParentComputedStyle(
356 nsIFrame
** aProviderFrame
) const override
;
358 #ifdef DEBUG_FRAME_DUMP
359 /** @see nsIFrame::GetFrameName */
360 nsresult
GetFrameName(nsAString
& aResult
) const override
;
363 /** Return the isize of the column at aColIndex.
364 * This may only be called on the table's first-in-flow.
366 nscoord
GetColumnISizeFromFirstInFlow(int32_t aColIndex
);
368 /** Helper to get the column spacing style value.
369 * The argument refers to the space between column aColIndex and column
370 * aColIndex + 1. An index of -1 indicates the padding between the table
371 * and the left border, an index equal to the number of columns indicates
372 * the padding between the table and the right border.
374 * Although in this class cell spacing does not depend on the index, it
375 * may be important for overriding classes.
377 virtual nscoord
GetColSpacing(int32_t aColIndex
);
379 /** Helper to find the sum of the cell spacing between arbitrary columns.
380 * The argument refers to the space between column aColIndex and column
381 * aColIndex + 1. An index of -1 indicates the padding between the table
382 * and the left border, an index equal to the number of columns indicates
383 * the padding between the table and the right border.
385 * This method is equivalent to
386 * nscoord result = 0;
387 * for (i = aStartColIndex; i < aEndColIndex; i++) {
388 * result += GetColSpacing(i);
392 virtual nscoord
GetColSpacing(int32_t aStartColIndex
, int32_t aEndColIndex
);
394 /** Helper to get the row spacing style value.
395 * The argument refers to the space between row aRowIndex and row
396 * aRowIndex + 1. An index of -1 indicates the padding between the table
397 * and the top border, an index equal to the number of rows indicates
398 * the padding between the table and the bottom border.
400 * Although in this class cell spacing does not depend on the index, it
401 * may be important for overriding classes.
403 virtual nscoord
GetRowSpacing(int32_t aRowIndex
);
405 /** Helper to find the sum of the cell spacing between arbitrary rows.
406 * The argument refers to the space between row aRowIndex and row
407 * aRowIndex + 1. An index of -1 indicates the padding between the table
408 * and the top border, an index equal to the number of rows indicates
409 * the padding between the table and the bottom border.
411 * This method is equivalent to
412 * nscoord result = 0;
413 * for (i = aStartRowIndex; i < aEndRowIndex; i++) {
414 * result += GetRowSpacing(i);
418 virtual nscoord
GetRowSpacing(int32_t aStartRowIndex
, int32_t aEndRowIndex
);
421 /* For the base implementation of nsTableFrame, cell spacing does not depend
422 * on row/column indexing.
424 nscoord
GetColSpacing();
425 nscoord
GetRowSpacing();
428 nscoord
SynthesizeFallbackBaseline(
429 mozilla::WritingMode aWM
,
430 BaselineSharingGroup aBaselineGroup
) const override
;
431 Maybe
<nscoord
> GetNaturalBaselineBOffset(
432 mozilla::WritingMode aWM
, BaselineSharingGroup aBaselineGroup
,
433 BaselineExportContext
) const override
;
435 /** return the row span of a cell, taking into account row span magic at the
436 * bottom of a table. The row span equals the number of rows spanned by aCell
437 * starting at aStartRowIndex, and can be smaller if aStartRowIndex is greater
438 * than the row index in which aCell originates.
440 * @param aStartRowIndex the cell
441 * @param aCell the cell
443 * @return the row span, correcting for row spans that extend beyond the
444 * bottom of the table.
446 int32_t GetEffectiveRowSpan(int32_t aStartRowIndex
,
447 const nsTableCellFrame
& aCell
) const;
448 int32_t GetEffectiveRowSpan(const nsTableCellFrame
& aCell
,
449 nsCellMap
* aCellMap
= nullptr);
451 /** return the col span of a cell, taking into account col span magic at the
454 * @param aCell the cell
456 * @return the col span, correcting for col spans that extend beyond the edge
459 int32_t GetEffectiveColSpan(const nsTableCellFrame
& aCell
,
460 nsCellMap
* aCellMap
= nullptr) const;
462 /** indicate whether the row has more than one cell that either originates
463 * or is spanned from the rows above
465 bool HasMoreThanOneCell(int32_t aRowIndex
) const;
467 /** return the column frame associated with aColIndex
468 * returns nullptr if the col frame has not yet been allocated, or if
469 * aColIndex is out of range
471 nsTableColFrame
* GetColFrame(int32_t aColIndex
) const;
473 /** Insert a col frame reference into the colframe cache and adapt the cellmap
474 * @param aColFrame - the column frame
475 * @param aColIndex - index where the column should be inserted into the
478 void InsertCol(nsTableColFrame
& aColFrame
, int32_t aColIndex
);
480 nsTableColGroupFrame
* CreateSyntheticColGroupFrame();
482 int32_t DestroyAnonymousColFrames(int32_t aNumFrames
);
484 // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our
485 // last synthetic colgroup. If we have no such colgroup, then create one.
486 void AppendAnonymousColFrames(int32_t aNumColsToAdd
);
488 // Append aNumColsToAdd anonymous col frames of type aColType to
489 // aColGroupFrame. If aAddToTable is true, also call AddColsToTable on the
491 void AppendAnonymousColFrames(nsTableColGroupFrame
* aColGroupFrame
,
492 int32_t aNumColsToAdd
, nsTableColType aColType
,
495 void MatchCellMapToColCache(nsTableCellMap
* aCellMap
);
497 void DidResizeColumns();
499 void AppendCell(nsTableCellFrame
& aCellFrame
, int32_t aRowIndex
);
501 void InsertCells(nsTArray
<nsTableCellFrame
*>& aCellFrames
, int32_t aRowIndex
,
502 int32_t aColIndexBefore
);
504 void RemoveCell(nsTableCellFrame
* aCellFrame
, int32_t aRowIndex
);
506 void AppendRows(nsTableRowGroupFrame
* aRowGroupFrame
, int32_t aRowIndex
,
507 nsTArray
<nsTableRowFrame
*>& aRowFrames
);
509 int32_t InsertRows(nsTableRowGroupFrame
* aRowGroupFrame
,
510 nsTArray
<nsTableRowFrame
*>& aFrames
, int32_t aRowIndex
,
511 bool aConsiderSpans
);
513 void RemoveRows(nsTableRowFrame
& aFirstRowFrame
, int32_t aNumRowsToRemove
,
514 bool aConsiderSpans
);
516 /** Insert multiple rowgroups into the table cellmap handling
517 * @param aRowGroups - iterator that iterates over the rowgroups to insert
519 void InsertRowGroups(const nsFrameList::Slice
& aRowGroups
);
521 void InsertColGroups(int32_t aStartColIndex
,
522 const nsFrameList::Slice
& aColgroups
);
524 void RemoveCol(nsTableColGroupFrame
* aColGroupFrame
, int32_t aColIndex
,
525 bool aRemoveFromCache
, bool aRemoveFromCellMap
);
527 bool ColumnHasCellSpacingBefore(int32_t aColIndex
) const;
529 bool HasPctCol() const;
530 void SetHasPctCol(bool aValue
);
532 bool HasCellSpanningPctCol() const;
533 void SetHasCellSpanningPctCol(bool aValue
);
536 * To be called on a frame by its parent after setting its size/position and
537 * calling DidReflow (possibly via FinishReflowChild()). This can also be
538 * used for child frames which are not being reflowed but did have their size
539 * or position changed.
541 * @param aFrame The frame to invalidate
542 * @param aOrigRect The original rect of aFrame (before the change).
543 * @param aOrigInkOverflow The original overflow rect of aFrame.
544 * @param aIsFirstReflow True if the size/position change is due to the
545 * first reflow of aFrame.
547 static void InvalidateTableFrame(nsIFrame
* aFrame
, const nsRect
& aOrigRect
,
548 const nsRect
& aOrigInkOverflow
,
549 bool aIsFirstReflow
);
551 bool ComputeCustomOverflow(mozilla::OverflowAreas
& aOverflowAreas
) override
;
553 // Return our wrapper frame.
554 void AppendDirectlyOwnedAnonBoxes(nsTArray
<OwnedAnonBox
>& aResult
) override
;
557 static void UpdateStyleOfOwnedAnonBoxesForTableWrapper(
558 nsIFrame
* aOwningFrame
, nsIFrame
* aWrapperFrame
,
559 mozilla::ServoRestyleState
& aRestyleState
);
561 /** protected constructor.
564 explicit nsTableFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
,
565 ClassID aID
= kClassID
);
567 virtual ~nsTableFrame();
569 void InitChildReflowInput(ReflowInput
& aReflowInput
);
571 LogicalSides
GetLogicalSkipSides() const override
;
573 void IterateBCBorders(BCPaintBorderAction
& aAction
, const nsRect
& aDirtyRect
);
576 bool IsRowInserted() const;
577 void SetRowInserted(bool aValue
);
580 // A helper function to reflow a header or footer with unconstrained
581 // block-size to see if it should be made repeatable.
582 // @return the desired block-size for a header or footer.
583 nscoord
SetupHeaderFooterChild(const mozilla::TableReflowInput
& aReflowInput
,
584 nsTableRowGroupFrame
* aFrame
);
586 void ReflowChildren(mozilla::TableReflowInput
& aReflowInput
,
587 nsReflowStatus
& aStatus
, nsIFrame
*& aLastChildReflowed
,
588 mozilla::OverflowAreas
& aOverflowAreas
);
590 // This calls the col group and column reflow methods, which do two things:
591 // (1) set all the dimensions to 0
592 // (2) notify the table about colgroups or columns with hidden visibility
593 void ReflowColGroups(gfxContext
* aRenderingContext
);
595 /** return the isize of the table taking into account visibility collapse
596 * on columns and colgroups
597 * @param aBorderPadding the border and padding of the table
599 nscoord
GetCollapsedISize(const WritingMode aWM
,
600 const LogicalMargin
& aBorderPadding
);
602 /** Adjust the table for visibility.collapse set on rowgroups, rows,
604 * @param aDesiredSize the metrics of the table
605 * @param aBorderPadding the border and padding of the table
607 void AdjustForCollapsingRowsCols(ReflowOutput
& aDesiredSize
,
608 const WritingMode aWM
,
609 const LogicalMargin
& aBorderPadding
);
611 /** FixupPositionedTableParts is called at the end of table reflow to reflow
612 * the absolutely positioned descendants of positioned table parts. This is
613 * necessary because the dimensions of table parts may change after they've
614 * been reflowed (e.g. in AdjustForCollapsingRowsCols).
616 void FixupPositionedTableParts(nsPresContext
* aPresContext
,
617 ReflowOutput
& aDesiredSize
,
618 const ReflowInput
& aReflowInput
);
620 // Clears the list of positioned table parts.
621 void ClearAllPositionedTableParts();
623 nsITableLayoutStrategy
* LayoutStrategy() const {
624 return static_cast<nsTableFrame
*>(FirstInFlow())
625 ->mTableLayoutStrategy
.get();
628 // Helper for InsertFrames.
629 void HomogenousInsertFrames(ChildListID aListID
, nsIFrame
* aPrevFrame
,
630 nsFrameList
& aFrameList
);
633 /* Handle a row that got inserted during reflow. aNewHeight is the
634 new height of the table after reflow. */
635 void ProcessRowInserted(nscoord aNewHeight
);
638 // Calculate the border-box block-size of this table, with the min-block-size,
639 // max-block-size, and intrinsic border-box block considered.
640 nscoord
CalcBorderBoxBSize(const ReflowInput
& aReflowInput
,
641 const LogicalMargin
& aBorderPadding
,
642 nscoord aIntrinsicBorderBoxBSize
);
644 // Calculate the desired block-size of this table.
646 // Note: this method is accurate after the children are reflowed. It might
647 // distribute extra block-size to table rows if the table has a specified
648 // block-size larger than the intrinsic block-size.
649 nscoord
CalcDesiredBSize(const ReflowInput
& aReflowInput
,
650 const LogicalMargin
& aBorderPadding
);
652 // The following is a helper for CalcDesiredBSize
653 void DistributeBSizeToRows(const ReflowInput
& aReflowInput
, nscoord aAmount
);
655 void PlaceChild(mozilla::TableReflowInput
& aReflowInput
, nsIFrame
* aKidFrame
,
656 const ReflowInput
& aKidReflowInput
,
657 const mozilla::LogicalPoint
& aKidPosition
,
658 const nsSize
& aContainerSize
, ReflowOutput
& aKidDesiredSize
,
659 const nsRect
& aOriginalKidRect
,
660 const nsRect
& aOriginalKidInkOverflow
);
661 void PlaceRepeatedFooter(mozilla::TableReflowInput
& aReflowInput
,
662 nsTableRowGroupFrame
* aTfoot
, nscoord aFooterBSize
);
665 using RowGroupArray
= AutoTArray
<nsTableRowGroupFrame
*, 8>;
668 // Push all our non-repeatable child frames from the aRowGroups array, in
669 // order, starting from the frame at aPushFrom to the end of the array. The
670 // pushed frames are put on our overflow list. This is a table specific
671 // version that takes into account repeated header and footer frames when
672 // continuing table frames.
673 void PushChildrenToOverflow(const RowGroupArray
& aRowGroups
,
677 // Return the children frames in the display order (e.g. thead before tbodies
678 // before tfoot). If there are multiple theads or tfoots, all but the first
679 // one are treated as tbodies instead.
681 // @param aHead Outparam for the first thead if there is any.
682 // @param aFoot Outparam for the first tfoot if there is any.
683 RowGroupArray
OrderedRowGroups(nsTableRowGroupFrame
** aHead
= nullptr,
684 nsTableRowGroupFrame
** aFoot
= nullptr) const;
686 // Returns true if there are any cells above the row at
687 // aRowIndex and spanning into the row at aRowIndex, the number of
688 // effective columns limits the search up to that column
689 bool RowIsSpannedInto(int32_t aRowIndex
, int32_t aNumEffCols
);
691 // Returns true if there is a cell originating in aRowIndex
692 // which spans into the next row, the number of effective
693 // columns limits the search up to that column
694 bool RowHasSpanningCells(int32_t aRowIndex
, int32_t aNumEffCols
);
697 bool HaveReflowedColGroups() const;
698 void SetHaveReflowedColGroups(bool aValue
);
701 bool IsBorderCollapse() const;
703 bool NeedToCalcBCBorders() const;
704 void SetNeedToCalcBCBorders(bool aValue
);
706 bool NeedToCollapse() const;
707 void SetNeedToCollapse(bool aValue
);
709 bool NeedToCalcHasBCBorders() const;
710 void SetNeedToCalcHasBCBorders(bool aValue
);
712 void CalcHasBCBorders();
714 void SetHasBCBorders(bool aValue
);
716 /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
717 * state bit, which implies that all descendants are dirty. The
718 * GeometryDirty still implies that all the parts of the table are
719 * dirty, but resizing optimizations should still apply to the
720 * contents of the individual cells.
722 void SetGeometryDirty() { mBits
.mGeometryDirty
= true; }
723 void ClearGeometryDirty() { mBits
.mGeometryDirty
= false; }
724 bool IsGeometryDirty() const { return mBits
.mGeometryDirty
; }
726 /** Get the cell map for this table frame. It is not always mCellMap.
727 * Only the firstInFlow has a legit cell map
729 nsTableCellMap
* GetCellMap() const;
731 /** Iterate over the row groups and adjust the row indices of all rows
732 * whose index is >= aRowIndex.
733 * @param aRowIndex - start adjusting with this index
734 * @param aAdjustment - shift the row index by this amount
736 void AdjustRowIndices(int32_t aRowIndex
, int32_t aAdjustment
);
738 /** Reset the rowindices of all rows as they might have changed due to
739 * rowgroup reordering, exclude new row group frames that show in the
740 * reordering but are not yet inserted into the cellmap
741 * @param aRowGroupsToExclude - an iterator that will produce the row groups
744 void ResetRowIndices(const nsFrameList::Slice
& aRowGroupsToExclude
);
746 nsTArray
<nsTableColFrame
*>& GetColCache();
748 mozilla::TableBCData
* GetTableBCData() const;
751 void SetBorderCollapse(bool aValue
);
753 mozilla::TableBCData
* GetOrCreateTableBCData();
754 void SetFullBCDamageArea();
755 void CalcBCBorders();
757 void ExpandBCDamageArea(mozilla::TableArea
& aRect
) const;
759 void SetColumnDimensions(nscoord aHeight
, WritingMode aWM
,
760 const LogicalMargin
& aBorderPadding
,
761 const nsSize
& aContainerSize
);
763 int32_t CollectRows(nsIFrame
* aFrame
,
764 nsTArray
<nsTableRowFrame
*>& aCollection
);
766 public: /* ----- Cell Map public methods ----- */
767 int32_t GetStartRowIndex(const nsTableRowGroupFrame
* aRowGroupFrame
) const;
769 /** returns the number of rows in this table.
771 int32_t GetRowCount() const { return GetCellMap()->GetRowCount(); }
773 /** returns the number of columns in this table after redundant columns have
776 int32_t GetEffectiveColCount() const;
778 /* return the col count including dead cols */
779 int32_t GetColCount() const { return GetCellMap()->GetColCount(); }
781 // return the last col index which isn't of type eColAnonymousCell
782 int32_t GetIndexOfLastRealCol();
784 /** returns true if table-layout:auto */
788 /* ---------- Row index management methods ------------ */
790 /** Add the given index to the existing ranges of
791 * deleted row indices and merge ranges if, with the addition of the new
792 * index, they become consecutive.
793 * @param aDeletedRowStoredIndex - index of the row that was deleted
794 * Note - 'stored' index here refers to the index that was assigned to
795 * the row before any remove row operations were performed i.e. the
796 * value of mRowIndex and not the value returned by GetRowIndex()
798 void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex
);
800 /** Calculate the change that aStoredIndex must be increased/decreased by
802 * Note that aStoredIndex is always the index of an undeleted row (since
803 * rows that have already been deleted can never call this method).
804 * @param aStoredIndex - The stored index value that must be adjusted
805 * Note - 'stored' index here refers to the index that was assigned to
806 * the row before any remove row operations were performed i.e. the
807 * value of mRowIndex and not the value returned by GetRowIndex()
809 int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex
);
811 /** Returns whether mDeletedRowIndexRanges is empty
813 bool IsDeletedRowIndexRangesEmpty() const {
814 return mDeletedRowIndexRanges
.empty();
817 bool IsDestroying() const { return mBits
.mIsDestroying
; }
821 void Dump(bool aDumpRows
, bool aDumpCols
, bool aDumpCellMap
);
826 * Helper method for RemoveFrame.
828 void DoRemoveFrame(DestroyContext
&, ChildListID
, nsIFrame
*);
830 void DumpRowGroup(nsIFrame
* aChildFrame
);
833 AutoTArray
<nsTableColFrame
*, 8> mColFrames
;
836 uint32_t mHaveReflowedColGroups
: 1; // have the col groups gotten their
838 uint32_t mHasPctCol
: 1; // does any cell or col have a pct width
839 uint32_t mCellSpansPctCol
: 1; // does any cell span a col with a pct width
840 // (or containing a cell with a pct width)
841 uint32_t mIsBorderCollapse
: 1; // border collapsing model vs. separate
843 uint32_t mRowInserted
: 1;
844 uint32_t mNeedToCalcBCBorders
: 1;
845 uint32_t mGeometryDirty
: 1;
846 uint32_t mIStartContBCBorder
: 8;
847 uint32_t mNeedToCollapse
: 1; // rows, cols that have visibility:collapse
848 // need to be collapsed
849 uint32_t mResizedColumns
: 1; // have we resized columns since last reflow?
850 uint32_t mNeedToCalcHasBCBorders
: 1;
851 uint32_t mHasBCBorders
: 1;
852 uint32_t mIsDestroying
: 1; // Whether we're in the process of destroying
856 std::map
<int32_t, int32_t> mDeletedRowIndexRanges
; // maintains ranges of row
857 // indices of deleted rows
858 mozilla::UniquePtr
<nsTableCellMap
> mCellMap
; // maintains the relationships
859 // between rows, cols, and cells
860 // the layout strategy for this frame
861 mozilla::UniquePtr
<nsITableLayoutStrategy
> mTableLayoutStrategy
;
862 nsFrameList mColGroups
; // the list of colgroup frames
865 inline bool nsTableFrame::IsRowGroup(mozilla::StyleDisplay aDisplayType
) const {
866 return mozilla::StyleDisplay::TableHeaderGroup
== aDisplayType
||
867 mozilla::StyleDisplay::TableFooterGroup
== aDisplayType
||
868 mozilla::StyleDisplay::TableRowGroup
== aDisplayType
;
871 inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue
) {
872 mBits
.mHaveReflowedColGroups
= aValue
;
875 inline bool nsTableFrame::HaveReflowedColGroups() const {
876 return (bool)mBits
.mHaveReflowedColGroups
;
879 inline bool nsTableFrame::HasPctCol() const { return (bool)mBits
.mHasPctCol
; }
881 inline void nsTableFrame::SetHasPctCol(bool aValue
) {
882 mBits
.mHasPctCol
= (unsigned)aValue
;
885 inline bool nsTableFrame::HasCellSpanningPctCol() const {
886 return (bool)mBits
.mCellSpansPctCol
;
889 inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue
) {
890 mBits
.mCellSpansPctCol
= (unsigned)aValue
;
893 inline bool nsTableFrame::IsRowInserted() const {
894 return (bool)mBits
.mRowInserted
;
897 inline void nsTableFrame::SetRowInserted(bool aValue
) {
898 mBits
.mRowInserted
= (unsigned)aValue
;
901 inline void nsTableFrame::SetNeedToCollapse(bool aValue
) {
902 static_cast<nsTableFrame
*>(FirstInFlow())->mBits
.mNeedToCollapse
=
906 inline bool nsTableFrame::NeedToCollapse() const {
907 return (bool)static_cast<nsTableFrame
*>(FirstInFlow())->mBits
.mNeedToCollapse
;
910 inline nsFrameList
& nsTableFrame::GetColGroups() {
911 return static_cast<nsTableFrame
*>(FirstInFlow())->mColGroups
;
914 inline nsTArray
<nsTableColFrame
*>& nsTableFrame::GetColCache() {
918 inline bool nsTableFrame::IsBorderCollapse() const {
919 return (bool)mBits
.mIsBorderCollapse
;
922 inline void nsTableFrame::SetBorderCollapse(bool aValue
) {
923 mBits
.mIsBorderCollapse
= aValue
;
926 inline bool nsTableFrame::NeedToCalcBCBorders() const {
927 return (bool)mBits
.mNeedToCalcBCBorders
;
930 inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue
) {
931 mBits
.mNeedToCalcBCBorders
= (unsigned)aValue
;
934 inline bool nsTableFrame::NeedToCalcHasBCBorders() const {
935 return (bool)mBits
.mNeedToCalcHasBCBorders
;
938 inline void nsTableFrame::SetNeedToCalcHasBCBorders(bool aValue
) {
939 mBits
.mNeedToCalcHasBCBorders
= (unsigned)aValue
;
942 inline bool nsTableFrame::HasBCBorders() {
943 if (NeedToCalcHasBCBorders()) {
945 SetNeedToCalcHasBCBorders(false);
947 return (bool)mBits
.mHasBCBorders
;
950 inline void nsTableFrame::SetHasBCBorders(bool aValue
) {
951 mBits
.mHasBCBorders
= (unsigned)aValue
;
954 inline nscoord
nsTableFrame::GetContinuousIStartBCBorderWidth() const {
955 int32_t d2a
= PresContext()->AppUnitsPerDevPixel();
956 return BC_BORDER_END_HALF_COORD(d2a
, mBits
.mIStartContBCBorder
);
959 inline void nsTableFrame::SetContinuousIStartBCBorderWidth(nscoord aValue
) {
960 mBits
.mIStartContBCBorder
= (unsigned)aValue
;
965 NS_ASSERTION(false, "CellIterator program error"); \
969 #define ABORT1(aReturn) \
971 NS_ASSERTION(false, "CellIterator program error"); \