Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/nsTableFrame.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 nsTableFrame_h__
6
#define nsTableFrame_h__
7
8
#include "mozilla/Attributes.h"
9
#include "celldata.h"
10
#include "imgIContainer.h"
11
#include "nscore.h"
12
#include "nsContainerFrame.h"
13
#include "nsStyleCoord.h"
14
#include "nsStyleConsts.h"
15
#include "nsCellMap.h"
16
#include "nsGkAtoms.h"
17
#include "nsDisplayList.h"
18
#include "TableArea.h"
19
20
struct BCPaintBorderAction;
21
class nsTableCellFrame;
22
class nsTableCellMap;
23
class nsTableColFrame;
24
class nsTableRowGroupFrame;
25
class nsTableRowFrame;
26
class nsTableColGroupFrame;
27
class nsITableLayoutStrategy;
28
namespace mozilla {
29
class WritingMode;
30
class LogicalMargin;
31
struct TableReflowInput;
32
namespace layers {
33
class StackingContextHelper;
34
}
35
} // namespace mozilla
36
37
struct BCPropertyData;
38
39
static inline bool
40
IsTableCell(mozilla::LayoutFrameType frameType)
41
0
{
42
0
  return frameType == mozilla::LayoutFrameType::TableCell ||
43
0
         frameType == mozilla::LayoutFrameType::BCTableCell;
44
0
}
Unexecuted instantiation: Unified_cpp_dom_base4.cpp:IsTableCell(mozilla::LayoutFrameType)
Unexecuted instantiation: Unified_cpp_accessible_generic0.cpp:IsTableCell(mozilla::LayoutFrameType)
45
46
class nsDisplayTableItem : public nsDisplayItem
47
{
48
public:
49
  nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
50
                     bool aDrawsBackground = true) :
51
      nsDisplayItem(aBuilder, aFrame),
52
      mPartHasFixedBackground(false),
53
      mDrawsBackground(aDrawsBackground) {}
54
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
  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
60
                           bool* aSnap) const override;
61
62
  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
63
  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
64
                                         const nsDisplayItemGeometry* aGeometry,
65
                                         nsRegion *aInvalidRegion) const override;
66
67
  void UpdateForFrameBackground(nsIFrame* aFrame);
68
69
private:
70
  bool mPartHasFixedBackground;
71
  bool mDrawsBackground;
72
};
73
74
class nsAutoPushCurrentTableItem
75
{
76
public:
77
  nsAutoPushCurrentTableItem()
78
    : mBuilder(nullptr)
79
    , mOldCurrentItem(nullptr) {}
80
81
  void Push(nsDisplayListBuilder* aBuilder, nsDisplayTableItem* aPushItem)
82
  {
83
    mBuilder = aBuilder;
84
    mOldCurrentItem = aBuilder->GetCurrentTableItem();
85
    aBuilder->SetCurrentTableItem(aPushItem);
86
#ifdef DEBUG
87
    mPushedItem = aPushItem;
88
#endif
89
  }
90
  ~nsAutoPushCurrentTableItem() {
91
    if (!mBuilder)
92
      return;
93
#ifdef DEBUG
94
    NS_ASSERTION(mBuilder->GetCurrentTableItem() == mPushedItem,
95
                 "Someone messed with the current table item behind our back!");
96
#endif
97
    mBuilder->SetCurrentTableItem(mOldCurrentItem);
98
  }
99
100
private:
101
  nsDisplayListBuilder* mBuilder;
102
  nsDisplayTableItem*   mOldCurrentItem;
103
#ifdef DEBUG
104
  nsDisplayTableItem*   mPushedItem;
105
#endif
106
};
107
108
/* ============================================================================ */
109
110
enum nsTableColType {
111
  eColContent            = 0, // there is real col content associated
112
  eColAnonymousCol       = 1, // the result of a span on a col
113
  eColAnonymousColGroup  = 2, // the result of a span on a col group
114
  eColAnonymousCell      = 3  // the result of a cell alone
115
};
116
117
/**
118
  * nsTableFrame maps the inner portion of a table (everything except captions.)
119
  * Used as a pseudo-frame within nsTableWrapperFrame, it may also be used
120
  * stand-alone as the top-level frame.
121
  *
122
  * The principal child list contains row group frames. There is also an
123
  * additional child list, kColGroupList, which contains the col group frames.
124
  */
