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 nsTableRowFrame_h__
6 #define nsTableRowFrame_h__
8 #include "mozilla/Attributes.h"
10 #include "nsContainerFrame.h"
11 #include "nsTableRowGroupFrame.h"
12 #include "mozilla/WritingModes.h"
14 class nsTableCellFrame
;
17 struct TableCellReflowInput
;
19 // Yes if table-cells should use 'vertical-align:top' in
20 // nsTableCellFrame::BlockDirAlignChild(). This is a hack to workaround our
21 // current table row group fragmentation to avoid data loss.
22 enum class ForceAlignTopForTableCell
: uint8_t { No
, Yes
};
23 } // namespace mozilla
26 * nsTableRowFrame is the frame that maps table rows
27 * (HTML tag TR). This class cannot be reused
28 * outside of an nsTableRowGroupFrame. It assumes that its parent is an
29 * nsTableRowGroupFrame, and its children are nsTableCellFrames.
32 * @see nsTableRowGroupFrame
33 * @see nsTableCellFrame
35 class nsTableRowFrame
: public nsContainerFrame
{
36 using TableCellReflowInput
= mozilla::TableCellReflowInput
;
40 NS_DECL_FRAMEARENA_HELPERS(nsTableRowFrame
)
42 virtual ~nsTableRowFrame();
44 void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
45 nsIFrame
* aPrevInFlow
) override
;
47 void Destroy(DestroyContext
&) override
;
49 void DidSetComputedStyle(ComputedStyle
* aOldComputedStyle
) override
;
51 void AppendFrames(ChildListID aListID
, nsFrameList
&& aFrameList
) override
;
52 void InsertFrames(ChildListID aListID
, nsIFrame
* aPrevFrame
,
53 const nsLineList::iterator
* aPrevFrameLine
,
54 nsFrameList
&& aFrameList
) override
;
55 void RemoveFrame(DestroyContext
&, ChildListID
, nsIFrame
*) override
;
57 /** instantiate a new instance of nsTableRowFrame.
58 * @param aPresShell the pres shell for this frame
60 * @return the frame that was created
62 friend nsTableRowFrame
* NS_NewTableRowFrame(mozilla::PresShell
* aPresShell
,
63 ComputedStyle
* aStyle
);
65 nsTableRowGroupFrame
* GetTableRowGroupFrame() const {
66 nsIFrame
* parent
= GetParent();
67 MOZ_ASSERT(parent
&& parent
->IsTableRowGroupFrame());
68 return static_cast<nsTableRowGroupFrame
*>(parent
);
71 nsTableFrame
* GetTableFrame() const {
72 return GetTableRowGroupFrame()->GetTableFrame();
75 nsMargin
GetUsedMargin() const override
;
76 nsMargin
GetUsedBorder() const override
;
77 nsMargin
GetUsedPadding() const override
;
79 void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
80 const nsDisplayListSet
& aLists
) override
;
82 void PaintCellBackgroundsForFrame(nsIFrame
* aFrame
,
83 nsDisplayListBuilder
* aBuilder
,
84 const nsDisplayListSet
& aLists
,
85 const nsPoint
& aOffset
= nsPoint());
87 // Implemented in nsTableCellFrame.h, because it needs to know about the
88 // nsTableCellFrame class, but we can't include nsTableCellFrame.h here.
89 inline nsTableCellFrame
* GetFirstCell() const;
91 /** calls Reflow for all of its child cells.
93 * Cells with rowspan=1 are all set to the same height and stacked
96 * Cells are not split unless absolutely necessary.
98 * Cells are resized in nsTableFrame::BalanceColumnWidths and
99 * nsTableFrame::ShrinkWrapChildren
101 * @param aDesiredSize width set to width of the sum of the cells,
102 * height set to height of cells with rowspan=1.
104 * @see nsIFrame::Reflow
105 * @see nsTableFrame::BalanceColumnWidths
106 * @see nsTableFrame::ShrinkWrapChildren
108 void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
109 const ReflowInput
& aReflowInput
,
110 nsReflowStatus
& aStatus
) override
;
112 void DidResize(mozilla::ForceAlignTopForTableCell aForceAlignTop
=
113 mozilla::ForceAlignTopForTableCell::No
);
115 #ifdef DEBUG_FRAME_DUMP
116 nsresult
GetFrameName(nsAString
& aResult
) const override
;
119 void UpdateBSize(nscoord aBSize
, nscoord aAscent
, nscoord aDescent
,
120 nsTableFrame
* aTableFrame
= nullptr,
121 nsTableCellFrame
* aCellFrame
= nullptr);
125 // calculate the bsize, considering content bsize of the
126 // cells and the style bsize of the row and cells, excluding pct bsizes
127 nscoord
CalcBSize(const ReflowInput
& aReflowInput
);
129 // Support for cells with 'vertical-align: baseline'.
132 * returns the max-ascent amongst all the cells that have
133 * 'vertical-align: baseline', *including* cells with rowspans.
134 * returns 0 if we don't have any cell with 'vertical-align: baseline'
136 nscoord
GetMaxCellAscent() const;
138 /* return the row ascent
140 Maybe
<nscoord
> GetRowBaseline(mozilla::WritingMode aWM
);
142 /** returns the ordinal position of this row in its table */
143 virtual int32_t GetRowIndex() const;
145 /** set this row's starting row index */
146 void SetRowIndex(int aRowIndex
);
148 // See nsTableFrame.h
149 int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex
) const;
151 // See nsTableFrame.h
152 void AddDeletedRowIndex();
155 * This function is called by the row group frame's SplitRowGroup() code when
156 * pushing a row frame that has cell frames that span into it. The cell frame
157 * should be reflowed with the specified available block-size.
159 nscoord
ReflowCellFrame(nsPresContext
* aPresContext
,
160 const ReflowInput
& aReflowInput
, bool aIsTopOfPage
,
161 nsTableCellFrame
* aCellFrame
, nscoord aAvailableBSize
,
162 nsReflowStatus
& aStatus
);
164 * Collapse the row if required, apply col and colgroup visibility: collapse
165 * info to the cells in the row.
166 * @return the amount to shift bstart-wards all following rows
167 * @param aRowOffset - shift the row bstart-wards by this amount
168 * @param aISize - new isize of the row
169 * @param aCollapseGroup - parent rowgroup is collapsed so this row needs
171 * @param aDidCollapse - the row has been collapsed
173 nscoord
CollapseRowIfNecessary(nscoord aRowOffset
, nscoord aISize
,
174 bool aCollapseGroup
, bool& aDidCollapse
);
177 * Insert a cell frame after the last cell frame that has a col index
178 * that is less than aColIndex. If no such cell frame is found the
179 * frame to insert is prepended to the child list.
180 * @param aFrame the cell frame to insert
181 * @param aColIndex the col index
183 void InsertCellFrame(nsTableCellFrame
* aFrame
, int32_t aColIndex
);
186 * Calculate the cell frame's actual block-size given its desired block-size
187 * (the border-box block-size in the last reflow). This method takes into
188 * account the specified bsize (in the style).
190 * @return the specified block-size if it is larger than the desired
191 * block-size. Otherwise, the desired block-size.
193 nscoord
CalcCellActualBSize(nsTableCellFrame
* aCellFrame
,
194 const nscoord
& aDesiredBSize
,
195 mozilla::WritingMode aWM
);
197 bool IsFirstInserted() const;
198 void SetFirstInserted(bool aValue
);
200 nscoord
GetContentBSize() const;
201 void SetContentBSize(nscoord aTwipValue
);
203 bool HasStyleBSize() const;
205 bool HasFixedBSize() const;
206 void SetHasFixedBSize(bool aValue
);
208 bool HasPctBSize() const;
209 void SetHasPctBSize(bool aValue
);
211 nscoord
GetFixedBSize() const;
212 void SetFixedBSize(nscoord aValue
);
214 float GetPctBSize() const;
215 void SetPctBSize(float aPctValue
, bool aForce
= false);
217 nscoord
GetInitialBSize(nscoord aBasis
= 0) const;
219 nsTableRowFrame
* GetPrevRow() const;
220 nsTableRowFrame
* GetNextRow() const;
222 bool HasUnpaginatedBSize() const {
223 return HasAnyStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE
);
225 nscoord
GetUnpaginatedBSize() const;
226 void SetUnpaginatedBSize(nscoord aValue
);
228 nscoord
GetBStartBCBorderWidth() const { return mBStartBorderWidth
; }
229 nscoord
GetBEndBCBorderWidth() const { return mBEndBorderWidth
; }
230 void SetBStartBCBorderWidth(nscoord aWidth
) { mBStartBorderWidth
= aWidth
; }
231 void SetBEndBCBorderWidth(nscoord aWidth
) { mBEndBorderWidth
= aWidth
; }
232 mozilla::LogicalMargin
GetBCBorderWidth(mozilla::WritingMode aWM
);
234 void InvalidateFrame(uint32_t aDisplayItemKey
= 0,
235 bool aRebuildDisplayItems
= true) override
;
236 void InvalidateFrameWithRect(const nsRect
& aRect
,
237 uint32_t aDisplayItemKey
= 0,
238 bool aRebuildDisplayItems
= true) override
;
239 void InvalidateFrameForRemoval() override
{ InvalidateFrameSubtree(); }
242 mozilla::a11y::AccType
AccessibleType() override
;
246 /** protected constructor.
249 explicit nsTableRowFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
,
250 ClassID aID
= kClassID
);
252 void InitChildReflowInput(nsPresContext
& aPresContext
,
253 const mozilla::LogicalSize
& aAvailSize
,
254 bool aBorderCollapse
,
255 TableCellReflowInput
& aReflowInput
);
257 LogicalSides
GetLogicalSkipSides() const override
;
259 // row-specific methods
261 nscoord
ComputeCellXOffset(const ReflowInput
& aState
, nsIFrame
* aKidFrame
,
262 const nsMargin
& aKidMargin
) const;
264 * Called for incremental/dirty and resize reflows. If aDirtyOnly is true then
265 * only reflow dirty cells.
267 void ReflowChildren(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
268 const ReflowInput
& aReflowInput
,
269 nsTableFrame
& aTableFrame
, nsReflowStatus
& aStatus
);
273 unsigned mRowIndex
: 29;
274 unsigned mHasFixedBSize
: 1; // set if the dominating style bsize on the
275 // row or any cell is pixel based
276 unsigned mHasPctBSize
: 1; // set if the dominating style bsize on the row
277 // or any cell is pct based
278 unsigned mFirstInserted
: 1; // if true, then it was the bstart-most newly
282 // the desired bsize based on the content of the tallest cell in the row
283 nscoord mContentBSize
= 0;
284 // the bsize based on a style percentage bsize on either the row or any cell
285 // if mHasPctBSize is set
286 nscoord mStylePctBSize
= 0;
287 // the bsize based on a style pixel bsize on the row or any
288 // cell if mHasFixedBSize is set
289 nscoord mStyleFixedBSize
= 0;
291 // max-ascent and max-descent amongst all cells that have
292 // 'vertical-align: baseline'
293 nscoord mMaxCellAscent
= 0; // does include cells with rowspan > 1
294 nscoord mMaxCellDescent
= 0; // does *not* include cells with rowspan > 1
296 // border widths in the collapsing border model of the *inner*
297 // half of the border only
298 nscoord mBStartBorderWidth
= 0;
299 nscoord mBEndBorderWidth
= 0;
300 nscoord mIEndContBorderWidth
= 0;
301 nscoord mBStartContBorderWidth
= 0;
302 nscoord mIStartContBorderWidth
= 0;
305 * Sets the NS_ROW_HAS_CELL_WITH_STYLE_BSIZE bit to indicate whether
306 * this row has any cells that have non-auto-bsize. (Row-spanning
307 * cells are ignored.)
309 void InitHasCellWithStyleBSize(nsTableFrame
* aTableFrame
);
312 inline int32_t nsTableRowFrame::GetAdjustmentForStoredIndex(
313 int32_t aStoredIndex
) const {
314 nsTableRowGroupFrame
* parentFrame
= GetTableRowGroupFrame();
315 return parentFrame
->GetAdjustmentForStoredIndex(aStoredIndex
);
318 inline void nsTableRowFrame::AddDeletedRowIndex() {
319 nsTableRowGroupFrame
* parentFrame
= GetTableRowGroupFrame();
320 parentFrame
->AddDeletedRowIndex(int32_t(mBits
.mRowIndex
));
323 inline int32_t nsTableRowFrame::GetRowIndex() const {
324 int32_t storedRowIndex
= int32_t(mBits
.mRowIndex
);
325 int32_t rowIndexAdjustment
= GetAdjustmentForStoredIndex(storedRowIndex
);
326 return (storedRowIndex
- rowIndexAdjustment
);
329 inline void nsTableRowFrame::SetRowIndex(int aRowIndex
) {
330 // Note: Setting the index of a row (as in the case of adding new rows) should
331 // be preceded by a call to nsTableFrame::RecalculateRowIndices()
332 // so as to correctly clear mDeletedRowIndexRanges.
334 GetTableRowGroupFrame()->GetTableFrame()->IsDeletedRowIndexRangesEmpty(),
335 "mDeletedRowIndexRanges should be empty here!");
336 mBits
.mRowIndex
= aRowIndex
;
339 inline bool nsTableRowFrame::IsFirstInserted() const {
340 return bool(mBits
.mFirstInserted
);
343 inline void nsTableRowFrame::SetFirstInserted(bool aValue
) {
344 mBits
.mFirstInserted
= aValue
;
347 inline bool nsTableRowFrame::HasStyleBSize() const {
348 return (bool)mBits
.mHasFixedBSize
|| (bool)mBits
.mHasPctBSize
;
351 inline bool nsTableRowFrame::HasFixedBSize() const {
352 return (bool)mBits
.mHasFixedBSize
;
355 inline void nsTableRowFrame::SetHasFixedBSize(bool aValue
) {
356 mBits
.mHasFixedBSize
= aValue
;
359 inline bool nsTableRowFrame::HasPctBSize() const {
360 return (bool)mBits
.mHasPctBSize
;
363 inline void nsTableRowFrame::SetHasPctBSize(bool aValue
) {
364 mBits
.mHasPctBSize
= aValue
;
367 inline nscoord
nsTableRowFrame::GetContentBSize() const {
368 return mContentBSize
;
371 inline void nsTableRowFrame::SetContentBSize(nscoord aValue
) {
372 mContentBSize
= aValue
;
375 inline nscoord
nsTableRowFrame::GetFixedBSize() const {
376 if (mBits
.mHasFixedBSize
) {
377 return mStyleFixedBSize
;
382 inline float nsTableRowFrame::GetPctBSize() const {
383 if (mBits
.mHasPctBSize
) {
384 return (float)mStylePctBSize
/ 100.0f
;
389 inline mozilla::LogicalMargin
nsTableRowFrame::GetBCBorderWidth(
390 mozilla::WritingMode aWM
) {
391 return mozilla::LogicalMargin(aWM
, mBStartBorderWidth
, 0, mBEndBorderWidth
,