Bug 1881621 - Add colors/color_canvas.html tests to dom/canvas/test/reftest. r=bradwerth
[gecko.git] / layout / tables / nsTableRowGroupFrame.h
blobcbeea1ff13d58544daff5a92e1e1d3e37d8ffcfa
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 nsTableRowGroupFrame_h__
6 #define nsTableRowGroupFrame_h__
8 #include "mozilla/Attributes.h"
9 #include "nscore.h"
10 #include "nsContainerFrame.h"
11 #include "nsAtom.h"
12 #include "nsILineIterator.h"
13 #include "nsTArray.h"
14 #include "nsTableFrame.h"
15 #include "mozilla/WritingModes.h"
17 class nsTableRowFrame;
18 namespace mozilla {
19 class PresShell;
20 struct TableRowGroupReflowInput;
21 } // namespace mozilla
23 #define MIN_ROWS_NEEDING_CURSOR 20
25 /**
26 * nsTableRowGroupFrame is the frame that maps row groups
27 * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
28 * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame,
29 * and its children are nsTableRowFrames.
31 * @see nsTableFrame
32 * @see nsTableRowFrame
34 class nsTableRowGroupFrame final : public nsContainerFrame,
35 public nsILineIterator {
36 public:
37 NS_DECL_QUERYFRAME
38 NS_DECL_FRAMEARENA_HELPERS(nsTableRowGroupFrame)
40 /** instantiate a new instance of nsTableRowFrame.
41 * @param aPresShell the pres shell for this frame
43 * @return the frame that was created
45 friend nsTableRowGroupFrame* NS_NewTableRowGroupFrame(
46 mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
47 virtual ~nsTableRowGroupFrame();
49 // nsIFrame overrides
50 void Init(nsIContent* aContent, nsContainerFrame* aParent,
51 nsIFrame* aPrevInFlow) override {
52 nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
53 if (!aPrevInFlow) {
54 mWritingMode = GetTableFrame()->GetWritingMode();
58 void Destroy(DestroyContext&) override;
60 /** @see nsIFrame::DidSetComputedStyle */
61 void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
63 void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
64 void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
65 const nsLineList::iterator* aPrevFrameLine,
66 nsFrameList&& aFrameList) override;
67 void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override;
69 nsMargin GetUsedMargin() const override;
70 nsMargin GetUsedBorder() const override;
71 nsMargin GetUsedPadding() const override;
73 void BuildDisplayList(nsDisplayListBuilder* aBuilder,
74 const nsDisplayListSet& aLists) override;
76 /**
77 * Calls Reflow for all of its child rows.
79 * Rows are all set to the same isize and stacked in the block direction.
81 * Rows are not split unless absolutely necessary.
83 * @param aDesiredSize isize set to isize of rows, bsize set to
84 * sum of bsize of rows that fit in AvailableBSize.
86 * @see nsIFrame::Reflow
88 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
89 const ReflowInput& aReflowInput,
90 nsReflowStatus& aStatus) override;
92 bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
94 #ifdef DEBUG_FRAME_DUMP
95 nsresult GetFrameName(nsAString& aResult) const override;
96 #endif
98 nsTableRowFrame* GetFirstRow() const;
99 nsTableRowFrame* GetLastRow() const;
101 nsTableFrame* GetTableFrame() const {
102 nsIFrame* parent = GetParent();
103 MOZ_ASSERT(parent && parent->IsTableFrame());
104 return static_cast<nsTableFrame*>(parent);
107 /** return the number of child rows (not necessarily == number of child
108 * frames) */
109 int32_t GetRowCount() const;
111 /** return the table-relative row index of the first row in this rowgroup.
112 * if there are no rows, -1 is returned.
114 int32_t GetStartRowIndex() const;
116 /** Adjust the row indices of all rows whose index is >= aRowIndex.
117 * @param aRowIndex - start adjusting with this index
118 * @param aAdjustment - shift the row index by this amount
120 void AdjustRowIndices(int32_t aRowIndex, int32_t anAdjustment);
122 // See nsTableFrame.h
123 int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex);
125 /* mark rows starting from aStartRowFrame to the next 'aNumRowsToRemove-1'
126 * number of rows as deleted
128 void MarkRowsAsDeleted(nsTableRowFrame& aStartRowFrame,
129 int32_t aNumRowsToDelete);
131 // See nsTableFrame.h
132 void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex);
135 * Used for header and footer row group frames that are repeated when
136 * splitting a table frame.
138 * Performs any table specific initialization
140 * @param aHeaderFooterFrame the original header or footer row group frame
141 * that was repeated
143 void InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame);
146 * Get the total bsize of all the row rects
148 nscoord GetBSizeBasis(const ReflowInput& aReflowInput);
150 mozilla::LogicalMargin GetBCBorderWidth(mozilla::WritingMode aWM);
153 * Adjust to the effect of visibility:collapse on the row group and
154 * its children
155 * @return additional shift bstart-wards that should be applied
156 * to subsequent rowgroups due to rows and this
157 * rowgroup being collapsed
158 * @param aBTotalOffset the total amount that the rowgroup is shifted
159 * @param aISize new isize of the rowgroup
160 * @param aWM the table's writing mode
162 nscoord CollapseRowGroupIfNecessary(nscoord aBTotalOffset, nscoord aISize,
163 mozilla::WritingMode aWM);
165 // nsILineIterator methods
166 public:
167 // The table row is the equivalent to a line in block layout.
168 // The nsILineIterator assumes that a line resides in a block, this role is
169 // fullfilled by the row group. Rows in table are counted relative to the
170 // table. The row index of row corresponds to the cellmap coordinates. The
171 // line index with respect to a row group can be computed by substracting the
172 // row index of the first row in the row group.
174 /** Get the number of rows in a row group
175 * @return the number of lines in a row group
177 int32_t GetNumLines() const final;
179 /** @see nsILineIterator.h IsLineIteratorFlowRTL */
180 bool IsLineIteratorFlowRTL() final;
182 /** Return structural information about a line. */
183 Result<LineInfo, nsresult> GetLine(int32_t aLineNumber) final;
185 /** Given a frame that's a child of the rowgroup, find which line its on.
186 * @param aFrame - frame, should be a row
187 * @param aStartLine - minimal index to return
188 * @return row index relative to the row group if this a row
189 * frame and the index is at least aStartLine.
190 * -1 if the frame cannot be found.
192 int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) final;
194 /** Find the orginating cell frame on a row that is the nearest to the
195 * inline-dir coordinate of aPos.
196 * @param aLineNumber - the index of the row relative to the row group
197 * @param aPos - coordinate in twips relative to the
198 * origin of the row group
199 * @param aFrameFound - pointer to the cellframe
200 * @param aPosIsBeforeFirstFrame - the point is before the first originating
201 * cellframe
202 * @param aPosIsAfterLastFrame - the point is after the last originating
203 * cellframe
205 NS_IMETHOD FindFrameAt(int32_t aLineNumber, nsPoint aPos,
206 nsIFrame** aFrameFound, bool* aPosIsBeforeFirstFrame,
207 bool* aPosIsAfterLastFrame) final;
209 /** Check whether visual and logical order of cell frames within a line are
210 * identical. As the layout will reorder them this is always the case
211 * @param aLine - the index of the row relative to the table
212 * @param aIsReordered - returns false
213 * @param aFirstVisual - if the table is rtl first originating cell frame
214 * @param aLastVisual - if the table is rtl last originating cell frame
217 NS_IMETHOD CheckLineOrder(int32_t aLine, bool* aIsReordered,
218 nsIFrame** aFirstVisual,
219 nsIFrame** aLastVisual) final;
221 // row cursor methods to speed up searching for the row(s)
222 // containing a point. The basic idea is that we set the cursor
223 // property if the rows' y and yMosts are non-decreasing (considering only
224 // rows with nonempty overflowAreas --- empty overflowAreas never participate
225 // in event handling or painting), and the rowgroup has sufficient number of
226 // rows. The cursor property points to a "recently used" row. If we get a
227 // series of requests that work on rows "near" the cursor, then we can find
228 // those nearby rows quickly by starting our search at the cursor.
229 // This code is based on the line cursor code in nsBlockFrame. It's more
230 // general though, and could be extracted and used elsewhere.
231 struct FrameCursorData {
232 nsTArray<nsIFrame*> mFrames;
233 uint32_t mCursorIndex;
234 nscoord mOverflowAbove;
235 nscoord mOverflowBelow;
237 FrameCursorData()
238 : mFrames(MIN_ROWS_NEEDING_CURSOR),
239 mCursorIndex(0),
240 mOverflowAbove(0),
241 mOverflowBelow(0) {}
243 bool AppendFrame(nsIFrame* aFrame);
245 void FinishBuildingCursor() { mFrames.Compact(); }
248 // Clear out row cursor because we're disturbing the rows (e.g., Reflow)
249 void ClearRowCursor();
252 * Get the first row that might contain y-coord 'aY', or nullptr if you must
253 * search all rows.
254 * The actual row returned might not contain 'aY', but if not, it is
255 * guaranteed to be before any row which does contain 'aY'.
256 * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y.
257 * To find all rows that intersect the vertical interval aY/aYMost, call
258 * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all
259 * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost.
260 * That row and all subsequent rows cannot intersect the interval.
262 nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove);
265 * Set up the row cursor. After this, call AppendFrame for every
266 * child frame in sibling order. Ensure that the child frame y and YMost
267 * values form non-decreasing sequences (should always be true for table
268 * rows); if this is violated, call ClearRowCursor(). If we return nullptr,
269 * then we decided not to use a cursor or we already have one set up.
271 FrameCursorData* SetupRowCursor();
273 bool CanProvideLineIterator() const final { return true; }
274 nsILineIterator* GetLineIterator() final { return this; }
276 void InvalidateFrame(uint32_t aDisplayItemKey = 0,
277 bool aRebuildDisplayItems = true) override;
278 void InvalidateFrameWithRect(const nsRect& aRect,
279 uint32_t aDisplayItemKey = 0,
280 bool aRebuildDisplayItems = true) override;
281 void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
283 protected:
284 explicit nsTableRowGroupFrame(ComputedStyle* aStyle,
285 nsPresContext* aPresContext);
287 void InitChildReflowInput(nsPresContext* aPresContext, bool aBorderCollapse,
288 ReflowInput& aReflowInput);
290 LogicalSides GetLogicalSkipSides() const override;
292 void PlaceChild(nsPresContext* aPresContext,
293 mozilla::TableRowGroupReflowInput& aReflowInput,
294 nsIFrame* aKidFrame, const ReflowInput& aKidReflowInput,
295 mozilla::WritingMode aWM,
296 const mozilla::LogicalPoint& aKidPosition,
297 const nsSize& aContainerSize, ReflowOutput& aDesiredSize,
298 const nsRect& aOriginalKidRect,
299 const nsRect& aOriginalKidInkOverflow);
301 void CalculateRowBSizes(nsPresContext* aPresContext,
302 ReflowOutput& aDesiredSize,
303 const ReflowInput& aReflowInput);
305 void DidResizeRows(ReflowOutput& aDesiredSize);
308 * Reflow the frames we've already created
310 * @param aPresContext presentation context to use
311 * @param aReflowInput current inline state
313 void ReflowChildren(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
314 mozilla::TableRowGroupReflowInput& aReflowInput,
315 nsReflowStatus& aStatus,
316 bool* aPageBreakBeforeEnd = nullptr);
318 void SplitRowGroup(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
319 const ReflowInput& aReflowInput, nsTableFrame* aTableFrame,
320 nsReflowStatus& aStatus, bool aRowForcedPageBreak);
322 void SplitSpanningCells(nsPresContext* aPresContext,
323 const ReflowInput& aReflowInput,
324 nsTableFrame* aTableFrame, nsTableRowFrame* aFirstRow,
325 nsTableRowFrame* aLastRow, bool aFirstRowIsTopOfPage,
326 nscoord aSpanningRowBEnd,
327 const nsSize& aContainerSize,
328 nsTableRowFrame*& aContRowFrame,
329 nsTableRowFrame*& aFirstTruncatedRow,
330 nscoord& aDesiredBSize);
333 * Create a continuing table row frame, add it to the child list, and then
334 * push it and its later siblings to our overflow frames list.
336 nsTableRowFrame* CreateContinuingRowFrame(nsIFrame* aRowFrame);
338 bool IsSimpleRowFrame(nsTableFrame* aTableFrame, nsTableRowFrame* aRowFrame);
340 void GetNextRowSibling(nsIFrame** aRowFrame);
342 void UndoContinuedRow(nsPresContext* aPresContext, nsTableRowFrame* aRow);
344 public:
345 bool IsRepeatable() const;
346 void SetRepeatable(bool aRepeatable);
347 bool HasStyleBSize() const;
348 void SetHasStyleBSize(bool aValue);
349 bool HasInternalBreakBefore() const;
350 bool HasInternalBreakAfter() const;
353 inline bool nsTableRowGroupFrame::IsRepeatable() const {
354 return HasAnyStateBits(NS_ROWGROUP_REPEATABLE);
357 inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable) {
358 if (aRepeatable) {
359 AddStateBits(NS_ROWGROUP_REPEATABLE);
360 } else {
361 RemoveStateBits(NS_ROWGROUP_REPEATABLE);
365 inline bool nsTableRowGroupFrame::HasStyleBSize() const {
366 return HasAnyStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
369 inline void nsTableRowGroupFrame::SetHasStyleBSize(bool aValue) {
370 if (aValue) {
371 AddStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
372 } else {
373 RemoveStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
377 #endif