125
class nsTableFrame : public nsContainerFrame
126
{
127
  typedef mozilla::image::ImgDrawResult ImgDrawResult;
128
  typedef mozilla::WritingMode WritingMode;
129
  typedef mozilla::LogicalMargin LogicalMargin;
130
  typedef mozilla::TableReflowInput TableReflowInput;
131
132
public:
133
  NS_DECL_FRAMEARENA_HELPERS(nsTableFrame)
134
135
  typedef nsTArray<nsIFrame*> FrameTArray;
136
  NS_DECLARE_FRAME_PROPERTY_DELETABLE(PositionedTablePartArray, FrameTArray)
137
138
  /** nsTableWrapperFrame has intimate knowledge of the inner table frame */
139
  friend class nsTableWrapperFrame;
140
141
  /** instantiate a new instance of nsTableRowFrame.
142
    * @param aPresShell the pres shell for this frame
143
    *
144
    * @return           the frame that was created
145
    */
146
  friend nsTableFrame* NS_NewTableFrame(nsIPresShell* aPresShell,
147
                                        ComputedStyle* aStyle);
148
149
  /** sets defaults for table-specific style.
150
    * @see nsIFrame::Init
151
    */
152
  virtual void Init(nsIContent*       aContent,
153
                    nsContainerFrame* aParent,
154
                    nsIFrame*         aPrevInFlow) override;
155
156
  static float GetTwipsToPixels(nsPresContext* aPresContext);
157
158
  // Return true if aParentReflowInput.frame or any of its ancestors within
159
  // the containing table have non-auto bsize. (e.g. pct or fixed bsize)
160
  static bool AncestorsHaveStyleBSize(const ReflowInput& aParentReflowInput);
161
162
  // See if a special bsize reflow will occur due to having a pct bsize when
163
  // the pct bsize basis may not yet be valid.
164
  static void CheckRequestSpecialBSizeReflow(const ReflowInput& aReflowInput);
165
166
  // Notify the frame and its ancestors (up to the containing table) that a special
167
  // height reflow will occur.
168
  static void RequestSpecialBSizeReflow(const ReflowInput& aReflowInput);
169
170
  static void RePositionViews(nsIFrame* aFrame);
171
172
  static bool PageBreakAfter(nsIFrame* aSourceFrame,
173
                               nsIFrame* aNextFrame);
174
175
  // Register a positioned table part with its nsTableFrame. These objects will
176
  // be visited by FixupPositionedTableParts after reflow is complete. (See that
177
  // function for more explanation.) Should be called during frame construction.
178
  static void RegisterPositionedTablePart(nsIFrame* aFrame);
179
180
  // Unregister a positioned table part with its nsTableFrame.
181
  static void UnregisterPositionedTablePart(nsIFrame* aFrame,
182
                                            nsIFrame* aDestructRoot);
183
184
  nsPoint GetFirstSectionOrigin(const ReflowInput& aReflowInput) const;
185
186
  /*
187
   * Notification that rowspan or colspan has changed for content inside a
188
   * table cell
189
   */
190
  void RowOrColSpanChanged(nsTableCellFrame* aCellFrame);
191
192
  /** @see nsIFrame::DestroyFrom */
193
  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
194
195
  /** @see nsIFrame::DidSetComputedStyle */
196
  virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
197
198
  virtual void SetInitialChildList(ChildListID     aListID,
199
                                   nsFrameList&    aChildList) override;
200
  virtual void AppendFrames(ChildListID     aListID,
201
                            nsFrameList&    aFrameList) override;
202
  virtual void InsertFrames(ChildListID     aListID,
203
                            nsIFrame*       aPrevFrame,
204
                            nsFrameList&    aFrameList) override;
205
  virtual void RemoveFrame(ChildListID     aListID,
206
                           nsIFrame*       aOldFrame) override;
207
208
  virtual nsMargin GetUsedBorder() const override;
209
  virtual nsMargin GetUsedPadding() const override;
210
  virtual nsMargin GetUsedMargin() const override;
211
212
  // Get the offset from the border box to the area where the row groups fit
213
  LogicalMargin GetChildAreaOffset(const WritingMode aWM,
214
                                   const ReflowInput* aReflowInput) const;
215
216
  /** helper method to find the table parent of any table frame object */
217
  static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame);
218
219
  /* Like GetTableFrame, but will set *aDidPassThrough to false if we don't
220
   * pass through aMustPassThrough on the way to the table.
221
   */
222
  static nsTableFrame* GetTableFramePassingThrough(nsIFrame* aMustPassThrough,
223
                                                   nsIFrame* aSourceFrame,
224
                                                   bool* aDidPassThrough);
225
226
  typedef void (* DisplayGenericTablePartTraversal)
227
      (nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
228
       const nsDisplayListSet& aLists);
229
  static void GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
230
                               const nsDisplayListSet& aLists);
231
232
  /**
233
   * Helper method to handle display common to table frames, rowgroup frames
234
   * and row frames. It creates a background display item for handling events
235
   * if necessary, an outline display item if necessary, and displays
236
   * all the the frame's children.
237
   * @param aDisplayItem the display item created for this part, or null
238
   * if this part's border/background painting is delegated to an ancestor
239
   * @param aTraversal a function that gets called to traverse the table
240
   * part's child frames and add their display list items to a
241
   * display list set.
242
   */
243
  static void DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
244
                                      nsFrame* aFrame,
245
                                      const nsDisplayListSet& aLists,
246
                                      DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
247
248
  // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
249
  // of type aChildType.
250
  static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
251
                                      nsIFrame* aPriorChildFrame,
252
                                      mozilla::LayoutFrameType aChildType);
253
  bool IsAutoBSize(mozilla::WritingMode aWM);
254
255
  /** @return true if aDisplayType represents a rowgroup of any sort
256
    * (header, footer, or body)
257
    */
258
  bool IsRowGroup(mozilla::StyleDisplay aDisplayType) const;
259
260
  virtual const nsFrameList& GetChildList(ChildListID aListID) const override;
261
  virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
262
263
  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
264
                                const nsDisplayListSet& aLists) override;
265
266
  /** Get the outer half (i.e., the part outside the height and width of
267
   *  the table) of the largest segment (?) of border-collapsed border on
268
   *  the table on each side, or 0 for non border-collapsed tables.
269
   */
