summaryrefslogtreecommitdiffstats
path: root/layout/tables/nsTableFrame.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--layout/tables/nsTableFrame.h981
1 files changed, 981 insertions, 0 deletions
diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h
new file mode 100644
index 0000000000..67108b2eab
--- /dev/null
+++ b/layout/tables/nsTableFrame.h
@@ -0,0 +1,981 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsTableFrame_h__
+#define nsTableFrame_h__
+
+#include "mozilla/Attributes.h"
+#include "celldata.h"
+#include "nscore.h"
+#include "nsContainerFrame.h"
+#include "nsStyleConsts.h"
+#include "nsCellMap.h"
+#include "nsGkAtoms.h"
+#include "nsDisplayList.h"
+#include "TableArea.h"
+
+struct BCPaintBorderAction;
+struct BCPropertyData;
+class nsTableCellFrame;
+class nsTableCellMap;
+class nsTableColFrame;
+class nsTableRowGroupFrame;
+class nsTableRowFrame;
+class nsTableColGroupFrame;
+class nsITableLayoutStrategy;
+
+namespace mozilla {
+
+class LogicalMargin;
+class PresShell;
+class WritingMode;
+struct TableReflowInput;
+
+namespace layers {
+class StackingContextHelper;
+}
+
+class nsDisplayTableItem : public nsPaintedDisplayItem {
+ public:
+ nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+ : nsPaintedDisplayItem(aBuilder, aFrame) {}
+
+ // With collapsed borders, parts of the collapsed border can extend outside
+ // the table part frames, so allow this display element to blow out to our
+ // overflow rect. This is also useful for row frames that have spanning
+ // cells extending outside them.
+ virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
+ bool* aSnap) const override;
+};
+
+class nsDisplayTableBackgroundSet {
+ public:
+ nsDisplayList* ColGroupBackgrounds() { return &mColGroupBackgrounds; }
+
+ nsDisplayList* ColBackgrounds() { return &mColBackgrounds; }
+
+ nsDisplayTableBackgroundSet(nsDisplayListBuilder* aBuilder, nsIFrame* aTable);
+
+ ~nsDisplayTableBackgroundSet() {
+ mozilla::DebugOnly<nsDisplayTableBackgroundSet*> result =
+ mBuilder->SetTableBackgroundSet(mPrevTableBackgroundSet);
+ MOZ_ASSERT(result == this);
+ }
+
+ /**
+ * Move all display items in our lists to top of the corresponding lists in
+ * the destination.
+ */
+ void MoveTo(const nsDisplayListSet& aDestination) {
+ aDestination.BorderBackground()->AppendToTop(ColGroupBackgrounds());
+ aDestination.BorderBackground()->AppendToTop(ColBackgrounds());
+ }
+
+ void AddColumn(nsTableColFrame* aFrame) { mColumns.AppendElement(aFrame); }
+
+ nsTableColFrame* GetColForIndex(int32_t aIndex) { return mColumns[aIndex]; }
+
+ const nsPoint& TableToReferenceFrame() { return mToReferenceFrame; }
+
+ const nsRect& GetDirtyRect() { return mDirtyRect; }
+
+ const DisplayItemClipChain* GetTableClipChain() {
+ return mCombinedTableClipChain;
+ }
+
+ const ActiveScrolledRoot* GetTableASR() { return mTableASR; }
+ layers::ScrollableLayerGuid::ViewID GetScrollParentId() {
+ return mCurrentScrollParentId;
+ }
+
+ private:
+ // This class is only used on stack, so we don't have to worry about leaking
+ // it. Don't let us be heap-allocated!
+ void* operator new(size_t sz) noexcept(true);
+
+ protected:
+ nsDisplayListBuilder* mBuilder;
+ nsDisplayTableBackgroundSet* mPrevTableBackgroundSet;
+
+ nsDisplayList mColGroupBackgrounds;
+ nsDisplayList mColBackgrounds;
+
+ nsTArray<nsTableColFrame*> mColumns;
+ nsPoint mToReferenceFrame;
+ nsRect mDirtyRect;
+ layers::ScrollableLayerGuid::ViewID mCurrentScrollParentId;
+
+ const DisplayItemClipChain* mCombinedTableClipChain;
+ const ActiveScrolledRoot* mTableASR;
+};
+
+} // namespace mozilla
+
+/* ========================================================================== */
+
+enum nsTableColType {
+ eColContent = 0, // there is real col content associated
+ eColAnonymousCol = 1, // the result of a span on a col
+ eColAnonymousColGroup = 2, // the result of a span on a col group
+ eColAnonymousCell = 3 // the result of a cell alone
+};
+
+/**
+ * nsTableFrame maps the inner portion of a table (everything except captions.)
+ * Used as a pseudo-frame within nsTableWrapperFrame, it may also be used
+ * stand-alone as the top-level frame.
+ *
+ * The principal child list contains row group frames. There is also an
+ * additional child list, FrameChildListID::ColGroup, which contains the col
+ * group frames.
+ */
+class nsTableFrame : public nsContainerFrame {
+ typedef mozilla::image::ImgDrawResult ImgDrawResult;
+ typedef mozilla::WritingMode WritingMode;
+ typedef mozilla::LogicalMargin LogicalMargin;
+ typedef mozilla::TableReflowInput TableReflowInput;
+
+ public:
+ NS_DECL_FRAMEARENA_HELPERS(nsTableFrame)
+
+ typedef nsTArray<nsIFrame*> FrameTArray;
+ NS_DECLARE_FRAME_PROPERTY_DELETABLE(PositionedTablePartArray, FrameTArray)
+
+ /** nsTableWrapperFrame has intimate knowledge of the inner table frame */
+ friend class nsTableWrapperFrame;
+
+ /**
+ * instantiate a new instance of nsTableRowFrame.
+ *
+ * @param aPresShell the pres shell for this frame
+ *
+ * @return the frame that was created
+ */
+ friend nsTableFrame* NS_NewTableFrame(mozilla::PresShell* aPresShell,
+ ComputedStyle* aStyle);
+
+ /** sets defaults for table-specific style.
+ * @see nsIFrame::Init
+ */
+ virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
+ nsIFrame* aPrevInFlow) override;
+
+ // Return true if aParentReflowInput.frame or any of its ancestors within
+ // the containing table have non-auto bsize. (e.g. pct or fixed bsize)
+ static bool AncestorsHaveStyleBSize(const ReflowInput& aParentReflowInput);
+
+ // See if a special bsize reflow will occur due to having a pct bsize when
+ // the pct bsize basis may not yet be valid.
+ static void CheckRequestSpecialBSizeReflow(const ReflowInput& aReflowInput);
+
+ // Notify the frame and its ancestors (up to the containing table) that a
+ // special height reflow will occur.
+ static void RequestSpecialBSizeReflow(const ReflowInput& aReflowInput);
+
+ static void RePositionViews(nsIFrame* aFrame);
+
+ static bool PageBreakAfter(nsIFrame* aSourceFrame, nsIFrame* aNextFrame);
+
+ // Register a positioned table part with its nsTableFrame. These objects will
+ // be visited by FixupPositionedTableParts after reflow is complete. (See that
+ // function for more explanation.) Should be called during frame construction.
+ static void RegisterPositionedTablePart(nsIFrame* aFrame);
+
+ // Unregister a positioned table part with its nsTableFrame.
+ static void UnregisterPositionedTablePart(nsIFrame* aFrame,
+ nsIFrame* aDestructRoot);
+
+ /*
+ * Notification that rowspan or colspan has changed for content inside a
+ * table cell
+ */
+ void RowOrColSpanChanged(nsTableCellFrame* aCellFrame);
+
+ /** @see nsIFrame::DestroyFrom */
+ virtual void DestroyFrom(nsIFrame* aDestructRoot,
+ PostDestroyData& aPostDestroyData) override;
+
+ /** @see nsIFrame::DidSetComputedStyle */
+ virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
+
+ void SetInitialChildList(ChildListID aListID,
+ nsFrameList&& aChildList) override;
+ void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
+ void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
+ const nsLineList::iterator* aPrevFrameLine,
+ nsFrameList&& aFrameList) override;
+ virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
+
+ virtual nsMargin GetUsedBorder() const override;
+ virtual nsMargin GetUsedPadding() const override;
+ virtual nsMargin GetUsedMargin() const override;
+
+ // Get the offset from the border box to the area where the row groups fit
+ LogicalMargin GetChildAreaOffset(const WritingMode aWM,
+ const ReflowInput* aReflowInput) const;
+
+ /** helper method to find the table parent of any table frame object */
+ static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame);
+
+ /* Like GetTableFrame, but will set *aDidPassThrough to false if we don't
+ * pass through aMustPassThrough on the way to the table.
+ */
+ static nsTableFrame* GetTableFramePassingThrough(nsIFrame* aMustPassThrough,
+ nsIFrame* aSourceFrame,
+ bool* aDidPassThrough);
+
+ // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
+ // of type aChildType.
+ static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
+ nsIFrame* aPriorChildFrame,
+ mozilla::LayoutFrameType aChildType);
+ bool IsAutoBSize(mozilla::WritingMode aWM);
+
+ /** @return true if aDisplayType represents a rowgroup of any sort
+ * (header, footer, or body)
+ */
+ bool IsRowGroup(mozilla::StyleDisplay aDisplayType) const;
+
+ virtual const nsFrameList& GetChildList(ChildListID aListID) const override;
+ virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
+
+ virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists) override;
+
+ /** Get the outer half (i.e., the part outside the height and width of
+ * the table) of the largest segment (?) of border-collapsed border on
+ * the table on each side, or 0 for non border-collapsed tables.
+ */
+ LogicalMargin GetOuterBCBorder(const WritingMode aWM) const;
+
+ /** Same as above, but only if it's included from the border-box width
+ * of the table.
+ */
+ LogicalMargin GetIncludedOuterBCBorder(const WritingMode aWM) const;
+
+ /** Same as above, but only if it's excluded from the border-box width
+ * of the table. This is the area that leaks out into the margin
+ * (or potentially past it, if there is no margin).
+ */
+ LogicalMargin GetExcludedOuterBCBorder(const WritingMode aWM) const;
+
+ /**
+ * Emplace our border and padding in aBorder and aPadding if we are
+ * border-collapsed. Otherwise, do nothing.
+ */
+ void GetCollapsedBorderPadding(
+ mozilla::Maybe<mozilla::LogicalMargin>& aBorder,
+ mozilla::Maybe<mozilla::LogicalMargin>& aPadding) const;
+
+ /**
+ * In quirks mode, the size of the table background is reduced
+ * by the outer BC border. Compute the reduction needed.
+ */
+ nsMargin GetDeflationForBackground(nsPresContext* aPresContext) const;
+
+ /** Get width of table + colgroup + col collapse: elements that
+ * continue along the length of the whole iStart side.
+ * see nsTablePainter about continuous borders
+ */
+ nscoord GetContinuousIStartBCBorderWidth() const;
+ void SetContinuousIStartBCBorderWidth(nscoord aValue);
+
+ friend class nsDelayedCalcBCBorders;
+
+ void AddBCDamageArea(const mozilla::TableArea& aValue);
+ bool BCRecalcNeeded(ComputedStyle* aOldComputedStyle,
+ ComputedStyle* aNewComputedStyle);
+ void PaintBCBorders(DrawTarget& aDrawTarget, const nsRect& aDirtyRect);
+ void CreateWebRenderCommandsForBCBorders(
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ const mozilla::layers::StackingContextHelper& aSc,
+ const nsRect& aVisibleRect, const nsPoint& aOffsetToReferenceFrame);
+
+ virtual void MarkIntrinsicISizesDirty() override;
+ // For border-collapse tables, the caller must not add padding and
+ // border to the results of these functions.
+ virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
+ virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
+ IntrinsicSizeOffsetData IntrinsicISizeOffsets(
+ nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override;
+
+ SizeComputationResult ComputeSize(
+ gfxContext* aRenderingContext, mozilla::WritingMode aWM,
+ const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
+ const mozilla::LogicalSize& aMargin,
+ const mozilla::LogicalSize& aBorderPadding,
+ const mozilla::StyleSizeOverrides& aSizeOverrides,
+ mozilla::ComputeSizeFlags aFlags) override;
+
+ mozilla::LogicalSize ComputeAutoSize(
+ gfxContext* aRenderingContext, mozilla::WritingMode aWM,
+ const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
+ const mozilla::LogicalSize& aMargin,
+ const mozilla::LogicalSize& aBorderPadding,
+ const mozilla::StyleSizeOverrides& aSizeOverrides,
+ mozilla::ComputeSizeFlags aFlags) override;
+
+ /**
+ * A copy of nsIFrame::ShrinkISizeToFit that calls a different
+ * GetPrefISize, since tables have two different ones.
+ */
+ nscoord TableShrinkISizeToFit(gfxContext* aRenderingContext,
+ nscoord aWidthInCB);
+
+ // XXXldb REWRITE THIS COMMENT!
+ // clang-format off
+ /**
+ * Inner tables are reflowed in two steps.
+ * <pre>
+ * if mFirstPassValid is false, this is our first time through since content was last changed
+ * set pass to 1
+ * do pass 1
+ * get min/max info for all cells in an infinite space
+ * do column balancing
+ * set mFirstPassValid to true
+ * do pass 2
+ * use column widths to Reflow cells
+ * </pre>
+ *
+ * @see nsIFrame::Reflow
+ */
+ // clang-format on
+ virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
+ const ReflowInput& aReflowInput,
+ nsReflowStatus& aStatus) override;
+
+ void ReflowTable(ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
+ nscoord aAvailBSize, nsIFrame*& aLastChildReflowed,
+ nsReflowStatus& aStatus);
+
+ nsFrameList& GetColGroups();
+
+ virtual ComputedStyle* GetParentComputedStyle(
+ nsIFrame** aProviderFrame) const override;
+
+ virtual bool IsFrameOfType(uint32_t aFlags) const override {
+ if (aFlags & eSupportsCSSTransforms) {
+ return false;
+ }
+ return nsContainerFrame::IsFrameOfType(aFlags);
+ }
+
+#ifdef DEBUG_FRAME_DUMP
+ /** @see nsIFrame::GetFrameName */
+ virtual nsresult GetFrameName(nsAString& aResult) const override;
+#endif
+
+ /** Return the isize of the column at aColIndex.
+ * This may only be called on the table's first-in-flow.
+ */
+ nscoord GetColumnISizeFromFirstInFlow(int32_t aColIndex);
+
+ /** Helper to get the column spacing style value.
+ * The argument refers to the space between column aColIndex and column
+ * aColIndex + 1. An index of -1 indicates the padding between the table
+ * and the left border, an index equal to the number of columns indicates
+ * the padding between the table and the right border.
+ *
+ * Although in this class cell spacing does not depend on the index, it
+ * may be important for overriding classes.
+ */
+ virtual nscoord GetColSpacing(int32_t aColIndex);
+
+ /** Helper to find the sum of the cell spacing between arbitrary columns.
+ * The argument refers to the space between column aColIndex and column
+ * aColIndex + 1. An index of -1 indicates the padding between the table
+ * and the left border, an index equal to the number of columns indicates
+ * the padding between the table and the right border.
+ *
+ * This method is equivalent to
+ * nscoord result = 0;
+ * for (i = aStartColIndex; i < aEndColIndex; i++) {
+ * result += GetColSpacing(i);
+ * }
+ * return result;
+ */
+ virtual nscoord GetColSpacing(int32_t aStartColIndex, int32_t aEndColIndex);
+
+ /** Helper to get the row spacing style value.
+ * The argument refers to the space between row aRowIndex and row
+ * aRowIndex + 1. An index of -1 indicates the padding between the table
+ * and the top border, an index equal to the number of rows indicates
+ * the padding between the table and the bottom border.
+ *
+ * Although in this class cell spacing does not depend on the index, it
+ * may be important for overriding classes.
+ */
+ virtual nscoord GetRowSpacing(int32_t aRowIndex);
+
+ /** Helper to find the sum of the cell spacing between arbitrary rows.
+ * The argument refers to the space between row aRowIndex and row
+ * aRowIndex + 1. An index of -1 indicates the padding between the table
+ * and the top border, an index equal to the number of rows indicates
+ * the padding between the table and the bottom border.
+ *
+ * This method is equivalent to
+ * nscoord result = 0;
+ * for (i = aStartRowIndex; i < aEndRowIndex; i++) {
+ * result += GetRowSpacing(i);
+ * }
+ * return result;
+ */
+ virtual nscoord GetRowSpacing(int32_t aStartRowIndex, int32_t aEndRowIndex);
+
+ private:
+ /* For the base implementation of nsTableFrame, cell spacing does not depend
+ * on row/column indexing.
+ */
+ nscoord GetColSpacing();
+ nscoord GetRowSpacing();
+
+ public:
+ virtual nscoord GetLogicalBaseline(
+ mozilla::WritingMode aWritingMode) const override;
+ bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const override;
+
+ /** return the row span of a cell, taking into account row span magic at the
+ * bottom of a table. The row span equals the number of rows spanned by aCell
+ * starting at aStartRowIndex, and can be smaller if aStartRowIndex is greater
+ * than the row index in which aCell originates.
+ *
+ * @param aStartRowIndex the cell
+ * @param aCell the cell
+ *
+ * @return the row span, correcting for row spans that extend beyond the
+ * bottom of the table.
+ */
+ int32_t GetEffectiveRowSpan(int32_t aStartRowIndex,
+ const nsTableCellFrame& aCell) const;
+ int32_t GetEffectiveRowSpan(const nsTableCellFrame& aCell,
+ nsCellMap* aCellMap = nullptr);
+
+ /** return the col span of a cell, taking into account col span magic at the
+ * edge of a table.
+ *
+ * @param aCell the cell
+ *
+ * @return the col span, correcting for col spans that extend beyond the edge
+ * of the table.
+ */
+ int32_t GetEffectiveColSpan(const nsTableCellFrame& aCell,
+ nsCellMap* aCellMap = nullptr) const;
+
+ /** indicate whether the row has more than one cell that either originates
+ * or is spanned from the rows above
+ */
+ bool HasMoreThanOneCell(int32_t aRowIndex) const;
+
+ /** return the column frame associated with aColIndex
+ * returns nullptr if the col frame has not yet been allocated, or if
+ * aColIndex is out of range
+ */
+ nsTableColFrame* GetColFrame(int32_t aColIndex) const;
+
+ /** Insert a col frame reference into the colframe cache and adapt the cellmap
+ * @param aColFrame - the column frame
+ * @param aColIndex - index where the column should be inserted into the
+ * colframe cache
+ */
+ void InsertCol(nsTableColFrame& aColFrame, int32_t aColIndex);
+
+ nsTableColGroupFrame* CreateSyntheticColGroupFrame();
+
+ int32_t DestroyAnonymousColFrames(int32_t aNumFrames);
+
+ // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our
+ // last synthetic colgroup. If we have no such colgroup, then create one.
+ void AppendAnonymousColFrames(int32_t aNumColsToAdd);
+
+ // Append aNumColsToAdd anonymous col frames of type aColType to
+ // aColGroupFrame. If aAddToTable is true, also call AddColsToTable on the
+ // new cols.
+ void AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame,
+ int32_t aNumColsToAdd, nsTableColType aColType,
+ bool aAddToTable);
+
+ void MatchCellMapToColCache(nsTableCellMap* aCellMap);
+ /** empty the column frame cache */
+ void ClearColCache();
+
+ void DidResizeColumns();
+
+ void AppendCell(nsTableCellFrame& aCellFrame, int32_t aRowIndex);
+
+ void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames, int32_t aRowIndex,
+ int32_t aColIndexBefore);
+
+ void RemoveCell(nsTableCellFrame* aCellFrame, int32_t aRowIndex);
+
+ void AppendRows(nsTableRowGroupFrame* aRowGroupFrame, int32_t aRowIndex,
+ nsTArray<nsTableRowFrame*>& aRowFrames);
+
+ int32_t InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
+ nsTArray<nsTableRowFrame*>& aFrames, int32_t aRowIndex,
+ bool aConsiderSpans);
+
+ void RemoveRows(nsTableRowFrame& aFirstRowFrame, int32_t aNumRowsToRemove,
+ bool aConsiderSpans);
+
+ /** Insert multiple rowgroups into the table cellmap handling
+ * @param aRowGroups - iterator that iterates over the rowgroups to insert
+ */
+ void InsertRowGroups(const nsFrameList::Slice& aRowGroups);
+
+ void InsertColGroups(int32_t aStartColIndex,
+ const nsFrameList::Slice& aColgroups);
+
+ void RemoveCol(nsTableColGroupFrame* aColGroupFrame, int32_t aColIndex,
+ bool aRemoveFromCache, bool aRemoveFromCellMap);
+
+ bool ColumnHasCellSpacingBefore(int32_t aColIndex) const;
+
+ bool HasPctCol() const;
+ void SetHasPctCol(bool aValue);
+
+ bool HasCellSpanningPctCol() const;
+ void SetHasCellSpanningPctCol(bool aValue);
+
+ /**
+ * To be called on a frame by its parent after setting its size/position and
+ * calling DidReflow (possibly via FinishReflowChild()). This can also be
+ * used for child frames which are not being reflowed but did have their size
+ * or position changed.
+ *
+ * @param aFrame The frame to invalidate
+ * @param aOrigRect The original rect of aFrame (before the change).
+ * @param aOrigInkOverflow The original overflow rect of aFrame.
+ * @param aIsFirstReflow True if the size/position change is due to the
+ * first reflow of aFrame.
+ */
+ static void InvalidateTableFrame(nsIFrame* aFrame, const nsRect& aOrigRect,
+ const nsRect& aOrigInkOverflow,
+ bool aIsFirstReflow);
+
+ bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
+
+ // Return our wrapper frame.
+ void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
+
+ protected:
+ static void UpdateStyleOfOwnedAnonBoxesForTableWrapper(
+ nsIFrame* aOwningFrame, nsIFrame* aWrapperFrame,
+ mozilla::ServoRestyleState& aRestyleState);
+
+ /** protected constructor.
+ * @see NewFrame
+ */
+ explicit nsTableFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
+ ClassID aID = kClassID);
+
+ virtual ~nsTableFrame();
+
+ void InitChildReflowInput(ReflowInput& aReflowInput);
+
+ LogicalSides GetLogicalSkipSides() const override;
+
+ void IterateBCBorders(BCPaintBorderAction& aAction, const nsRect& aDirtyRect);
+
+ public:
+ bool IsRowInserted() const;
+ void SetRowInserted(bool aValue);
+
+ protected:
+ // A helper function to reflow a header or footer with unconstrained height
+ // to see if it should be made repeatable.
+ // @return the desired height for a header or footer.
+ // XXX: This helper should be converted to logic coordinates.
+ nscoord SetupHeaderFooterChild(const TableReflowInput& aReflowInput,
+ nsTableRowGroupFrame* aFrame);
+
+ void ReflowChildren(TableReflowInput& aReflowInput, nsReflowStatus& aStatus,
+ nsIFrame*& aLastChildReflowed,
+ mozilla::OverflowAreas& aOverflowAreas);
+
+ // This calls the col group and column reflow methods, which do two things:
+ // (1) set all the dimensions to 0
+ // (2) notify the table about colgroups or columns with hidden visibility
+ void ReflowColGroups(gfxContext* aRenderingContext);
+
+ /** return the isize of the table taking into account visibility collapse
+ * on columns and colgroups
+ * @param aBorderPadding the border and padding of the table
+ */
+ nscoord GetCollapsedISize(const WritingMode aWM,
+ const LogicalMargin& aBorderPadding);
+
+ /** Adjust the table for visibility.collapse set on rowgroups, rows,
+ * colgroups and cols
+ * @param aDesiredSize the metrics of the table
+ * @param aBorderPadding the border and padding of the table
+ */
+ void AdjustForCollapsingRowsCols(ReflowOutput& aDesiredSize,
+ const WritingMode aWM,
+ const LogicalMargin& aBorderPadding);
+
+ /** FixupPositionedTableParts is called at the end of table reflow to reflow
+ * the absolutely positioned descendants of positioned table parts. This is
+ * necessary because the dimensions of table parts may change after they've
+ * been reflowed (e.g. in AdjustForCollapsingRowsCols).
+ */
+ void FixupPositionedTableParts(nsPresContext* aPresContext,
+ ReflowOutput& aDesiredSize,
+ const ReflowInput& aReflowInput);
+
+ // Clears the list of positioned table parts.
+ void ClearAllPositionedTableParts();
+
+ nsITableLayoutStrategy* LayoutStrategy() const {
+ return static_cast<nsTableFrame*>(FirstInFlow())
+ ->mTableLayoutStrategy.get();
+ }
+
+ // Helper for InsertFrames.
+ void HomogenousInsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
+ nsFrameList& aFrameList);
+
+ private:
+ /* Handle a row that got inserted during reflow. aNewHeight is the
+ new height of the table after reflow. */
+ void ProcessRowInserted(nscoord aNewHeight);
+
+ // WIDTH AND HEIGHT CALCULATION
+
+ public:
+ // calculate the computed block-size of aFrame including its border and
+ // padding given its reflow input.
+ nscoord CalcBorderBoxBSize(const ReflowInput& aReflowInput,
+ const LogicalMargin& aBorderPadding,
+ nscoord aIntrinsicBorderBoxBSize);
+
+ protected:
+ // update the desired block-size of this table taking into account the
+ // current reflow input, the table attributes and the content driven rowgroup
+ // bsizes this function can change the overflow area
+ void CalcDesiredBSize(const ReflowInput& aReflowInput,
+ ReflowOutput& aDesiredSize);
+
+ // The following is a helper for CalcDesiredBSize
+
+ void DistributeBSizeToRows(const ReflowInput& aReflowInput, nscoord aAmount);
+
+ void PlaceChild(TableReflowInput& aReflowInput, nsIFrame* aKidFrame,
+ const ReflowInput& aKidReflowInput,
+ const mozilla::LogicalPoint& aKidPosition,
+ const nsSize& aContainerSize, ReflowOutput& aKidDesiredSize,
+ const nsRect& aOriginalKidRect,
+ const nsRect& aOriginalKidInkOverflow);
+ void PlaceRepeatedFooter(TableReflowInput& aReflowInput,
+ nsTableRowGroupFrame* aTfoot, nscoord aFooterHeight);
+
+ nsIFrame* GetFirstBodyRowGroupFrame();
+
+ public:
+ typedef AutoTArray<nsTableRowGroupFrame*, 8> RowGroupArray;
+ /**
+ * Push all our child frames from the aRowGroups array, in order, starting
+ * from the frame at aPushFrom to the end of the array. The frames are put on
+ * our overflow list or moved directly to our next-in-flow if one exists.
+ */
+ protected:
+ void PushChildren(const RowGroupArray& aRowGroups, int32_t aPushFrom);
+
+ public:
+ // put the children frames in the display order (e.g. thead before tbodies
+ // before tfoot). This will handle calling GetRowGroupFrame() on the
+ // children, and not append nulls, so the array is guaranteed to contain
+ // nsTableRowGroupFrames. If there are multiple theads or tfoots, all but
+ // the first one are treated as tbodies instead.
+
+ void OrderRowGroups(RowGroupArray& aChildren,
+ nsTableRowGroupFrame** aHead = nullptr,
+ nsTableRowGroupFrame** aFoot = nullptr) const;
+
+ // Returns true if there are any cells above the row at
+ // aRowIndex and spanning into the row at aRowIndex, the number of
+ // effective columns limits the search up to that column
+ bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols);
+
+ // Returns true if there is a cell originating in aRowIndex
+ // which spans into the next row, the number of effective
+ // columns limits the search up to that column
+ bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols);
+
+ protected:
+ bool HaveReflowedColGroups() const;
+ void SetHaveReflowedColGroups(bool aValue);
+
+ public:
+ bool IsBorderCollapse() const;
+
+ bool NeedToCalcBCBorders() const;
+ void SetNeedToCalcBCBorders(bool aValue);
+
+ bool NeedToCollapse() const;
+ void SetNeedToCollapse(bool aValue);
+
+ bool NeedToCalcHasBCBorders() const;
+ void SetNeedToCalcHasBCBorders(bool aValue);
+
+ void CalcHasBCBorders();
+ bool HasBCBorders();
+ void SetHasBCBorders(bool aValue);
+
+ /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
+ * state bit, which implies that all descendants are dirty. The
+ * GeometryDirty still implies that all the parts of the table are
+ * dirty, but resizing optimizations should still apply to the
+ * contents of the individual cells.
+ */
+ void SetGeometryDirty() { mBits.mGeometryDirty = true; }
+ void ClearGeometryDirty() { mBits.mGeometryDirty = false; }
+ bool IsGeometryDirty() const { return mBits.mGeometryDirty; }
+
+ /** Get the cell map for this table frame. It is not always mCellMap.
+ * Only the firstInFlow has a legit cell map
+ */
+ nsTableCellMap* GetCellMap() const;
+
+ /** Iterate over the row groups and adjust the row indices of all rows
+ * whose index is >= aRowIndex.
+ * @param aRowIndex - start adjusting with this index
+ * @param aAdjustment - shift the row index by this amount
+ */
+ void AdjustRowIndices(int32_t aRowIndex, int32_t aAdjustment);
+
+ /** Reset the rowindices of all rows as they might have changed due to
+ * rowgroup reordering, exclude new row group frames that show in the
+ * reordering but are not yet inserted into the cellmap
+ * @param aRowGroupsToExclude - an iterator that will produce the row groups
+ * to exclude.
+ */
+ void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
+
+ nsTArray<nsTableColFrame*>& GetColCache();
+
+ protected:
+ void SetBorderCollapse(bool aValue);
+
+ BCPropertyData* GetBCProperty() const;
+ BCPropertyData* GetOrCreateBCProperty();
+ void SetFullBCDamageArea();
+ void CalcBCBorders();
+
+ void ExpandBCDamageArea(mozilla::TableArea& aRect) const;
+
+ void SetColumnDimensions(nscoord aHeight, WritingMode aWM,
+ const LogicalMargin& aBorderPadding,
+ const nsSize& aContainerSize);
+
+ int32_t CollectRows(nsIFrame* aFrame,
+ nsTArray<nsTableRowFrame*>& aCollection);
+
+ public: /* ----- Cell Map public methods ----- */
+ int32_t GetStartRowIndex(const nsTableRowGroupFrame* aRowGroupFrame) const;
+
+ /** returns the number of rows in this table.
+ */
+ int32_t GetRowCount() const { return GetCellMap()->GetRowCount(); }
+
+ /** returns the number of columns in this table after redundant columns have
+ * been removed
+ */
+ int32_t GetEffectiveColCount() const;
+
+ /* return the col count including dead cols */
+ int32_t GetColCount() const { return GetCellMap()->GetColCount(); }
+
+ // return the last col index which isn't of type eColAnonymousCell
+ int32_t GetIndexOfLastRealCol();
+
+ /** returns true if table-layout:auto */
+ bool IsAutoLayout();
+
+ public:
+ /* ---------- Row index management methods ------------ */
+
+ /** Add the given index to the existing ranges of
+ * deleted row indices and merge ranges if, with the addition of the new
+ * index, they become consecutive.
+ * @param aDeletedRowStoredIndex - index of the row that was deleted
+ * Note - 'stored' index here refers to the index that was assigned to
+ * the row before any remove row operations were performed i.e. the
+ * value of mRowIndex and not the value returned by GetRowIndex()
+ */
+ void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex);
+
+ /** Calculate the change that aStoredIndex must be increased/decreased by
+ * to get new index.
+ * Note that aStoredIndex is always the index of an undeleted row (since
+ * rows that have already been deleted can never call this method).
+ * @param aStoredIndex - The stored index value that must be adjusted
+ * Note - 'stored' index here refers to the index that was assigned to
+ * the row before any remove row operations were performed i.e. the
+ * value of mRowIndex and not the value returned by GetRowIndex()
+ */
+ int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex);
+
+ /** Returns whether mDeletedRowIndexRanges is empty
+ */
+ bool IsDeletedRowIndexRangesEmpty() const {
+ return mDeletedRowIndexRanges.empty();
+ }
+
+ public:
+#ifdef DEBUG
+ void Dump(bool aDumpRows, bool aDumpCols, bool aDumpCellMap);
+#endif
+
+ protected:
+ /**
+ * Helper method for RemoveFrame.
+ */
+ void DoRemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
+#ifdef DEBUG
+ void DumpRowGroup(nsIFrame* aChildFrame);
+#endif
+ // DATA MEMBERS
+ AutoTArray<nsTableColFrame*, 8> mColFrames;
+
+ struct TableBits {
+ uint32_t mHaveReflowedColGroups : 1; // have the col groups gotten their
+ // initial reflow
+ uint32_t mHasPctCol : 1; // does any cell or col have a pct width
+ uint32_t mCellSpansPctCol : 1; // does any cell span a col with a pct width
+ // (or containing a cell with a pct width)
+ uint32_t mIsBorderCollapse : 1; // border collapsing model vs. separate
+ // model
+ uint32_t mRowInserted : 1;
+ uint32_t mNeedToCalcBCBorders : 1;
+ uint32_t mGeometryDirty : 1;
+ uint32_t mIStartContBCBorder : 8;
+ uint32_t mNeedToCollapse : 1; // rows, cols that have visibility:collapse
+ // need to be collapsed
+ uint32_t mResizedColumns : 1; // have we resized columns since last reflow?
+ uint32_t mNeedToCalcHasBCBorders : 1;
+ uint32_t mHasBCBorders : 1;
+ } mBits;
+
+ std::map<int32_t, int32_t> mDeletedRowIndexRanges; // maintains ranges of row
+ // indices of deleted rows
+ mozilla::UniquePtr<nsTableCellMap> mCellMap; // maintains the relationships
+ // between rows, cols, and cells
+ // the layout strategy for this frame
+ mozilla::UniquePtr<nsITableLayoutStrategy> mTableLayoutStrategy;
+ nsFrameList mColGroups; // the list of colgroup frames
+};
+
+inline bool nsTableFrame::IsRowGroup(mozilla::StyleDisplay aDisplayType) const {
+ return mozilla::StyleDisplay::TableHeaderGroup == aDisplayType ||
+ mozilla::StyleDisplay::TableFooterGroup == aDisplayType ||
+ mozilla::StyleDisplay::TableRowGroup == aDisplayType;
+}
+
+inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue) {
+ mBits.mHaveReflowedColGroups = aValue;
+}
+
+inline bool nsTableFrame::HaveReflowedColGroups() const {
+ return (bool)mBits.mHaveReflowedColGroups;
+}
+
+inline bool nsTableFrame::HasPctCol() const { return (bool)mBits.mHasPctCol; }
+
+inline void nsTableFrame::SetHasPctCol(bool aValue) {
+ mBits.mHasPctCol = (unsigned)aValue;
+}
+
+inline bool nsTableFrame::HasCellSpanningPctCol() const {
+ return (bool)mBits.mCellSpansPctCol;
+}
+
+inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue) {
+ mBits.mCellSpansPctCol = (unsigned)aValue;
+}
+
+inline bool nsTableFrame::IsRowInserted() const {
+ return (bool)mBits.mRowInserted;
+}
+
+inline void nsTableFrame::SetRowInserted(bool aValue) {
+ mBits.mRowInserted = (unsigned)aValue;
+}
+
+inline void nsTableFrame::SetNeedToCollapse(bool aValue) {
+ static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse =
+ (unsigned)aValue;
+}
+
+inline bool nsTableFrame::NeedToCollapse() const {
+ return (bool)static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse;
+}
+
+inline nsFrameList& nsTableFrame::GetColGroups() {
+ return static_cast<nsTableFrame*>(FirstInFlow())->mColGroups;
+}
+
+inline nsTArray<nsTableColFrame*>& nsTableFrame::GetColCache() {
+ return mColFrames;
+}
+
+inline bool nsTableFrame::IsBorderCollapse() const {
+ return (bool)mBits.mIsBorderCollapse;
+}
+
+inline void nsTableFrame::SetBorderCollapse(bool aValue) {
+ mBits.mIsBorderCollapse = aValue;
+}
+
+inline bool nsTableFrame::NeedToCalcBCBorders() const {
+ return (bool)mBits.mNeedToCalcBCBorders;
+}
+
+inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue) {
+ mBits.mNeedToCalcBCBorders = (unsigned)aValue;
+}
+
+inline bool nsTableFrame::NeedToCalcHasBCBorders() const {
+ return (bool)mBits.mNeedToCalcHasBCBorders;
+}
+
+inline void nsTableFrame::SetNeedToCalcHasBCBorders(bool aValue) {
+ mBits.mNeedToCalcHasBCBorders = (unsigned)aValue;
+}
+
+inline bool nsTableFrame::HasBCBorders() {
+ if (NeedToCalcHasBCBorders()) {
+ CalcHasBCBorders();
+ SetNeedToCalcHasBCBorders(false);
+ }
+ return (bool)mBits.mHasBCBorders;
+}
+
+inline void nsTableFrame::SetHasBCBorders(bool aValue) {
+ mBits.mHasBCBorders = (unsigned)aValue;
+}
+
+inline nscoord nsTableFrame::GetContinuousIStartBCBorderWidth() const {
+ int32_t d2a = PresContext()->AppUnitsPerDevPixel();
+ return BC_BORDER_END_HALF_COORD(d2a, mBits.mIStartContBCBorder);
+}
+
+inline void nsTableFrame::SetContinuousIStartBCBorderWidth(nscoord aValue) {
+ mBits.mIStartContBCBorder = (unsigned)aValue;
+}
+
+#define ABORT0() \
+ { \
+ NS_ASSERTION(false, "CellIterator program error"); \
+ return; \
+ }
+
+#define ABORT1(aReturn) \
+ { \
+ NS_ASSERTION(false, "CellIterator program error"); \
+ return aReturn; \
+ }
+
+#endif