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__
7
8 #include "mozilla/Attributes.h"
9 #include "nscore.h"
10 #include "nsContainerFrame.h"
11 #include "nsTablePainter.h"
12 #include "nsTableRowGroupFrame.h"
13 #include "mozilla/WritingModes.h"
14
15 class nsTableCellFrame;
16 namespace mozilla {
17 struct TableCellReflowInput;
18 } // namespace mozilla
19
20 /**
21 * nsTableRowFrame is the frame that maps table rows
22 * (HTML tag TR). This class cannot be reused
23 * outside of an nsTableRowGroupFrame. It assumes that its parent is an nsTableRowGroupFrame,
24 * and its children are nsTableCellFrames.
25 *
26 * @see nsTableFrame
27 * @see nsTableRowGroupFrame
28 * @see nsTableCellFrame
29 */
30 class nsTableRowFrame : public nsContainerFrame
31 {
32 using TableCellReflowInput = mozilla::TableCellReflowInput;
33
34 public:
35 NS_DECL_QUERYFRAME_TARGET(nsTableRowFrame)
36 NS_DECL_QUERYFRAME
37 NS_DECL_FRAMEARENA_HELPERS
38
39 virtual ~nsTableRowFrame();
40
41 virtual void Init(nsIContent* aContent,
42 nsContainerFrame* aParent,
43 nsIFrame* aPrevInFlow) override;
44
45 virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
46
47 /** @see nsIFrame::DidSetStyleContext */
48 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
49
50 virtual void AppendFrames(ChildListID aListID,
51 nsFrameList& aFrameList) override;
52 virtual void InsertFrames(ChildListID aListID,
53 nsIFrame* aPrevFrame,
54 nsFrameList& aFrameList) override;
55 virtual void RemoveFrame(ChildListID aListID,
56 nsIFrame* aOldFrame) override;
57
58 /** instantiate a new instance of nsTableRowFrame.
59 * @param aPresShell the pres shell for this frame
60 *
61 * @return the frame that was created
62 */
63 friend nsTableRowFrame* NS_NewTableRowFrame(nsIPresShell* aPresShell,
64 nsStyleContext* aContext);
65
GetTableRowGroupFrame()66 nsTableRowGroupFrame* GetTableRowGroupFrame() const
67 {
68 nsIFrame* parent = GetParent();
69 MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableRowGroupFrame);
70 return static_cast<nsTableRowGroupFrame*>(parent);
71 }
72
GetTableFrame()73 nsTableFrame* GetTableFrame() const
74 {
75 return GetTableRowGroupFrame()->GetTableFrame();
76 }
77
78 virtual nsMargin GetUsedMargin() const override;
79 virtual nsMargin GetUsedBorder() const override;
80 virtual nsMargin GetUsedPadding() const override;
81
82 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
83 const nsRect& aDirtyRect,
84 const nsDisplayListSet& aLists) override;
85
86 nsTableCellFrame* GetFirstCell() ;
87
88 /** calls Reflow for all of its child cells.
89 * Cells with rowspan=1 are all set to the same height and stacked horizontally.
90 * <P> Cells are not split unless absolutely necessary.
91 * <P> Cells are resized in nsTableFrame::BalanceColumnWidths
92 * and nsTableFrame::ShrinkWrapChildren
93 *
94 * @param aDesiredSize width set to width of the sum of the cells, height set to
95 * height of cells with rowspan=1.
96 *
97 * @see nsIFrame::Reflow
98 * @see nsTableFrame::BalanceColumnWidths
99 * @see nsTableFrame::ShrinkWrapChildren
100 */
101 virtual void Reflow(nsPresContext* aPresContext,
102 ReflowOutput& aDesiredSize,
103 const ReflowInput& aReflowInput,
104 nsReflowStatus& aStatus) override;
105
106 void DidResize();
107
108 /**
109 * Get the "type" of the frame
110 *
111 * @see nsGkAtoms::tableRowFrame
112 */
113 virtual nsIAtom* GetType() const override;
114
115 #ifdef DEBUG_FRAME_DUMP
116 virtual nsresult GetFrameName(nsAString& aResult) const override;
117 #endif
118
GetWritingMode()119 virtual mozilla::WritingMode GetWritingMode() const override
120 { return GetTableFrame()->GetWritingMode(); }
121
122 void UpdateBSize(nscoord aBSize,
123 nscoord aAscent,
124 nscoord aDescent,
125 nsTableFrame* aTableFrame = nullptr,
126 nsTableCellFrame* aCellFrame = nullptr);
127
128 void ResetBSize(nscoord aRowStyleBSize);
129
130 // calculate the bsize, considering content bsize of the
131 // cells and the style bsize of the row and cells, excluding pct bsizes
132 nscoord CalcBSize(const ReflowInput& aReflowInput);
133
134 // Support for cells with 'vertical-align: baseline'.
135
136 /**
137 * returns the max-ascent amongst all the cells that have
138 * 'vertical-align: baseline', *including* cells with rowspans.
139 * returns 0 if we don't have any cell with 'vertical-align: baseline'
140 */
141 nscoord GetMaxCellAscent() const;
142
143 /* return the row ascent
144 */
145 nscoord GetRowBaseline(mozilla::WritingMode aWritingMode);
146
147 /** returns the ordinal position of this row in its table */
148 virtual int32_t GetRowIndex() const;
149
150 /** set this row's starting row index */
151 void SetRowIndex (int aRowIndex);
152
153 /** used by row group frame code */
154 nscoord ReflowCellFrame(nsPresContext* aPresContext,
155 const ReflowInput& aReflowInput,
156 bool aIsTopOfPage,
157 nsTableCellFrame* aCellFrame,
158 nscoord aAvailableBSize,
159 nsReflowStatus& aStatus);
160 /**
161 * Collapse the row if required, apply col and colgroup visibility: collapse
162 * info to the cells in the row.
163 * @return the amount to shift bstart-wards all following rows
164 * @param aRowOffset - shift the row bstart-wards by this amount
165 * @param aISize - new isize of the row
166 * @param aCollapseGroup - parent rowgroup is collapsed so this row needs
167 * to be collapsed
168 * @param aDidCollapse - the row has been collapsed
169 */
170 nscoord CollapseRowIfNecessary(nscoord aRowOffset,
171 nscoord aISize,
172 bool aCollapseGroup,
173 bool& aDidCollapse);
174
175 /**
176 * Insert a cell frame after the last cell frame that has a col index
177 * that is less than aColIndex. If no such cell frame is found the
178 * frame to insert is prepended to the child list.
179 * @param aFrame the cell frame to insert
180 * @param aColIndex the col index
181 */
182 void InsertCellFrame(nsTableCellFrame* aFrame,
183 int32_t aColIndex);
184
185 nsresult CalculateCellActualBSize(nsTableCellFrame* aCellFrame,
186 nscoord& aDesiredBSize,
187 mozilla::WritingMode aWM);
188
189 bool IsFirstInserted() const;
190 void SetFirstInserted(bool aValue);
191
192 nscoord GetContentBSize() const;
193 void SetContentBSize(nscoord aTwipValue);
194
195 bool HasStyleBSize() const;
196
197 bool HasFixedBSize() const;
198 void SetHasFixedBSize(bool aValue);
199
200 bool HasPctBSize() const;
201 void SetHasPctBSize(bool aValue);
202
203 nscoord GetFixedBSize() const;
204 void SetFixedBSize(nscoord aValue);
205
206 float GetPctBSize() const;
207 void SetPctBSize(float aPctValue,
208 bool aForce = false);
209
210 nscoord GetInitialBSize(nscoord aBasis = 0) const;
211
212 nsTableRowFrame* GetNextRow() const;
213
214 bool HasUnpaginatedBSize();
215 void SetHasUnpaginatedBSize(bool aValue);
216 nscoord GetUnpaginatedBSize();
217 void SetUnpaginatedBSize(nsPresContext* aPresContext, nscoord aValue);
218
GetBStartBCBorderWidth()219 nscoord GetBStartBCBorderWidth() const { return mBStartBorderWidth; }
GetBEndBCBorderWidth()220 nscoord GetBEndBCBorderWidth() const { return mBEndBorderWidth; }
SetBStartBCBorderWidth(BCPixelSize aWidth)221 void SetBStartBCBorderWidth(BCPixelSize aWidth) { mBStartBorderWidth = aWidth; }
SetBEndBCBorderWidth(BCPixelSize aWidth)222 void SetBEndBCBorderWidth(BCPixelSize aWidth) { mBEndBorderWidth = aWidth; }
223 mozilla::LogicalMargin GetBCBorderWidth(mozilla::WritingMode aWM);
224
225 /**
226 * Gets inner border widths before collapsing with cell borders
227 * Caller must get block-end border from next row or from table
228 * GetContinuousBCBorderWidth will not overwrite that border
229 * see nsTablePainter about continuous borders
230 */
231 void GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
232 mozilla::LogicalMargin& aBorder);
233
234 /**
235 * @returns outer block-start bc border == prev row's block-end inner
236 */
237 nscoord GetOuterBStartContBCBorderWidth();
238 /**
239 * Sets full border widths before collapsing with cell borders
240 * @param aForSide - side to set; only accepts iend, istart, and bstart
241 */
242 void SetContinuousBCBorderWidth(mozilla::LogicalSide aForSide,
243 BCPixelSize aPixelValue);
244
IsFrameOfType(uint32_t aFlags)245 virtual bool IsFrameOfType(uint32_t aFlags) const override
246 {
247 return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
248 }
249
250 virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
251 virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
InvalidateFrameForRemoval()252 virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
253
254 #ifdef ACCESSIBILITY
255 virtual mozilla::a11y::AccType AccessibleType() override;
256 #endif
257
258 protected:
259
260 /** protected constructor.
261 * @see NewFrame
262 */
263 explicit nsTableRowFrame(nsStyleContext *aContext);
264
265 void InitChildReflowInput(nsPresContext& aPresContext,
266 const mozilla::LogicalSize& aAvailSize,
267 bool aBorderCollapse,
268 TableCellReflowInput& aReflowInput);
269
270 virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
271
272 // row-specific methods
273
274 nscoord ComputeCellXOffset(const ReflowInput& aState,
275 nsIFrame* aKidFrame,
276 const nsMargin& aKidMargin) const;
277 /**
278 * Called for incremental/dirty and resize reflows. If aDirtyOnly is true then
279 * only reflow dirty cells.
280 */
281 void ReflowChildren(nsPresContext* aPresContext,
282 ReflowOutput& aDesiredSize,
283 const ReflowInput& aReflowInput,
284 nsTableFrame& aTableFrame,
285 nsReflowStatus& aStatus);
286
287 private:
288 struct RowBits {
289 unsigned mRowIndex:29;
290 unsigned mHasFixedBSize:1; // set if the dominating style bsize on the row or any cell is pixel based
291 unsigned mHasPctBSize:1; // set if the dominating style bsize on the row or any cell is pct based
292 unsigned mFirstInserted:1; // if true, then it was the bstart-most newly inserted row
293 } mBits;
294
295 // the desired bsize based on the content of the tallest cell in the row
296 nscoord mContentBSize;
297 // the bsize based on a style percentage bsize on either the row or any cell
298 // if mHasPctBSize is set
299 nscoord mStylePctBSize;
300 // the bsize based on a style pixel bsize on the row or any
301 // cell if mHasFixedBSize is set
302 nscoord mStyleFixedBSize;
303
304 // max-ascent and max-descent amongst all cells that have 'vertical-align: baseline'
305 nscoord mMaxCellAscent; // does include cells with rowspan > 1
306 nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1
307
308 // border widths in pixels in the collapsing border model of the *inner*
309 // half of the border only
310 BCPixelSize mBStartBorderWidth;
311 BCPixelSize mBEndBorderWidth;
312 BCPixelSize mIEndContBorderWidth;
313 BCPixelSize mBStartContBorderWidth;
314 BCPixelSize mIStartContBorderWidth;
315
316 /**
317 * Sets the NS_ROW_HAS_CELL_WITH_STYLE_BSIZE bit to indicate whether
318 * this row has any cells that have non-auto-bsize. (Row-spanning
319 * cells are ignored.)
320 */
321 void InitHasCellWithStyleBSize(nsTableFrame* aTableFrame);
322
323 };
324
GetRowIndex()325 inline int32_t nsTableRowFrame::GetRowIndex() const
326 {
327 return int32_t(mBits.mRowIndex);
328 }
329
SetRowIndex(int aRowIndex)330 inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
331 {
332 mBits.mRowIndex = aRowIndex;
333 }
334
IsFirstInserted()335 inline bool nsTableRowFrame::IsFirstInserted() const
336 {
337 return bool(mBits.mFirstInserted);
338 }
339
SetFirstInserted(bool aValue)340 inline void nsTableRowFrame::SetFirstInserted(bool aValue)
341 {
342 mBits.mFirstInserted = aValue;
343 }
344
HasStyleBSize()345 inline bool nsTableRowFrame::HasStyleBSize() const
346 {
347 return (bool)mBits.mHasFixedBSize || (bool)mBits.mHasPctBSize;
348 }
349
HasFixedBSize()350 inline bool nsTableRowFrame::HasFixedBSize() const
351 {
352 return (bool)mBits.mHasFixedBSize;
353 }
354
SetHasFixedBSize(bool aValue)355 inline void nsTableRowFrame::SetHasFixedBSize(bool aValue)
356 {
357 mBits.mHasFixedBSize = aValue;
358 }
359
HasPctBSize()360 inline bool nsTableRowFrame::HasPctBSize() const
361 {
362 return (bool)mBits.mHasPctBSize;
363 }
364
SetHasPctBSize(bool aValue)365 inline void nsTableRowFrame::SetHasPctBSize(bool aValue)
366 {
367 mBits.mHasPctBSize = aValue;
368 }
369
GetContentBSize()370 inline nscoord nsTableRowFrame::GetContentBSize() const
371 {
372 return mContentBSize;
373 }
374
SetContentBSize(nscoord aValue)375 inline void nsTableRowFrame::SetContentBSize(nscoord aValue)
376 {
377 mContentBSize = aValue;
378 }
379
GetFixedBSize()380 inline nscoord nsTableRowFrame::GetFixedBSize() const
381 {
382 if (mBits.mHasFixedBSize) {
383 return mStyleFixedBSize;
384 }
385 return 0;
386 }
387
GetPctBSize()388 inline float nsTableRowFrame::GetPctBSize() const
389 {
390 if (mBits.mHasPctBSize) {
391 return (float)mStylePctBSize / 100.0f;
392 }
393 return 0.0f;
394 }
395
HasUnpaginatedBSize()396 inline bool nsTableRowFrame::HasUnpaginatedBSize()
397 {
398 return HasAnyStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE);
399 }
400
SetHasUnpaginatedBSize(bool aValue)401 inline void nsTableRowFrame::SetHasUnpaginatedBSize(bool aValue)
402 {
403 if (aValue) {
404 AddStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE);
405 } else {
406 RemoveStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE);
407 }
408 }
409
410 inline mozilla::LogicalMargin
GetBCBorderWidth(mozilla::WritingMode aWM)411 nsTableRowFrame::GetBCBorderWidth(mozilla::WritingMode aWM)
412 {
413 return mozilla::LogicalMargin(
414 aWM, nsPresContext::CSSPixelsToAppUnits(mBStartBorderWidth), 0,
415 nsPresContext::CSSPixelsToAppUnits(mBEndBorderWidth), 0);
416 }
417
418 inline void
GetContinuousBCBorderWidth(mozilla::WritingMode aWM,mozilla::LogicalMargin & aBorder)419 nsTableRowFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
420 mozilla::LogicalMargin& aBorder)
421 {
422 int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
423 aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips,
424 mIStartContBorderWidth);
425 aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips,
426 mBStartContBorderWidth);
427 aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips,
428 mIEndContBorderWidth);
429 }
430
GetOuterBStartContBCBorderWidth()431 inline nscoord nsTableRowFrame::GetOuterBStartContBCBorderWidth()
432 {
433 int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
434 return BC_BORDER_START_HALF_COORD(aPixelsToTwips, mBStartContBorderWidth);
435 }
436
437 #endif
438