270
  LogicalMargin GetOuterBCBorder(const WritingMode aWM) const;
271
272
  /** Same as above, but only if it's included from the border-box width
273
   *  of the table.
274
   */
275
  LogicalMargin GetIncludedOuterBCBorder(const WritingMode aWM) const;
276
277
  /** Same as above, but only if it's excluded from the border-box width
278
   *  of the table.  This is the area that leaks out into the margin
279
   *  (or potentially past it, if there is no margin).
280
   */
281
  LogicalMargin GetExcludedOuterBCBorder(const WritingMode aWM) const;
282
283
  /**
284
   * In quirks mode, the size of the table background is reduced
285
   * by the outer BC border. Compute the reduction needed.
286
   */
287
  nsMargin GetDeflationForBackground(nsPresContext* aPresContext) const;
288
289
  /** Get width of table + colgroup + col collapse: elements that
290
   *  continue along the length of the whole iStart side.
291
   *  see nsTablePainter about continuous borders
292
   */
293
  nscoord GetContinuousIStartBCBorderWidth() const;
294
  void SetContinuousIStartBCBorderWidth(nscoord aValue);
295
296
  friend class nsDelayedCalcBCBorders;
297
298
  void AddBCDamageArea(const mozilla::TableArea& aValue);
299
  bool BCRecalcNeeded(ComputedStyle* aOldComputedStyle,
300
                        ComputedStyle* aNewComputedStyle);
301
  void PaintBCBorders(DrawTarget& aDrawTarget, const nsRect& aDirtyRect);
302
  void CreateWebRenderCommandsForBCBorders(mozilla::wr::DisplayListBuilder& aBuilder,
303
                                           const mozilla::layers::StackingContextHelper& aSc,
304
                                           const nsRect& aVisibleRect,
305
                                           const nsPoint& aOffsetToReferenceFrame);
306
307
  virtual void MarkIntrinsicISizesDirty() override;
308
  // For border-collapse tables, the caller must not add padding and
309
  // border to the results of these functions.
310
  virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
311
  virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
312
  IntrinsicISizeOffsetData IntrinsicISizeOffsets(nscoord aPercentageBasis =
313
                                                 NS_UNCONSTRAINEDSIZE) override;
314
315
  virtual mozilla::LogicalSize
316
  ComputeSize(gfxContext*                 aRenderingContext,
317
              mozilla::WritingMode        aWM,
318
              const mozilla::LogicalSize& aCBSize,
319
              nscoord                     aAvailableISize,
320
              const mozilla::LogicalSize& aMargin,
321
              const mozilla::LogicalSize& aBorder,
322
              const mozilla::LogicalSize& aPadding,
323
              ComputeSizeFlags            aFlags) override;
324
325
  virtual mozilla::LogicalSize
326
  ComputeAutoSize(gfxContext*                 aRenderingContext,
327
                  mozilla::WritingMode        aWM,
328
                  const mozilla::LogicalSize& aCBSize,
329
                  nscoord                     aAvailableISize,
330
                  const mozilla::LogicalSize& aMargin,
331
                  const mozilla::LogicalSize& aBorder,
332
                  const mozilla::LogicalSize& aPadding,
333
                  ComputeSizeFlags            aFlags) override;
334
335
  /**
336
   * A copy of nsFrame::ShrinkWidthToFit that calls a different
337
   * GetPrefISize, since tables have two different ones.
338
   */
339
  nscoord TableShrinkISizeToFit(gfxContext *aRenderingContext,
340
                                nscoord aWidthInCB);
341
342
  // XXXldb REWRITE THIS COMMENT!
343
  /** inner tables are reflowed in two steps.
344
    * <pre>
345
    * if mFirstPassValid is false, this is our first time through since content was last changed
346
    *   set pass to 1
347
    *   do pass 1
348
    *     get min/max info for all cells in an infinite space
349
    *   do column balancing
350
    *   set mFirstPassValid to true
351
    *   do pass 2
352
    *     use column widths to Reflow cells
353
    * </pre>
354
    *
355
    * @see nsIFrame::Reflow
356
    */
357
  virtual void Reflow(nsPresContext*           aPresContext,
358
                      ReflowOutput&     aDesiredSize,
359
                      const ReflowInput& aReflowInput,
360
                      nsReflowStatus&          aStatus) override;
361
362
  void ReflowTable(ReflowOutput&     aDesiredSize,
363
                   const ReflowInput& aReflowInput,
364
                   nscoord                  aAvailBSize,
365
                   nsIFrame*&               aLastChildReflowed,
366
                   nsReflowStatus&          aStatus);
367
368
  nsFrameList& GetColGroups();
369
370
  virtual ComputedStyle*
371
  GetParentComputedStyle(nsIFrame** aProviderFrame) const override;
372
373
  virtual bool IsFrameOfType(uint32_t aFlags) const override
374
  {
375
    if (aFlags & eSupportsCSSTransforms) {
376
      return false;
377
    }
378
    return nsContainerFrame::IsFrameOfType(aFlags);
379
  }
380
381
#ifdef DEBUG_FRAME_DUMP
382
  /** @see nsIFrame::GetFrameName */
383
  virtual nsresult GetFrameName(nsAString& aResult) const override;
384
#endif
385
386
  /** Return the isize of the column at aColIndex.
387
   *  This may only be called on the table's first-in-flow.
388
   */
