Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/tables/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
0
#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
0
  {
57
0
    nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
58
0
    if (!aPrevInFlow) {
59
0
      mWritingMode = GetTableFrame()->GetWritingMode();
60
0
    }
61
0
  }
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
0
  {
108
0
    nsIFrame* parent = GetParent();
109
0
    MOZ_ASSERT(parent && parent->IsTableFrame());
110
0
    return static_cast<nsTableFrame*>(parent);
111
0
  }
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
0
  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
0
        mOverflowBelow(0) {}
291
292
    bool AppendFrame(nsIFrame* aFrame);
293
294
0
    void FinishBuildingCursor() {
295
0
      mFrames.Compact();
296
0
    }
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
0
  virtual nsILineIterator* GetLineIterator() override { return this; }
325
326
  virtual bool IsFrameOfType(uint32_t aFlags) const override
327
0
  {
328
0
    if (aFlags & eSupportsContainLayoutAndPaint) {
329
0
      return false;
330
0
    }
331
0
332
0
    return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
333
0
  }
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
0
  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
0
{
427
0
  return HasAnyStateBits(NS_ROWGROUP_REPEATABLE);
428
0
}
429
430
inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable)
431
0
{
432
0
  if (aRepeatable) {
433
0
    AddStateBits(NS_ROWGROUP_REPEATABLE);
434
0
  } else {
435
0
    RemoveStateBits(NS_ROWGROUP_REPEATABLE);
436
0
  }
437
0
}
438
439
inline bool nsTableRowGroupFrame::HasStyleBSize() const
440
0
{
441
0
  return HasAnyStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
442
0
}
443
444
inline void nsTableRowGroupFrame::SetHasStyleBSize(bool aValue)
445
0
{
446
0
  if (aValue) {
447
0
    AddStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
448
0
  } else {
449
0
    RemoveStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
450
0
  }
451
0
}
452
453
inline void
454
nsTableRowGroupFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
455
                                                 mozilla::LogicalMargin& aBorder)
456
{
457
  int32_t d2a = PresContext()->AppUnitsPerDevPixel();
458
  aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a,
459
                                                 mIEndContBorderWidth);
460
  aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a,
461
                                                 mBEndContBorderWidth);
462
  aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(d2a,
463
                                                 mIStartContBorderWidth);
464
}
465
#endif