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