389
  nscoord GetColumnISizeFromFirstInFlow(int32_t aColIndex);
390
391
  /** Helper to get the column spacing style value.
392
   *  The argument refers to the space between column aColIndex and column
393
   *  aColIndex + 1.  An index of -1 indicates the padding between the table
394
   *  and the left border, an index equal to the number of columns indicates
395
   *  the padding between the table and the right border.
396
   *
397
   *  Although in this class cell spacing does not depend on the index, it
398
   *  may be important for overriding classes.
399
   */
400
  virtual nscoord GetColSpacing(int32_t aColIndex);
401
402
  /** Helper to find the sum of the cell spacing between arbitrary columns.
403
   *  The argument refers to the space between column aColIndex and column
404
   *  aColIndex + 1.  An index of -1 indicates the padding between the table
405
   *  and the left border, an index equal to the number of columns indicates
406
   *  the padding between the table and the right border.
407
   *
408
   *  This method is equivalent to
409
   *  nscoord result = 0;
410
   *  for (i = aStartColIndex; i < aEndColIndex; i++) {
411
   *    result += GetColSpacing(i);
412
   *  }
413
   *  return result;
414
   */
415
  virtual nscoord GetColSpacing(int32_t aStartColIndex,
416
                                int32_t aEndColIndex);
417
418
  /** Helper to get the row spacing style value.
419
   *  The argument refers to the space between row aRowIndex and row
420
   *  aRowIndex + 1.  An index of -1 indicates the padding between the table
421
   *  and the top border, an index equal to the number of rows indicates
422
   *  the padding between the table and the bottom border.
423
   *
424
   *  Although in this class cell spacing does not depend on the index, it
425
   *  may be important for overriding classes.
426
   */
427
  virtual nscoord GetRowSpacing(int32_t aRowIndex);
428
429
  /** Helper to find the sum of the cell spacing between arbitrary rows.
430
   *  The argument refers to the space between row aRowIndex and row
431
   *  aRowIndex + 1.  An index of -1 indicates the padding between the table
432
   *  and the top border, an index equal to the number of rows indicates
433
   *  the padding between the table and the bottom border.
434
   *
435
   *  This method is equivalent to
436
   *  nscoord result = 0;
437
   *  for (i = aStartRowIndex; i < aEndRowIndex; i++) {
438
   *    result += GetRowSpacing(i);
439
   *  }
440
   *  return result;
441
   */
442
  virtual nscoord GetRowSpacing(int32_t aStartRowIndex,
443
                                  int32_t aEndRowIndex);
444
445
private:
446
  /* For the base implementation of nsTableFrame, cell spacing does not depend
447
   * on row/column indexing.
448
   */
449
  nscoord GetColSpacing();
450
  nscoord GetRowSpacing();
451
452
public:
453
  virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;
454
  bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
455
                                 BaselineSharingGroup aBaselineGroup,
456
                                 nscoord*             aBaseline) const override;
457
458
  /** return the row span of a cell, taking into account row span magic at the bottom
459
    * of a table. The row span equals the number of rows spanned by aCell starting at
460
    * aStartRowIndex, and can be smaller if aStartRowIndex is greater than the row
461
    * index in which aCell originates.
462
    *
463
    * @param aStartRowIndex the cell
464
    * @param aCell          the cell
465
    *
466
    * @return  the row span, correcting for row spans that extend beyond the bottom
467
    *          of the table.
468
    */
469
  int32_t  GetEffectiveRowSpan(int32_t                 aStartRowIndex,
470
                               const nsTableCellFrame& aCell) const;
471
  int32_t  GetEffectiveRowSpan(const nsTableCellFrame& aCell,
472
                               nsCellMap*              aCellMap = nullptr);
473
474
  /** return the col span of a cell, taking into account col span magic at the edge
475
    * of a table.
476
    *
477
    * @param aCell      the cell
478
    *
479
    * @return  the col span, correcting for col spans that extend beyond the edge
480
    *          of the table.
481
    */
482
  int32_t  GetEffectiveColSpan(const nsTableCellFrame& aCell,
483
                               nsCellMap*              aCellMap = nullptr) const;
484
485
  /** indicate whether the row has more than one cell that either originates
486
    * or is spanned from the rows above
487
    */
488
  bool HasMoreThanOneCell(int32_t aRowIndex) const;
489
490
  /** return the column frame associated with aColIndex
491
    * returns nullptr if the col frame has not yet been allocated, or if
492
    * aColIndex is out of range
493
    */
494
  nsTableColFrame* GetColFrame(int32_t aColIndex) const;
495
496
  /** Insert a col frame reference into the colframe cache and adapt the cellmap
497
    * @param aColFrame    - the column frame
498
    * @param aColIndex    - index where the column should be inserted into the
499
    *                       colframe cache
500
    */
501
  void InsertCol(nsTableColFrame& aColFrame,
502
                 int32_t          aColIndex);
503
504
  nsTableColGroupFrame* CreateSyntheticColGroupFrame();
505
506
  int32_t DestroyAnonymousColFrames(int32_t aNumFrames);
507
508
  // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our
509
  // last synthetic colgroup.  If we have no such colgroup, then create one.
510
  void AppendAnonymousColFrames(int32_t aNumColsToAdd);
511
512
  // Append aNumColsToAdd anonymous col frames of type aColType to
