nsTableRowGroupFrame.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 nsTableRowGroupFrame_h__
  6. #define nsTableRowGroupFrame_h__
  7. #include "mozilla/Attributes.h"
  8. #include "nscore.h"
  9. #include "nsContainerFrame.h"
  10. #include "nsIAtom.h"
  11. #include "nsILineIterator.h"
  12. #include "nsTArray.h"
  13. #include "nsTableFrame.h"
  14. #include "mozilla/WritingModes.h"
  15. class nsTableRowFrame;
  16. namespace mozilla {
  17. struct TableRowGroupReflowInput;
  18. } // namespace mozilla
  19. #define MIN_ROWS_NEEDING_CURSOR 20
  20. /**
  21. * nsTableRowGroupFrame is the frame that maps row groups
  22. * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
  23. * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame, and
  24. * its children are nsTableRowFrames.
  25. *
  26. * @see nsTableFrame
  27. * @see nsTableRowFrame
  28. */
  29. class nsTableRowGroupFrame final
  30. : public nsContainerFrame
  31. , public nsILineIterator
  32. {
  33. using TableRowGroupReflowInput = mozilla::TableRowGroupReflowInput;
  34. public:
  35. NS_DECL_QUERYFRAME_TARGET(nsTableRowGroupFrame)
  36. NS_DECL_QUERYFRAME
  37. NS_DECL_FRAMEARENA_HELPERS
  38. /** instantiate a new instance of nsTableRowFrame.
  39. * @param aPresShell the pres shell for this frame
  40. *
  41. * @return the frame that was created
  42. */
  43. friend nsTableRowGroupFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell,
  44. nsStyleContext* aContext);
  45. virtual ~nsTableRowGroupFrame();
  46. nsTableFrame* GetTableFrame() const
  47. {
  48. nsIFrame* parent = GetParent();
  49. MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableFrame);
  50. return static_cast<nsTableFrame*>(parent);
  51. }
  52. virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
  53. /** @see nsIFrame::DidSetStyleContext */
  54. virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
  55. virtual void AppendFrames(ChildListID aListID,
  56. nsFrameList& aFrameList) override;
  57. virtual void InsertFrames(ChildListID aListID,
  58. nsIFrame* aPrevFrame,
  59. nsFrameList& aFrameList) override;
  60. virtual void RemoveFrame(ChildListID aListID,
  61. nsIFrame* aOldFrame) override;
  62. virtual nsMargin GetUsedMargin() const override;
  63. virtual nsMargin GetUsedBorder() const override;
  64. virtual nsMargin GetUsedPadding() const override;
  65. virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
  66. const nsDisplayListSet& aLists) override;
  67. /** calls Reflow for all of its child rows.
  68. * Rows are all set to the same isize and stacked in the block direction.
  69. * <P> rows are not split unless absolutely necessary.
  70. *
  71. * @param aDesiredSize isize set to isize of rows, bsize set to
  72. * sum of bsize of rows that fit in AvailableBSize.
  73. *
  74. * @see nsIFrame::Reflow
  75. */
  76. virtual void Reflow(nsPresContext* aPresContext,
  77. ReflowOutput& aDesiredSize,
  78. const ReflowInput& aReflowInput,
  79. nsReflowStatus& aStatus) override;
  80. virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
  81. /**
  82. * Get the "type" of the frame
  83. *
  84. * @see nsGkAtoms::tableRowGroupFrame
  85. */
  86. virtual nsIAtom* GetType() const override;
  87. nsTableRowFrame* GetFirstRow();
  88. nsTableRowFrame* GetLastRow();
  89. #ifdef DEBUG_FRAME_DUMP
  90. virtual nsresult GetFrameName(nsAString& aResult) const override;
  91. #endif
  92. virtual mozilla::WritingMode GetWritingMode() const override
  93. { return GetTableFrame()->GetWritingMode(); }
  94. /** return the number of child rows (not necessarily == number of child frames) */
  95. int32_t GetRowCount();
  96. /** return the table-relative row index of the first row in this rowgroup.
  97. * if there are no rows, -1 is returned.
  98. */
  99. int32_t GetStartRowIndex();
  100. /** Adjust the row indices of all rows whose index is >= aRowIndex.
  101. * @param aRowIndex - start adjusting with this index
  102. * @param aAdjustment - shift the row index by this amount
  103. */
  104. void AdjustRowIndices(int32_t aRowIndex,
  105. int32_t anAdjustment);
  106. /**
  107. * Used for header and footer row group frames that are repeated when
  108. * splitting a table frame.
  109. *
  110. * Performs any table specific initialization
  111. *
  112. * @param aHeaderFooterFrame the original header or footer row group frame
  113. * that was repeated
  114. */
  115. nsresult InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame);
  116. /**
  117. * Get the total bsize of all the row rects
  118. */
  119. nscoord GetBSizeBasis(const ReflowInput& aReflowInput);
  120. mozilla::LogicalMargin GetBCBorderWidth(mozilla::WritingMode aWM);
  121. /**
  122. * Gets inner border widths before collapsing with cell borders
  123. * Caller must get bstart border from previous row group or from table
  124. * GetContinuousBCBorderWidth will not overwrite aBorder.BStart()
  125. * see nsTablePainter about continuous borders
  126. */
  127. void GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
  128. mozilla::LogicalMargin& aBorder);
  129. /**
  130. * Sets full border widths before collapsing with cell borders
  131. * @param aForSide - side to set; only IEnd, IStart, BEnd are valid
  132. */
  133. void SetContinuousBCBorderWidth(mozilla::LogicalSide aForSide,
  134. BCPixelSize aPixelValue);
  135. /**
  136. * Adjust to the effect of visibility:collapse on the row group and
  137. * its children
  138. * @return additional shift bstart-wards that should be applied
  139. * to subsequent rowgroups due to rows and this
  140. * rowgroup being collapsed
  141. * @param aBTotalOffset the total amount that the rowgroup is shifted
  142. * @param aISize new isize of the rowgroup
  143. * @param aWM the table's writing mode
  144. */
  145. nscoord CollapseRowGroupIfNecessary(nscoord aBTotalOffset,
  146. nscoord aISize,
  147. mozilla::WritingMode aWM);
  148. // nsILineIterator methods
  149. public:
  150. virtual void DisposeLineIterator() override { }
  151. // The table row is the equivalent to a line in block layout.
  152. // The nsILineIterator assumes that a line resides in a block, this role is
  153. // fullfilled by the row group. Rows in table are counted relative to the
  154. // table. The row index of row corresponds to the cellmap coordinates. The
  155. // line index with respect to a row group can be computed by substracting the
  156. // row index of the first row in the row group.
  157. /** Get the number of rows in a row group
  158. * @return the number of lines in a row group
  159. */
  160. virtual int32_t GetNumLines() override;
  161. /** @see nsILineIterator.h GetDirection
  162. * @return true if the table is rtl
  163. */
  164. virtual bool GetDirection() override;
  165. /** Return structural information about a line.
  166. * @param aLineNumber - the index of the row relative to the row group
  167. * If the line-number is invalid then
  168. * aFirstFrameOnLine will be nullptr and
  169. * aNumFramesOnLine will be zero.
  170. * @param aFirstFrameOnLine - the first cell frame that originates in row
  171. * with a rowindex that matches a line number
  172. * @param aNumFramesOnLine - return the numbers of cells originating in
  173. * this row
  174. * @param aLineBounds - rect of the row
  175. */
  176. NS_IMETHOD GetLine(int32_t aLineNumber,
  177. nsIFrame** aFirstFrameOnLine,
  178. int32_t* aNumFramesOnLine,
  179. nsRect& aLineBounds) override;
  180. /** Given a frame that's a child of the rowgroup, find which line its on.
  181. * @param aFrame - frame, should be a row
  182. * @param aStartLine - minimal index to return
  183. * @return row index relative to the row group if this a row
  184. * frame and the index is at least aStartLine.
  185. * -1 if the frame cannot be found.
  186. */
  187. virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) override;
  188. /** Find the orginating cell frame on a row that is the nearest to the
  189. * inline-dir coordinate of aPos.
  190. * @param aLineNumber - the index of the row relative to the row group
  191. * @param aPos - coordinate in twips relative to the
  192. * origin of the row group
  193. * @param aFrameFound - pointer to the cellframe
  194. * @param aPosIsBeforeFirstFrame - the point is before the first originating
  195. * cellframe
  196. * @param aPosIsAfterLastFrame - the point is after the last originating
  197. * cellframe
  198. */
  199. NS_IMETHOD FindFrameAt(int32_t aLineNumber,
  200. nsPoint aPos,
  201. nsIFrame** aFrameFound,
  202. bool* aPosIsBeforeFirstFrame,
  203. bool* aPosIsAfterLastFrame) override;
  204. /** Check whether visual and logical order of cell frames within a line are
  205. * identical. As the layout will reorder them this is always the case
  206. * @param aLine - the index of the row relative to the table
  207. * @param aIsReordered - returns false
  208. * @param aFirstVisual - if the table is rtl first originating cell frame
  209. * @param aLastVisual - if the table is rtl last originating cell frame
  210. */
  211. NS_IMETHOD CheckLineOrder(int32_t aLine,
  212. bool *aIsReordered,
  213. nsIFrame **aFirstVisual,
  214. nsIFrame **aLastVisual) override;
  215. /** Find the next originating cell frame that originates in the row.
  216. * @param aFrame - cell frame to start with, will return the next cell
  217. * originating in a row
  218. * @param aLineNumber - the index of the row relative to the table
  219. */
  220. NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) override;
  221. // row cursor methods to speed up searching for the row(s)
  222. // containing a point. The basic idea is that we set the cursor
  223. // property if the rows' y and yMosts are non-decreasing (considering only
  224. // rows with nonempty overflowAreas --- empty overflowAreas never participate
  225. // in event handling or painting), and the rowgroup has sufficient number of
  226. // rows. The cursor property points to a "recently used" row. If we get a
  227. // series of requests that work on rows "near" the cursor, then we can find
  228. // those nearby rows quickly by starting our search at the cursor.
  229. // This code is based on the line cursor code in nsBlockFrame. It's more general
  230. // though, and could be extracted and used elsewhere.
  231. struct FrameCursorData {
  232. nsTArray<nsIFrame*> mFrames;
  233. uint32_t mCursorIndex;
  234. nscoord mOverflowAbove;
  235. nscoord mOverflowBelow;
  236. FrameCursorData()
  237. : mFrames(MIN_ROWS_NEEDING_CURSOR), mCursorIndex(0), mOverflowAbove(0),
  238. mOverflowBelow(0) {}
  239. bool AppendFrame(nsIFrame* aFrame);
  240. void FinishBuildingCursor() {
  241. mFrames.Compact();
  242. }
  243. };
  244. // Clear out row cursor because we're disturbing the rows (e.g., Reflow)
  245. void ClearRowCursor();
  246. /**
  247. * Get the first row that might contain y-coord 'aY', or nullptr if you must search
  248. * all rows.
  249. * The actual row returned might not contain 'aY', but if not, it is guaranteed
  250. * to be before any row which does contain 'aY'.
  251. * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y.
  252. * To find all rows that intersect the vertical interval aY/aYMost, call
  253. * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all
  254. * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost.
  255. * That row and all subsequent rows cannot intersect the interval.
  256. */
  257. nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove);
  258. /**
  259. * Set up the row cursor. After this, call AppendFrame for every
  260. * child frame in sibling order. Ensure that the child frame y and YMost values
  261. * form non-decreasing sequences (should always be true for table rows);
  262. * if this is violated, call ClearRowCursor(). If we return nullptr, then we
  263. * decided not to use a cursor or we already have one set up.
  264. */
  265. FrameCursorData* SetupRowCursor();
  266. virtual nsILineIterator* GetLineIterator() override { return this; }
  267. virtual bool IsFrameOfType(uint32_t aFlags) const override
  268. {
  269. return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
  270. }
  271. virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
  272. virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
  273. virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
  274. protected:
  275. explicit nsTableRowGroupFrame(nsStyleContext* aContext);
  276. void InitChildReflowInput(nsPresContext& aPresContext,
  277. bool aBorderCollapse,
  278. ReflowInput& aReflowInput);
  279. virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
  280. void PlaceChild(nsPresContext* aPresContext,
  281. TableRowGroupReflowInput& aReflowInput,
  282. nsIFrame* aKidFrame,
  283. mozilla::WritingMode aWM,
  284. const mozilla::LogicalPoint& aKidPosition,
  285. const nsSize& aContainerSize,
  286. ReflowOutput& aDesiredSize,
  287. const nsRect& aOriginalKidRect,
  288. const nsRect& aOriginalKidVisualOverflow);
  289. void CalculateRowBSizes(nsPresContext* aPresContext,
  290. ReflowOutput& aDesiredSize,
  291. const ReflowInput& aReflowInput);
  292. void DidResizeRows(ReflowOutput& aDesiredSize);
  293. void SlideChild(TableRowGroupReflowInput& aReflowInput,
  294. nsIFrame* aKidFrame);
  295. /**
  296. * Reflow the frames we've already created
  297. *
  298. * @param aPresContext presentation context to use
  299. * @param aReflowInput current inline state
  300. */
  301. void ReflowChildren(nsPresContext* aPresContext,
  302. ReflowOutput& aDesiredSize,
  303. TableRowGroupReflowInput& aReflowInput,
  304. nsReflowStatus& aStatus,
  305. bool* aPageBreakBeforeEnd = nullptr);
  306. nsresult SplitRowGroup(nsPresContext* aPresContext,
  307. ReflowOutput& aDesiredSize,
  308. const ReflowInput& aReflowInput,
  309. nsTableFrame* aTableFrame,
  310. nsReflowStatus& aStatus,
  311. bool aRowForcedPageBreak);
  312. void SplitSpanningCells(nsPresContext& aPresContext,
  313. const ReflowInput& aReflowInput,
  314. nsTableFrame& aTableFrame,
  315. nsTableRowFrame& aFirstRow,
  316. nsTableRowFrame& aLastRow,
  317. bool aFirstRowIsTopOfPage,
  318. nscoord aSpanningRowBottom,
  319. nsTableRowFrame*& aContRowFrame,
  320. nsTableRowFrame*& aFirstTruncatedRow,
  321. nscoord& aDesiredHeight);
  322. void CreateContinuingRowFrame(nsPresContext& aPresContext,
  323. nsIFrame& aRowFrame,
  324. nsIFrame** aContRowFrame);
  325. bool IsSimpleRowFrame(nsTableFrame* aTableFrame,
  326. nsTableRowFrame* aRowFrame);
  327. void GetNextRowSibling(nsIFrame** aRowFrame);
  328. void UndoContinuedRow(nsPresContext* aPresContext,
  329. nsTableRowFrame* aRow);
  330. private:
  331. // border widths in pixels in the collapsing border model
  332. BCPixelSize mIEndContBorderWidth;
  333. BCPixelSize mBEndContBorderWidth;
  334. BCPixelSize mIStartContBorderWidth;
  335. public:
  336. bool IsRepeatable() const;
  337. void SetRepeatable(bool aRepeatable);
  338. bool HasStyleBSize() const;
  339. void SetHasStyleBSize(bool aValue);
  340. bool HasInternalBreakBefore() const;
  341. bool HasInternalBreakAfter() const;
  342. };
  343. inline bool nsTableRowGroupFrame::IsRepeatable() const
  344. {
  345. return HasAnyStateBits(NS_ROWGROUP_REPEATABLE);
  346. }
  347. inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable)
  348. {
  349. if (aRepeatable) {
  350. AddStateBits(NS_ROWGROUP_REPEATABLE);
  351. } else {
  352. RemoveStateBits(NS_ROWGROUP_REPEATABLE);
  353. }
  354. }
  355. inline bool nsTableRowGroupFrame::HasStyleBSize() const
  356. {
  357. return HasAnyStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
  358. }
  359. inline void nsTableRowGroupFrame::SetHasStyleBSize(bool aValue)
  360. {
  361. if (aValue) {
  362. AddStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
  363. } else {
  364. RemoveStateBits(NS_ROWGROUP_HAS_STYLE_BSIZE);
  365. }
  366. }
  367. inline void
  368. nsTableRowGroupFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
  369. mozilla::LogicalMargin& aBorder)
  370. {
  371. int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
  372. aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips,
  373. mIEndContBorderWidth);
  374. aBorder.BEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips,
  375. mBEndContBorderWidth);
  376. aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips,
  377. mIStartContBorderWidth);
  378. }
  379. #endif