/work/obj-fuzz/dist/include/nsTableRowGroupFrame.h
Line | Count | Source (jump to first uncovered line) |
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__ |
7 | | |
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" |
16 | | |
17 | | class nsTableRowFrame; |
18 | | namespace mozilla { |
19 | | struct TableRowGroupReflowInput; |
20 | | } // namespace mozilla |
21 | | |
22 | | #define MIN_ROWS_NEEDING_CURSOR 20 |
23 | | |
24 | | /** |
25 | | * nsTableRowGroupFrame is the frame that maps row groups |
26 | | * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused |
27 | | * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame, and |
28 | | * its children are nsTableRowFrames. |
29 | | * |
30 | | * @see nsTableFrame |
31 | | * @see nsTableRowFrame |
32 | | */ |
33 | | class nsTableRowGroupFrame final |
34 | | : public nsContainerFrame |
35 | | , public nsILineIterator |
36 | | { |
37 | | using TableRowGroupReflowInput = mozilla::TableRowGroupReflowInput; |
38 | | |
39 | | public: |
40 | | NS_DECL_QUERYFRAME |
41 | | NS_DECL_FRAMEARENA_HELPERS(nsTableRowGroupFrame) |
42 | | |
43 | | /** instantiate a new instance of nsTableRowFrame. |
44 | | * @param aPresShell the pres shell for this frame |
45 | | * |
46 | | * @return the frame that was created |
47 | | */ |
48 | | friend nsTableRowGroupFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, |
49 | | ComputedStyle* aStyle); |
50 | | virtual ~nsTableRowGroupFrame(); |
51 | | |
52 | | // nsIFrame overrides |
53 | | virtual void Init(nsIContent* aContent, |
54 | | nsContainerFrame* aParent, |
55 | | nsIFrame* aPrevInFlow) override |
56 | | { |
57 | | nsContainerFrame::Init(aContent, aParent, aPrevInFlow); |
58 | | if (!aPrevInFlow) { |
59 | | mWritingMode = GetTableFrame()->GetWritingMode(); |
60 | | } |
61 | | } |
62 | | |
63 | | virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override; |
64 | | |
65 | | /** @see nsIFrame::DidSetComputedStyle */ |
66 | | virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override; |
67 | | |
68 | | virtual void AppendFrames(ChildListID aListID, |
69 | | nsFrameList& aFrameList) override; |
70 | | virtual void InsertFrames(ChildListID aListID, |
71 | | nsIFrame* aPrevFrame, |
72 | | nsFrameList& aFrameList) override; |
73 | | virtual void RemoveFrame(ChildListID aListID, |
74 | | nsIFrame* aOldFrame) override; |
75 | | |
76 | | virtual nsMargin GetUsedMargin() const override; |
77 | | virtual nsMargin GetUsedBorder() const override; |
78 | | virtual nsMargin GetUsedPadding() const override; |
79 | | |
80 | | virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
81 | | const nsDisplayListSet& aLists) override; |
82 | | |
83 | | /** calls Reflow for all of its child rows. |
84 | | * Rows are all set to the same isize and stacked in the block direction. |
85 | | * <P> rows are not split unless absolutely necessary. |
86 | | * |
87 | | * @param aDesiredSize isize set to isize of rows, bsize set to |
88 | | * sum of bsize of rows that fit in AvailableBSize. |
89 | | * |
90 | | * @see nsIFrame::Reflow |
91 | | */ |
92 | | virtual void Reflow(nsPresContext* aPresContext, |
93 | | ReflowOutput& aDesiredSize, |
94 | | const ReflowInput& aReflowInput, |
95 | | nsReflowStatus& aStatus) override; |
96 | | |
97 | | virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override; |
98 | | |
99 | | #ifdef DEBUG_FRAME_DUMP |
100 | | virtual nsresult GetFrameName(nsAString& aResult) const override; |
101 | | #endif |
102 | | |
103 | | nsTableRowFrame* GetFirstRow(); |
104 | | nsTableRowFrame* GetLastRow(); |
105 | | |
106 | | nsTableFrame* GetTableFrame() const |
107 | | { |
108 | | nsIFrame* parent = GetParent(); |
109 | | MOZ_ASSERT(parent && parent->IsTableFrame()); |
110 | | return static_cast<nsTableFrame*>(parent); |
111 | | } |
112 | | |
113 | | /** return the number of child rows (not necessarily == number of child frames) */ |
114 | | int32_t GetRowCount(); |
115 | | |
116 | | /** return the table-relative row index of the first row in this rowgroup. |
117 | | * if there are no rows, -1 is returned. |
118 | | */ |
119 | | int32_t GetStartRowIndex(); |
120 | | |
121 | | /** Adjust the row indices of all rows whose index is >= aRowIndex. |
122 | | * @param aRowIndex - start adjusting with this index |
123 | | * @param aAdjustment - shift the row index by this amount |
124 | | */ |
125 | | void AdjustRowIndices(int32_t aRowIndex, |
126 | | int32_t anAdjustment); |
127 | | |
128 | | // See nsTableFrame.h |
129 | | int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex); |
130 | | |
131 | | /* mark rows starting from aStartRowFrame to the next 'aNumRowsToRemove-1' |
132 | | * number of rows as deleted |
133 | | */ |
134 | | void MarkRowsAsDeleted(nsTableRowFrame& aStartRowFrame, |
135 | | int32_t aNumRowsToDelete); |
136 | | |
137 | | // See nsTableFrame.h |
138 | | void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex); |
139 | | |
140 | | |
141 | | /** |
142 | | * Used for header and footer row group frames that are repeated when |
143 | | * splitting a table frame. |
144 | | * |
145 | | * Performs any table specific initialization |
146 | | * |
147 | | * @param aHeaderFooterFrame the original header or footer row group frame |
148 | | * that was repeated |
149 | | */ |
150 | | nsresult InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame); |
151 | | |
152 | | |
153 | | /** |
154 | | * Get the total bsize of all the row rects |
155 | | */ |
156 | | nscoord GetBSizeBasis(const ReflowInput& aReflowInput); |
157 | | |
158 | | mozilla::LogicalMargin GetBCBorderWidth(mozilla::WritingMode aWM); |
159 | | |
160 | | /** |
161 | | * Gets inner border widths before collapsing with cell borders |
162 | | * Caller must get bstart border from previous row group or from table |
163 | | * GetContinuousBCBorderWidth will not overwrite aBorder.BStart() |
164 | | * see nsTablePainter about continuous borders |
165 | | */ |
166 | | void GetContinuousBCBorderWidth(mozilla::WritingMode aWM, |
167 | | mozilla::LogicalMargin& aBorder); |
168 | | |
169 | | /** |
170 | | * Sets full border widths before collapsing with cell borders |
171 | | * @param aForSide - side to set; only IEnd, IStart, BEnd are valid |
172 | | */ |
173 | | void SetContinuousBCBorderWidth(mozilla::LogicalSide aForSide, |
174 | | BCPixelSize aPixelValue); |
175 | | /** |
176 | | * Adjust to the effect of visibility:collapse on the row group and |
177 | | * its children |
178 | | * @return additional shift bstart-wards that should be applied |
179 | | * to subsequent rowgroups due to rows and this |
180 | | * rowgroup being collapsed |
181 | | * @param aBTotalOffset the total amount that the rowgroup is shifted |
182 | | * @param aISize new isize of the rowgroup |
183 | | * @param aWM the table's writing mode |
184 | | */ |
185 | | nscoord CollapseRowGroupIfNecessary(nscoord aBTotalOffset, |
186 | | nscoord aISize, |
187 | | mozilla::WritingMode aWM); |
188 | | |
189 | | // nsILineIterator methods |
190 | | public: |
191 | | virtual void DisposeLineIterator() override { } |
192 | | |
193 | | // The table row is the equivalent to a line in block layout. |
194 | | // The nsILineIterator assumes that a line resides in a block, this role is |
195 | | // fullfilled by the row group. Rows in table are counted relative to the |
196 | | // table. The row index of row corresponds to the cellmap coordinates. The |
197 | | // line index with respect to a row group can be computed by substracting the |
198 | | // row index of the first row in the row group. |
199 | | |
200 | | /** Get the number of rows in a row group |
201 | | * @return the number of lines in a row group |
202 | | */ |
203 | | virtual int32_t GetNumLines() override; |
204 | | |
205 | | /** @see nsILineIterator.h GetDirection |
206 | | * @return true if the table is rtl |
207 | | */ |
208 | | virtual bool GetDirection() override; |
209 | | |
210 | | /** Return structural information about a line. |
211 | | * @param aLineNumber - the index of the row relative to the row group |
212 | | * If the line-number is invalid then |
213 | | * aFirstFrameOnLine will be nullptr and |
214 | | * aNumFramesOnLine will be zero. |
215 | | * @param aFirstFrameOnLine - the first cell frame that originates in row |
216 | | * with a rowindex that matches a line number |
217 | | * @param aNumFramesOnLine - return the numbers of cells originating in |
218 | | * this row |
219 | | * @param aLineBounds - rect of the row |
220 | | */ |
221 | | NS_IMETHOD GetLine(int32_t aLineNumber, |
222 | | nsIFrame** aFirstFrameOnLine, |
223 | | int32_t* aNumFramesOnLine, |
224 | | nsRect& aLineBounds) override; |
225 | | |
226 | | /** Given a frame that's a child of the rowgroup, find which line its on. |
227 | | * @param aFrame - frame, should be a row |
228 | | * @param aStartLine - minimal index to return |
229 | | * @return row index relative to the row group if this a row |
230 | | * frame and the index is at least aStartLine. |
231 | | * -1 if the frame cannot be found. |
232 | | */ |
233 | | virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) override; |
234 | | |
235 | | /** Find the orginating cell frame on a row that is the nearest to the |
236 | | * inline-dir coordinate of aPos. |
237 | | * @param aLineNumber - the index of the row relative to the row group |
238 | | * @param aPos - coordinate in twips relative to the |
239 | | * origin of the row group |
240 | | * @param aFrameFound - pointer to the cellframe |
241 | | * @param aPosIsBeforeFirstFrame - the point is before the first originating |
242 | | * cellframe |
243 | | * @param aPosIsAfterLastFrame - the point is after the last originating |
244 | | * cellframe |
245 | | */ |
246 | | NS_IMETHOD FindFrameAt(int32_t aLineNumber, |
247 | | nsPoint aPos, |
248 | | nsIFrame** aFrameFound, |
249 | | bool* aPosIsBeforeFirstFrame, |
250 | | bool* aPosIsAfterLastFrame) override; |
251 | | |
252 | | /** Check whether visual and logical order of cell frames within a line are |
253 | | * identical. As the layout will reorder them this is always the case |
254 | | * @param aLine - the index of the row relative to the table |
255 | | * @param aIsReordered - returns false |
256 | | * @param aFirstVisual - if the table is rtl first originating cell frame |
257 | | * @param aLastVisual - if the table is rtl last originating cell frame |
258 | | */ |
259 | | |
260 | | NS_IMETHOD CheckLineOrder(int32_t aLine, |
261 | | bool *aIsReordered, |
262 | | nsIFrame **aFirstVisual, |
263 | | nsIFrame **aLastVisual) override; |
264 | | |
265 | | /** Find the next originating cell frame that originates in the row. |
266 | | * @param aFrame - cell frame to start with, will return the next cell |
267 | | * originating in a row |
268 | | * @param aLineNumber - the index of the row relative to the table |
269 | | */ |
270 | | NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) override; |
271 | | |
272 | | // row cursor methods to speed up searching for the row(s) |
273 | | // containing a point. The basic idea is that we set the cursor |
274 | | // property if the rows' y and yMosts are non-decreasing (considering only |
275 | | // rows with nonempty overflowAreas --- empty overflowAreas never participate |
276 | | // in event handling or painting), and the rowgroup has sufficient number of |
277 | | // rows. The cursor property points to a "recently used" row. If we get a |
278 | | // series of requests that work on rows "near" the cursor, then we can find |
279 | | // those nearby rows quickly by starting our search at the cursor. |
280 | | // This code is based on the line cursor code in nsBlockFrame. It's more general |
281 | | // though, and could be extracted and used elsewhere. |
282 | | struct FrameCursorData { |
283 | | nsTArray<nsIFrame*> mFrames; |
284 | | uint32_t mCursorIndex; |
285 | | nscoord mOverflowAbove; |
286 | | nscoord mOverflowBelow; |
287 | | |
288 | | FrameCursorData() |
289 | | : mFrames(MIN_ROWS_NEEDING_CURSOR), mCursorIndex(0), mOverflowAbove(0), |
290 | | mOverflowBelow(0) {} |
291 | | |
292 | | bool AppendFrame(nsIFrame* aFrame); |
293 | | |
294 | | void FinishBuildingCursor() { |
295 | | mFrames.Compact(); |
296 | | } |
297 | | }; |
298 | | |
299 | | // Clear out row cursor because we're disturbing the rows (e.g., Reflow) |
300 | | void ClearRowCursor(); |
301 | | |
302 | | /** |
303 | | * Get the first row that might contain y-coord 'aY', or nullptr if you must search |
304 | | * all rows. |
305 | | * The actual row returned might not contain 'aY', but if not, it is guaranteed |
306 | | * to be before any row which does contain 'aY'. |
307 | | * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y. |
308 | | * To find all rows that intersect the vertical interval aY/aYMost, call |
309 | | * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all |
310 | | * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost. |
311 | | * That row and all subsequent rows cannot intersect the interval. |
312 | | */ |
313 | | nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove); |
314 | | |
315 | | /** |
316 | | * Set up the row cursor. After this, call AppendFrame for every |
317 | | * child frame in sibling order. Ensure that the child frame y and YMost values |
318 | | * form non-decreasing sequences (should always be true for table rows); |
319 | | * if this is violated, call ClearRowCursor(). If we return nullptr, then we |
320 | | * decided not to use a cursor or we already have one set up. |
321 | | */ |
322 | | FrameCursorData* SetupRowCursor(); |
323 | | |
324 | | virtual nsILineIterator* GetLineIterator() override { return this; } |
325 | | |
326 | | virtual bool IsFrameOfType(uint32_t aFlags) const override |
327 | | { |
328 | | if (aFlags & eSupportsContainLayoutAndPaint) { |
329 | | return false; |
330 | | } |
331 | | |
332 | | return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart)); |
333 | | } |
334 | | |
335 | | virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true) override; |
336 | | virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true) override; |
337 | | virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); } |
338 | | |
339 | | protected: |
340 | | explicit nsTableRowGroupFrame(ComputedStyle* aStyle); |
341 | | |
342 | | void InitChildReflowInput(nsPresContext& aPresContext, |
343 | | bool aBorderCollapse, |
344 | | ReflowInput& aReflowInput); |
345 | | |
346 | | virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override; |
347 | | |
348 | | void PlaceChild(nsPresContext* aPresContext, |
349 | | TableRowGroupReflowInput& aReflowInput, |
350 | | nsIFrame* aKidFrame, |
351 | | mozilla::WritingMode aWM, |
352 | | const mozilla::LogicalPoint& aKidPosition, |
353 | | const nsSize& aContainerSize, |
354 | | ReflowOutput& aDesiredSize, |
355 | | const nsRect& aOriginalKidRect, |
356 | | const nsRect& aOriginalKidVisualOverflow); |
357 | | |
358 | | void CalculateRowBSizes(nsPresContext* aPresContext, |
359 | | ReflowOutput& aDesiredSize, |
360 | | const ReflowInput& aReflowInput); |
361 | | |
362 | | void DidResizeRows(ReflowOutput& aDesiredSize); |
363 | | |
364 | | void SlideChild(TableRowGroupReflowInput& aReflowInput, |
365 | | nsIFrame* aKidFrame); |
366 | | |
367 | | /** |
368 | | * Reflow the frames we've already created |
369 | | * |
370 | | * @param aPresContext presentation context to use |
371 | | * @param aReflowInput current inline state |
372 | | */ |
373 | | void ReflowChildren(nsPresContext* aPresContext, |
374 | | ReflowOutput& aDesiredSize, |
375 | | TableRowGroupReflowInput& aReflowInput, |
376 | | nsReflowStatus& aStatus, |
377 | | bool* aPageBreakBeforeEnd = nullptr); |
378 | | |
379 | | nsresult SplitRowGroup(nsPresContext* aPresContext, |
380 | | ReflowOutput& aDesiredSize, |
381 | | const ReflowInput& aReflowInput, |
382 | | nsTableFrame* aTableFrame, |
383 | | nsReflowStatus& aStatus, |
384 | | bool aRowForcedPageBreak); |
385 | | |
386 | | void SplitSpanningCells(nsPresContext& aPresContext, |
387 | | const ReflowInput& aReflowInput, |
388 | | nsTableFrame& aTableFrame, |
389 | | nsTableRowFrame& aFirstRow, |
390 | | nsTableRowFrame& aLastRow, |
391 | | bool aFirstRowIsTopOfPage, |
392 | | nscoord aSpanningRowBottom, |
393 | | nsTableRowFrame*& aContRowFrame, |
394 | | nsTableRowFrame*& aFirstTruncatedRow, |
395 | | nscoord& aDesiredHeight); |
396 | | |
397 | | void CreateContinuingRowFrame(nsPresContext& aPresContext, |
398 | | nsIFrame& aRowFrame, |
399 | | nsIFrame** aContRowFrame); |
400 | | |
401 | | bool IsSimpleRowFrame(nsTableFrame* aTableFrame, |
402 | | nsTableRowFrame* aRowFrame); |
403 | | |
404 | | void GetNextRowSibling(nsIFrame** aRowFrame); |
405 | | |
406 | | void UndoContinuedRow(nsPresContext* aPresContext, |
407 | | nsTableRowFrame* aRow); |
408 | | |
409 | | private: |
410 | | // border widths in pixels in the collapsing border model |
411 | | BCPixelSize mIEndContBorderWidth; |
412 | | BCPixelSize mBEndContBorderWidth; |
413 | | BCPixelSize mIStartContBorderWidth; |
414 | | |
415 | | public: |
416 | | bool IsRepeatable() const; |
417 | | void SetRepeatable(bool aRepeatable); |
418 | | bool HasStyleBSize() const; |
419 | | void SetHasStyleBSize(bool aValue); |
420 | | bool HasInternalBreakBefore() const; |
421 | | bool HasInternalBreakAfter() const; |
422 | | }; |
423 | | |
424 | | |
425 | | inline bool nsTableRowGroupFrame::IsRepeatable() const |
426 | | { |
427 | | return HasAnyStateBits(NS_ROWGROUP_REPEATABLE); |
428 | | } |
429 | | |
430 | | inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable) |
431 | | { |
432 | | if (aRepeatable) { |
433 | | AddStateBits(NS_ROWGROUP_REPEATABLE); |
434 | | } else { |
435 | | RemoveStateBits(NS_ROWGROUP_REPEATABLE); |
436 | | } |
437 | | } |
438 | | |
439 | | inline bool nsTableRowGroupFrame::HasStyleBSize() const |
440 | | { |
441 | | return HasAnyStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE); |
442 | | } |
443 | | |
444 | | inline void nsTableRowGroupFrame::SetHasStyleBSize(bool aValue) |
445 | | { |
446 | | if (aValue) { |
447 | | AddStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE); |
448 | | } else { |
449 | | RemoveStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE); |
450 | | } |
451 | | } |
452 | | |
453 | | inline void |
454 | | nsTableRowGroupFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM, |
455 | | mozilla::LogicalMargin& aBorder) |
456 | 0 | { |
457 | 0 | int32_t d2a = PresContext()->AppUnitsPerDevPixel(); |
458 | 0 | aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, |
459 | 0 | mIEndContBorderWidth); |
460 | 0 | aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a, |
461 | 0 | mBEndContBorderWidth); |
462 | 0 | aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(d2a, |
463 | 0 | mIStartContBorderWidth); |
464 | 0 | } |
465 | | #endif |