513
  // aColGroupFrame.  If aAddToTable is true, also call AddColsToTable on the
514
  // new cols.
515
  void AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame,
516
                                int32_t               aNumColsToAdd,
517
                                nsTableColType        aColType,
518
                                bool                  aAddToTable);
519
520
  void MatchCellMapToColCache(nsTableCellMap* aCellMap);
521
  /** empty the column frame cache */
522
  void ClearColCache();
523
524
  void DidResizeColumns();
525
526
  void AppendCell(nsTableCellFrame& aCellFrame,
527
                  int32_t           aRowIndex);
528
529
  void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
530
                   int32_t                      aRowIndex,
531
                   int32_t                      aColIndexBefore);
532
533
  void RemoveCell(nsTableCellFrame* aCellFrame,
534
                  int32_t           aRowIndex);
535
536
  void AppendRows(nsTableRowGroupFrame*       aRowGroupFrame,
537
                  int32_t                     aRowIndex,
538
                  nsTArray<nsTableRowFrame*>& aRowFrames);
539
540
  int32_t InsertRows(nsTableRowGroupFrame*       aRowGroupFrame,
541
                     nsTArray<nsTableRowFrame*>& aFrames,
542
                     int32_t                     aRowIndex,
543
                     bool                        aConsiderSpans);
544
545
  void RemoveRows(nsTableRowFrame& aFirstRowFrame,
546
                  int32_t          aNumRowsToRemove,
547
                  bool             aConsiderSpans);
548
549
  /** Insert multiple rowgroups into the table cellmap handling
550
    * @param aRowGroups - iterator that iterates over the rowgroups to insert
551
    */
552
  void InsertRowGroups(const nsFrameList::Slice& aRowGroups);
553
554
  void InsertColGroups(int32_t                   aStartColIndex,
555
                       const nsFrameList::Slice& aColgroups);
556
557
  void RemoveCol(nsTableColGroupFrame* aColGroupFrame,
558
                 int32_t               aColIndex,
559
                 bool                  aRemoveFromCache,
560
                 bool                  aRemoveFromCellMap);
561
562
  bool ColumnHasCellSpacingBefore(int32_t aColIndex) const;
563
564
  bool HasPctCol() const;
565
  void SetHasPctCol(bool aValue);
566
567
  bool HasCellSpanningPctCol() const;
568
  void SetHasCellSpanningPctCol(bool aValue);
569
570
  /**
571
   * To be called on a frame by its parent after setting its size/position and
572
   * calling DidReflow (possibly via FinishReflowChild()).  This can also be
573
   * used for child frames which are not being reflowed but did have their size
574
   * or position changed.
575
   *
576
   * @param aFrame The frame to invalidate
577
   * @param aOrigRect The original rect of aFrame (before the change).
578
   * @param aOrigVisualOverflow The original overflow rect of aFrame.
579
   * @param aIsFirstReflow True if the size/position change is due to the
580
   *                       first reflow of aFrame.
581
   */
582
  static void InvalidateTableFrame(nsIFrame* aFrame,
583
                                   const nsRect& aOrigRect,
584
                                   const nsRect& aOrigVisualOverflow,
585
                                   bool aIsFirstReflow);
586
587
  virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
588
589
  // Return our wrapper frame.
590
  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
591
592
protected:
593
  static void UpdateStyleOfOwnedAnonBoxesForTableWrapper(
594
    nsIFrame* aOwningFrame,
595
    nsIFrame* aWrapperFrame,
596
    mozilla::ServoRestyleState& aRestyleState);
597
598
  /** protected constructor.
599
    * @see NewFrame
600
    */
601
  explicit nsTableFrame(ComputedStyle* aStyle, ClassID aID = kClassID);
602
603
  /** destructor, responsible for mColumnLayoutData */
604
  virtual ~nsTableFrame();
605
606
  void InitChildReflowInput(ReflowInput& aReflowInput);
607
608
  virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
609
610
  void IterateBCBorders(BCPaintBorderAction& aAction, const nsRect& aDirtyRect);
611
612
public:
613
  bool IsRowInserted() const;
614
  void   SetRowInserted(bool aValue);
615
616
protected:
617
618
  // A helper function to reflow a header or footer with unconstrained height
619
  // to see if it should be made repeatable and also to determine its desired
620
  // height.
621
  nsresult SetupHeaderFooterChild(const TableReflowInput& aReflowInput,
622
                                  nsTableRowGroupFrame* aFrame,
623
                                  nscoord* aDesiredHeight);
624
625
  void ReflowChildren(TableReflowInput&  aReflowInput,
626
                      nsReflowStatus&      aStatus,
627
                      nsIFrame*&           aLastChildReflowed,
628
                      nsOverflowAreas&     aOverflowAreas);
629
630
  // This calls the col group and column reflow methods, which do two things:
631
  //  (1) set all the dimensions to 0
632
  //  (2) notify the table about colgroups or columns with hidden visibility
633
  void ReflowColGroups(gfxContext* aRenderingContext);
634
635
  /** return the isize of the table taking into account visibility collapse
636
    * on columns and colgroups
637
    * @param aBorderPadding  the border and padding of the table
638
    */
639
  nscoord GetCollapsedISize(const WritingMode aWM,
640
                            const LogicalMargin& aBorderPadding);
