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