641
642
643
  /** Adjust the table for visibility.collapse set on rowgroups, rows,
644
    * colgroups and cols
645
    * @param aDesiredSize    the metrics of the table
646
    * @param aBorderPadding  the border and padding of the table
647
    */
648
  void AdjustForCollapsingRowsCols(ReflowOutput& aDesiredSize,
649
                                   const WritingMode aWM,
650
                                   const LogicalMargin& aBorderPadding);
651
652
  /** FixupPositionedTableParts is called at the end of table reflow to reflow
653
   *  the absolutely positioned descendants of positioned table parts. This is
654
   *  necessary because the dimensions of table parts may change after they've
655
   *  been reflowed (e.g. in AdjustForCollapsingRowsCols).
656
   */
657
  void FixupPositionedTableParts(nsPresContext*           aPresContext,
658
                                 ReflowOutput&     aDesiredSize,
659
                                 const ReflowInput& aReflowInput);
660
661
  // Clears the list of positioned table parts.
662
  void ClearAllPositionedTableParts();
663
664
  nsITableLayoutStrategy* LayoutStrategy() const {
665
    return static_cast<nsTableFrame*>(FirstInFlow())->
666
      mTableLayoutStrategy;
667
  }
668
669
  // Helper for InsertFrames.
670
  void HomogenousInsertFrames(ChildListID     aListID,
671
                              nsIFrame*       aPrevFrame,
672
                              nsFrameList&    aFrameList);
673
private:
674
  /* Handle a row that got inserted during reflow.  aNewHeight is the
675
     new height of the table after reflow. */
676
  void ProcessRowInserted(nscoord aNewHeight);
677
678
  // WIDTH AND HEIGHT CALCULATION
679
680
public:
681
682
  // calculate the computed block-size of aFrame including its border and
683
  // padding given its reflow state.
684
  nscoord CalcBorderBoxBSize(const ReflowInput& aReflowInput);
685
686
protected:
687
688
  // update the  desired block-size of this table taking into account the current
689
  // reflow state, the table attributes and the content driven rowgroup bsizes
690
  // this function can change the overflow area
691
  void CalcDesiredBSize(const ReflowInput& aReflowInput,
692
                        ReflowOutput& aDesiredSize);
693
694
  // The following is a helper for CalcDesiredBSize
695
696
  void DistributeBSizeToRows(const ReflowInput& aReflowInput,
697
                             nscoord                  aAmount);
698
699
  void PlaceChild(TableReflowInput&  aReflowInput,
700
                  nsIFrame*            aKidFrame,
701
                  nsPoint              aKidPosition,
702
                  ReflowOutput& aKidDesiredSize,
703
                  const nsRect&        aOriginalKidRect,
704
                  const nsRect&        aOriginalKidVisualOverflow);
705
   void PlaceRepeatedFooter(TableReflowInput& aReflowInput,
706
                            nsTableRowGroupFrame *aTfoot,
707
                            nscoord aFooterHeight);
708
709
  nsIFrame* GetFirstBodyRowGroupFrame();
710
public:
711
  typedef AutoTArray<nsTableRowGroupFrame*, 8> RowGroupArray;
712
  /**
713
   * Push all our child frames from the aRowGroups array, in order, starting
714
   * from the frame at aPushFrom to the end of the array. The frames are put on
715
   * our overflow list or moved directly to our next-in-flow if one exists.
716
   */
717
protected:
718
  void PushChildren(const RowGroupArray& aRowGroups, int32_t aPushFrom);
719
720
public:
721
  // put the children frames in the display order (e.g. thead before tbodies
722
  // before tfoot). This will handle calling GetRowGroupFrame() on the
723
  // children, and not append nulls, so the array is guaranteed to contain
724
  // nsTableRowGroupFrames.  If there are multiple theads or tfoots, all but
725
  // the first one are treated as tbodies instead.
726
727
  void OrderRowGroups(RowGroupArray& aChildren,
728
                      nsTableRowGroupFrame** aHead = nullptr,
729
                      nsTableRowGroupFrame** aFoot = nullptr) const;
730
731
  // Return the thead, if any
732
  nsTableRowGroupFrame* GetTHead() const;
733
734
  // Return the tfoot, if any
735
  nsTableRowGroupFrame* GetTFoot() const;
736
737
  // Returns true if there are any cells above the row at
738
  // aRowIndex and spanning into the row at aRowIndex, the number of
739
  // effective columns limits the search up to that column
740
  bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols);
741
742
  // Returns true if there is a cell originating in aRowIndex
743
  // which spans into the next row,  the number of effective
744
  // columns limits the search up to that column
745
  bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols);
746
747
protected:
748
749
  bool HaveReflowedColGroups() const;
750
  void   SetHaveReflowedColGroups(bool aValue);
751
752
public:
753
  bool IsBorderCollapse() const;
754
755
  bool NeedToCalcBCBorders() const;
756
  void SetNeedToCalcBCBorders(bool aValue);
757
758
  bool NeedToCollapse() const;
759
  void SetNeedToCollapse(bool aValue);
760
761
  bool NeedToCalcHasBCBorders() const;
762
  void SetNeedToCalcHasBCBorders(bool aValue);
763
764
  void CalcHasBCBorders();
765
  bool HasBCBorders();
766
  void SetHasBCBorders(bool aValue);
767
768
  /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
769
    * state bit, which implies that all descendants are dirty.  The
770
    * GeometryDirty still implies that all the parts of the table are
771
    * dirty, but resizing optimizations should still apply to the
772
    * contents of the individual cells.
773
    */
774
  void SetGeometryDirty() { mBits.mGeometryDirty = true; }
775
  void ClearGeometryDirty() { mBits.mGeometryDirty = false; }
776
  bool IsGeometryDirty() const { return mBits.mGeometryDirty; }
777
778
  /** Get the cell map for this table frame.  It is not always mCellMap.
779
    * Only the firstInFlow has a legit cell map
780
    */
781
  nsTableCellMap* GetCellMap() const;
782
783
  /** Iterate over the row groups and adjust the row indices of all rows
784
   * whose index is >= aRowIndex.
785
   * @param aRowIndex   - start adjusting with this index
786
   * @param aAdjustment - shift the row index by this amount
787
   */
788
  void AdjustRowIndices(int32_t aRowIndex,
789
                        int32_t aAdjustment);
790
791
  /** Reset the rowindices of all rows as they might have changed due to
792
    * rowgroup reordering, exclude new row group frames that show in the
793
    * reordering but are not yet inserted into the cellmap
794
    * @param aRowGroupsToExclude - an iterator that will produce the row groups
795
    *                              to exclude.
796
    */
797
  void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
798
799
  nsTArray<nsTableColFrame*>& GetColCache();
800
801
802
protected:
803
804
  void SetBorderCollapse(bool aValue);
805
806
  BCPropertyData* GetBCProperty() const;
807
  BCPropertyData* GetOrCreateBCProperty();
808
  void SetFullBCDamageArea();
809
  void CalcBCBorders();
810
811
  void ExpandBCDamageArea(mozilla::TableArea& aRect) const;
812
813
  void SetColumnDimensions(nscoord aHeight, WritingMode aWM,
814
                           const LogicalMargin& aBorderPadding,
815
                           const nsSize& aContainerSize);
816
817
  int32_t CollectRows(nsIFrame*                   aFrame,
818
                      nsTArray<nsTableRowFrame*>& aCollection);
819
820
public: /* ----- Cell Map public methods ----- */
821
822
  int32_t GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame);
823
824
  /** returns the number of rows in this table.
825
    */
826
  int32_t GetRowCount () const
827
  {
828
    return GetCellMap()->GetRowCount();
829
  }
830
831
  /** returns the number of columns in this table after redundant columns have been removed
832
    */
833
  int32_t GetEffectiveColCount() const;
834
835
  /* return the col count including dead cols */
836
  int32_t GetColCount () const
837
  {
838
    return GetCellMap()->GetColCount();
839
  }
840
841
  // return the last col index which isn't of type eColAnonymousCell
842
  int32_t GetIndexOfLastRealCol();
843
844
  /** returns true if table-layout:auto  */
845
  bool IsAutoLayout();
846
847
public:
848
849
  /* ---------- Row index management methods ------------ */
850
851
  /** Add the given index to the existing ranges of
852
   *  deleted row indices and merge ranges if, with the addition of the new
853
   *  index, they become consecutive.
854
   *  @param aDeletedRowStoredIndex - index of the row that was deleted
855
   *  Note - 'stored' index here refers to the index that was assigned to
856
   *  the row before any remove row operations were performed i.e. the
857
   *  value of mRowIndex and not the value returned by GetRowIndex()
858
   */
859
  void AddDeletedRowIndex(int32_t aDeletedRowStoredIndex);
860
861
  /** Calculate the change that aStoredIndex must be increased/decreased by
862
   *  to get new index.
863
   *  Note that aStoredIndex is always the index of an undeleted row (since
864
   *  rows that have already been deleted can never call this method).
865
   *  @param aStoredIndex - The stored index value that must be adjusted
866
   *  Note - 'stored' index here refers to the index that was assigned to
867
   *  the row before any remove row operations were performed i.e. the
868
   *  value of mRowIndex and not the value returned by GetRowIndex()
869
   */
870
  int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex);
871
872
  /** Returns whether mDeletedRowIndexRanges is empty
873
   */
874
  bool IsDeletedRowIndexRangesEmpty() const {
875
    return mDeletedRowIndexRanges.empty();
876
  }
877
878
public:
879
880
#ifdef DEBUG
881
  void Dump(bool            aDumpRows,
882
            bool            aDumpCols,
883
            bool            aDumpCellMap);
884
#endif
885
886
protected:
887
  /**
888
   * Helper method for RemoveFrame.
889
   */
890
  void DoRemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
891
#ifdef DEBUG
892
  void DumpRowGroup(nsIFrame* aChildFrame);
893
#endif
894
  // DATA MEMBERS
895
  AutoTArray<nsTableColFrame*, 8> mColFrames;
896
897
  struct TableBits {
898
    uint32_t mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
899
    uint32_t mHasPctCol:1;             // does any cell or col have a pct width
900
    uint32_t mCellSpansPctCol:1;       // does any cell span a col with a pct width (or containing a cell with a pct width)
901
    uint32_t mIsBorderCollapse:1;      // border collapsing model vs. separate model
902
    uint32_t mRowInserted:1;
903
    uint32_t mNeedToCalcBCBorders:1;
904
    uint32_t mGeometryDirty:1;
905
    uint32_t mIStartContBCBorder:8;
906
    uint32_t mNeedToCollapse:1;        // rows, cols that have visibility:collapse need to be collapsed
907
    uint32_t mResizedColumns:1;        // have we resized columns since last reflow?
908
    uint32_t mNeedToCalcHasBCBorders:1;
909
    uint32_t mHasBCBorders:1;
910
  } mBits;
911
912
  std::map<int32_t, int32_t> mDeletedRowIndexRanges; // maintains ranges of row
913
                                                     // indices of deleted rows
914
  nsTableCellMap*         mCellMap;            // maintains the relationships between rows, cols, and cells
915
  nsITableLayoutStrategy* mTableLayoutStrategy;// the layout strategy for this frame
916
  nsFrameList             mColGroups;          // the list of colgroup frames
917
};
918
919
920
inline bool nsTableFrame::IsRowGroup(mozilla::StyleDisplay aDisplayType) const
921
{
922
  return mozilla::StyleDisplay::TableHeaderGroup == aDisplayType ||
923
         mozilla::StyleDisplay::TableFooterGroup == aDisplayType ||
924
         mozilla::StyleDisplay::TableRowGroup    == aDisplayType;
925
}
926
927
inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue)
928
{
929
  mBits.mHaveReflowedColGroups = aValue;
930
}
931
932
inline bool nsTableFrame::HaveReflowedColGroups() const
933
{
934
  return (bool)mBits.mHaveReflowedColGroups;
935
}
936
937
inline bool nsTableFrame::HasPctCol() const
938
0
{
939
0
  return (bool)mBits.mHasPctCol;
940
0
}
941
942
inline void nsTableFrame::SetHasPctCol(bool aValue)
943
0
{
944
0
  mBits.mHasPctCol = (unsigned)aValue;
945
0
}
946
947
inline bool nsTableFrame::HasCellSpanningPctCol() const
948
0
{
949
0
  return (bool)mBits.mCellSpansPctCol;
950
0
}
951
952
inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue)
953
0
{
954
0
  mBits.mCellSpansPctCol = (unsigned)aValue;
955
0
}
956
957
inline bool nsTableFrame::IsRowInserted() const
958
{
959
  return (bool)mBits.mRowInserted;
960
}
961
962
inline void nsTableFrame::SetRowInserted(bool aValue)
963
{
964
  mBits.mRowInserted = (unsigned)aValue;
965
}
966
967
inline void nsTableFrame::SetNeedToCollapse(bool aValue)
968
{
969
  static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse = (unsigned)aValue;
970
}
971
972
inline bool nsTableFrame::NeedToCollapse() const
973
{
974
  return (bool) static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse;
975
}
976
977
inline nsFrameList& nsTableFrame::GetColGroups()
978
{
979
  return static_cast<nsTableFrame*>(FirstInFlow())->mColGroups;
980
}
981
982
inline nsTArray<nsTableColFrame*>& nsTableFrame::GetColCache()
983
0
{
984
0
  return mColFrames;
985
0
}
986
987
inline bool nsTableFrame::IsBorderCollapse() const
988
{
989
  return (bool)mBits.mIsBorderCollapse;
990
}
991
992
inline void nsTableFrame::SetBorderCollapse(bool aValue)
993
{
994
  mBits.mIsBorderCollapse = aValue;
995
}
996
997
inline bool nsTableFrame::NeedToCalcBCBorders() const
998
{
999
  return (bool)mBits.mNeedToCalcBCBorders;
1000
}
1001
1002
inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue)
1003
{
1004
  mBits.mNeedToCalcBCBorders = (unsigned)aValue;
1005
}
1006
1007
inline bool nsTableFrame::NeedToCalcHasBCBorders() const
1008
{
1009
  return (bool)mBits.mNeedToCalcHasBCBorders;
1010
}
1011
1012
inline void nsTableFrame::SetNeedToCalcHasBCBorders(bool aValue)
1013
{
1014
  mBits.mNeedToCalcHasBCBorders = (unsigned)aValue;
1015
}
1016
1017
inline bool nsTableFrame::HasBCBorders()
1018
{
1019
  if (NeedToCalcHasBCBorders()) {
1020
    CalcHasBCBorders();
1021
    SetNeedToCalcHasBCBorders(false);
1022
  }
1023
  return (bool)mBits.mHasBCBorders;
1024
}
1025
1026
inline void nsTableFrame::SetHasBCBorders(bool aValue)
1027
{
1028
  mBits.mHasBCBorders = (unsigned)aValue;
1029
}
1030
1031
inline nscoord
1032
nsTableFrame::GetContinuousIStartBCBorderWidth() const
1033
0
{
1034
0
  int32_t d2a = PresContext()->AppUnitsPerDevPixel();
1035
0
  return BC_BORDER_END_HALF_COORD(d2a, mBits.mIStartContBCBorder);
1036
0
}
1037
1038
inline void nsTableFrame::SetContinuousIStartBCBorderWidth(nscoord aValue)
1039
{
1040
  mBits.mIStartContBCBorder = (unsigned) aValue;
1041
}
1042
1043
#define ABORT0() \
1044
{NS_ASSERTION(false, "CellIterator program error"); \
1045
return;}
1046
1047
#define ABORT1(aReturn) \
1048
{NS_ASSERTION(false, "CellIterator program error"); \
1049
return aReturn;}
1050
1051
#endif