1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/tables/nsTableRowGroupFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,456 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +#ifndef nsTableRowGroupFrame_h__ 1.9 +#define nsTableRowGroupFrame_h__ 1.10 + 1.11 +#include "mozilla/Attributes.h" 1.12 +#include "nscore.h" 1.13 +#include "nsContainerFrame.h" 1.14 +#include "nsIAtom.h" 1.15 +#include "nsILineIterator.h" 1.16 +#include "nsTablePainter.h" 1.17 +#include "nsTArray.h" 1.18 + 1.19 +class nsTableFrame; 1.20 +class nsTableRowFrame; 1.21 +class nsTableCellFrame; 1.22 + 1.23 +struct nsRowGroupReflowState { 1.24 + const nsHTMLReflowState& reflowState; // Our reflow state 1.25 + 1.26 + nsTableFrame* tableFrame; 1.27 + 1.28 + // The available size (computed from the parent) 1.29 + nsSize availSize; 1.30 + 1.31 + // Running y-offset 1.32 + nscoord y; 1.33 + 1.34 + nsRowGroupReflowState(const nsHTMLReflowState& aReflowState, 1.35 + nsTableFrame* aTableFrame) 1.36 + :reflowState(aReflowState), tableFrame(aTableFrame) 1.37 + { 1.38 + availSize.width = reflowState.AvailableWidth(); 1.39 + availSize.height = reflowState.AvailableHeight(); 1.40 + y = 0; 1.41 + } 1.42 + 1.43 + ~nsRowGroupReflowState() {} 1.44 +}; 1.45 + 1.46 +#define MIN_ROWS_NEEDING_CURSOR 20 1.47 + 1.48 +/** 1.49 + * nsTableRowGroupFrame is the frame that maps row groups 1.50 + * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused 1.51 + * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame, and 1.52 + * its children are nsTableRowFrames. 1.53 + * 1.54 + * @see nsTableFrame 1.55 + * @see nsTableRowFrame 1.56 + */ 1.57 +class nsTableRowGroupFrame 1.58 + : public nsContainerFrame 1.59 + , public nsILineIterator 1.60 +{ 1.61 +public: 1.62 + NS_DECL_QUERYFRAME_TARGET(nsTableRowGroupFrame) 1.63 + NS_DECL_QUERYFRAME 1.64 + NS_DECL_FRAMEARENA_HELPERS 1.65 + 1.66 + /** instantiate a new instance of nsTableRowFrame. 1.67 + * @param aPresShell the pres shell for this frame 1.68 + * 1.69 + * @return the frame that was created 1.70 + */ 1.71 + friend nsIFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); 1.72 + virtual ~nsTableRowGroupFrame(); 1.73 + 1.74 + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; 1.75 + 1.76 + /** @see nsIFrame::DidSetStyleContext */ 1.77 + virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; 1.78 + 1.79 + virtual nsresult AppendFrames(ChildListID aListID, 1.80 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.81 + 1.82 + virtual nsresult InsertFrames(ChildListID aListID, 1.83 + nsIFrame* aPrevFrame, 1.84 + nsFrameList& aFrameList) MOZ_OVERRIDE; 1.85 + 1.86 + virtual nsresult RemoveFrame(ChildListID aListID, 1.87 + nsIFrame* aOldFrame) MOZ_OVERRIDE; 1.88 + 1.89 + virtual nsMargin GetUsedMargin() const MOZ_OVERRIDE; 1.90 + virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE; 1.91 + virtual nsMargin GetUsedPadding() const MOZ_OVERRIDE; 1.92 + 1.93 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.94 + const nsRect& aDirtyRect, 1.95 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.96 + 1.97 + /** calls Reflow for all of its child rows. 1.98 + * Rows are all set to the same width and stacked vertically. 1.99 + * <P> rows are not split unless absolutely necessary. 1.100 + * 1.101 + * @param aDesiredSize width set to width of rows, height set to 1.102 + * sum of height of rows that fit in aMaxSize.height. 1.103 + * 1.104 + * @see nsIFrame::Reflow 1.105 + */ 1.106 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.107 + nsHTMLReflowMetrics& aDesiredSize, 1.108 + const nsHTMLReflowState& aReflowState, 1.109 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.110 + 1.111 + virtual bool UpdateOverflow() MOZ_OVERRIDE; 1.112 + 1.113 + /** 1.114 + * Get the "type" of the frame 1.115 + * 1.116 + * @see nsGkAtoms::tableRowGroupFrame 1.117 + */ 1.118 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.119 + 1.120 + nsTableRowFrame* GetFirstRow(); 1.121 + 1.122 +#ifdef DEBUG_FRAME_DUMP 1.123 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; 1.124 +#endif 1.125 + 1.126 + /** return the number of child rows (not necessarily == number of child frames) */ 1.127 + int32_t GetRowCount(); 1.128 + 1.129 + /** return the table-relative row index of the first row in this rowgroup. 1.130 + * if there are no rows, -1 is returned. 1.131 + */ 1.132 + int32_t GetStartRowIndex(); 1.133 + 1.134 + /** Adjust the row indices of all rows whose index is >= aRowIndex. 1.135 + * @param aRowIndex - start adjusting with this index 1.136 + * @param aAdjustment - shift the row index by this amount 1.137 + */ 1.138 + void AdjustRowIndices(int32_t aRowIndex, 1.139 + int32_t anAdjustment); 1.140 + 1.141 + /** 1.142 + * Used for header and footer row group frames that are repeated when 1.143 + * splitting a table frame. 1.144 + * 1.145 + * Performs any table specific initialization 1.146 + * 1.147 + * @param aHeaderFooterFrame the original header or footer row group frame 1.148 + * that was repeated 1.149 + */ 1.150 + nsresult InitRepeatedFrame(nsPresContext* aPresContext, 1.151 + nsTableRowGroupFrame* aHeaderFooterFrame); 1.152 + 1.153 + 1.154 + /** 1.155 + * Get the total height of all the row rects 1.156 + */ 1.157 + nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState); 1.158 + 1.159 + nsMargin* GetBCBorderWidth(nsMargin& aBorder); 1.160 + 1.161 + /** 1.162 + * Gets inner border widths before collapsing with cell borders 1.163 + * Caller must get top border from previous row group or from table 1.164 + * GetContinuousBCBorderWidth will not overwrite aBorder.top 1.165 + * see nsTablePainter about continuous borders 1.166 + */ 1.167 + void GetContinuousBCBorderWidth(nsMargin& aBorder); 1.168 + /** 1.169 + * Sets full border widths before collapsing with cell borders 1.170 + * @param aForSide - side to set; only right, left, and bottom valid 1.171 + */ 1.172 + void SetContinuousBCBorderWidth(uint8_t aForSide, 1.173 + BCPixelSize aPixelValue); 1.174 + /** 1.175 + * Adjust to the effect of visibibility:collapse on the row group and 1.176 + * its children 1.177 + * @return additional shift upward that should be applied to 1.178 + * subsequent rowgroups due to rows and this rowgroup 1.179 + * being collapsed 1.180 + * @param aYTotalOffset the total amount that the rowgroup is shifted up 1.181 + * @param aWidth new width of the rowgroup 1.182 + */ 1.183 + nscoord CollapseRowGroupIfNecessary(nscoord aYTotalOffset, 1.184 + nscoord aWidth); 1.185 + 1.186 +// nsILineIterator methods 1.187 +public: 1.188 + virtual void DisposeLineIterator() MOZ_OVERRIDE { } 1.189 + 1.190 + // The table row is the equivalent to a line in block layout. 1.191 + // The nsILineIterator assumes that a line resides in a block, this role is 1.192 + // fullfilled by the row group. Rows in table are counted relative to the 1.193 + // table. The row index of row corresponds to the cellmap coordinates. The 1.194 + // line index with respect to a row group can be computed by substracting the 1.195 + // row index of the first row in the row group. 1.196 + 1.197 + /** Get the number of rows in a row group 1.198 + * @return the number of lines in a row group 1.199 + */ 1.200 + virtual int32_t GetNumLines() MOZ_OVERRIDE; 1.201 + 1.202 + /** @see nsILineIterator.h GetDirection 1.203 + * @return true if the table is rtl 1.204 + */ 1.205 + virtual bool GetDirection() MOZ_OVERRIDE; 1.206 + 1.207 + /** Return structural information about a line. 1.208 + * @param aLineNumber - the index of the row relative to the row group 1.209 + * If the line-number is invalid then 1.210 + * aFirstFrameOnLine will be nullptr and 1.211 + * aNumFramesOnLine will be zero. 1.212 + * @param aFirstFrameOnLine - the first cell frame that originates in row 1.213 + * with a rowindex that matches a line number 1.214 + * @param aNumFramesOnLine - return the numbers of cells originating in 1.215 + * this row 1.216 + * @param aLineBounds - rect of the row 1.217 + * @param aLineFlags - unused set to 0 1.218 + */ 1.219 + NS_IMETHOD GetLine(int32_t aLineNumber, 1.220 + nsIFrame** aFirstFrameOnLine, 1.221 + int32_t* aNumFramesOnLine, 1.222 + nsRect& aLineBounds, 1.223 + uint32_t* aLineFlags) MOZ_OVERRIDE; 1.224 + 1.225 + /** Given a frame that's a child of the rowgroup, find which line its on. 1.226 + * @param aFrame - frame, should be a row 1.227 + * @param aStartLine - minimal index to return 1.228 + * @return row index relative to the row group if this a row 1.229 + * frame and the index is at least aStartLine. 1.230 + * -1 if the frame cannot be found. 1.231 + */ 1.232 + virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE; 1.233 + 1.234 + /** Find the orginating cell frame on a row that is the nearest to the 1.235 + * coordinate X. 1.236 + * @param aLineNumber - the index of the row relative to the row group 1.237 + * @param aX - X coordinate in twips relative to the 1.238 + * origin of the row group 1.239 + * @param aFrameFound - pointer to the cellframe 1.240 + * @param aXIsBeforeFirstFrame - the point is before the first originating 1.241 + * cellframe 1.242 + * @param aXIsAfterLastFrame - the point is after the last originating 1.243 + * cellframe 1.244 + */ 1.245 + NS_IMETHOD FindFrameAt(int32_t aLineNumber, 1.246 + nscoord aX, 1.247 + nsIFrame** aFrameFound, 1.248 + bool* aXIsBeforeFirstFrame, 1.249 + bool* aXIsAfterLastFrame) MOZ_OVERRIDE; 1.250 + 1.251 + /** Check whether visual and logical order of cell frames within a line are 1.252 + * identical. As the layout will reorder them this is always the case 1.253 + * @param aLine - the index of the row relative to the table 1.254 + * @param aIsReordered - returns false 1.255 + * @param aFirstVisual - if the table is rtl first originating cell frame 1.256 + * @param aLastVisual - if the table is rtl last originating cell frame 1.257 + */ 1.258 + 1.259 + NS_IMETHOD CheckLineOrder(int32_t aLine, 1.260 + bool *aIsReordered, 1.261 + nsIFrame **aFirstVisual, 1.262 + nsIFrame **aLastVisual) MOZ_OVERRIDE; 1.263 + 1.264 + /** Find the next originating cell frame that originates in the row. 1.265 + * @param aFrame - cell frame to start with, will return the next cell 1.266 + * originating in a row 1.267 + * @param aLineNumber - the index of the row relative to the table 1.268 + */ 1.269 + NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) MOZ_OVERRIDE; 1.270 + 1.271 + // row cursor methods to speed up searching for the row(s) 1.272 + // containing a point. The basic idea is that we set the cursor 1.273 + // property if the rows' y and yMosts are non-decreasing (considering only 1.274 + // rows with nonempty overflowAreas --- empty overflowAreas never participate 1.275 + // in event handling or painting), and the rowgroup has sufficient number of 1.276 + // rows. The cursor property points to a "recently used" row. If we get a 1.277 + // series of requests that work on rows "near" the cursor, then we can find 1.278 + // those nearby rows quickly by starting our search at the cursor. 1.279 + // This code is based on the line cursor code in nsBlockFrame. It's more general 1.280 + // though, and could be extracted and used elsewhere. 1.281 + struct FrameCursorData { 1.282 + nsTArray<nsIFrame*> mFrames; 1.283 + uint32_t mCursorIndex; 1.284 + nscoord mOverflowAbove; 1.285 + nscoord mOverflowBelow; 1.286 + 1.287 + FrameCursorData() 1.288 + : mFrames(MIN_ROWS_NEEDING_CURSOR), mCursorIndex(0), mOverflowAbove(0), 1.289 + mOverflowBelow(0) {} 1.290 + 1.291 + bool AppendFrame(nsIFrame* aFrame); 1.292 + 1.293 + void FinishBuildingCursor() { 1.294 + mFrames.Compact(); 1.295 + } 1.296 + }; 1.297 + 1.298 + // Clear out row cursor because we're disturbing the rows (e.g., Reflow) 1.299 + void ClearRowCursor(); 1.300 + 1.301 + /** 1.302 + * Get the first row that might contain y-coord 'aY', or nullptr if you must search 1.303 + * all rows. 1.304 + * The actual row returned might not contain 'aY', but if not, it is guaranteed 1.305 + * to be before any row which does contain 'aY'. 1.306 + * aOverflowAbove is the maximum over all rows of -row.GetOverflowRect().y. 1.307 + * To find all rows that intersect the vertical interval aY/aYMost, call 1.308 + * GetFirstRowContaining(aY, &overflowAbove), and then iterate through all 1.309 + * rows until reaching a row where row->GetRect().y - overflowAbove >= aYMost. 1.310 + * That row and all subsequent rows cannot intersect the interval. 1.311 + */ 1.312 + nsIFrame* GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove); 1.313 + 1.314 + /** 1.315 + * Set up the row cursor. After this, call AppendFrame for every 1.316 + * child frame in sibling order. Ensure that the child frame y and YMost values 1.317 + * form non-decreasing sequences (should always be true for table rows); 1.318 + * if this is violated, call ClearRowCursor(). If we return nullptr, then we 1.319 + * decided not to use a cursor or we already have one set up. 1.320 + */ 1.321 + FrameCursorData* SetupRowCursor(); 1.322 + 1.323 + virtual nsILineIterator* GetLineIterator() MOZ_OVERRIDE { return this; } 1.324 + 1.325 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.326 + { 1.327 + return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart)); 1.328 + } 1.329 + 1.330 + virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; 1.331 + virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; 1.332 + virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); } 1.333 + 1.334 +protected: 1.335 + nsTableRowGroupFrame(nsStyleContext* aContext); 1.336 + 1.337 + void InitChildReflowState(nsPresContext& aPresContext, 1.338 + bool aBorderCollapse, 1.339 + nsHTMLReflowState& aReflowState); 1.340 + 1.341 + virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; 1.342 + 1.343 + void PlaceChild(nsPresContext* aPresContext, 1.344 + nsRowGroupReflowState& aReflowState, 1.345 + nsIFrame* aKidFrame, 1.346 + nsHTMLReflowMetrics& aDesiredSize, 1.347 + const nsRect& aOriginalKidRect, 1.348 + const nsRect& aOriginalKidVisualOverflow); 1.349 + 1.350 + void CalculateRowHeights(nsPresContext* aPresContext, 1.351 + nsHTMLReflowMetrics& aDesiredSize, 1.352 + const nsHTMLReflowState& aReflowState); 1.353 + 1.354 + void DidResizeRows(nsHTMLReflowMetrics& aDesiredSize); 1.355 + 1.356 + void SlideChild(nsRowGroupReflowState& aReflowState, 1.357 + nsIFrame* aKidFrame); 1.358 + 1.359 + /** 1.360 + * Reflow the frames we've already created 1.361 + * 1.362 + * @param aPresContext presentation context to use 1.363 + * @param aReflowState current inline state 1.364 + * @return true if we successfully reflowed all the mapped children and false 1.365 + * otherwise, e.g. we pushed children to the next in flow 1.366 + */ 1.367 + nsresult ReflowChildren(nsPresContext* aPresContext, 1.368 + nsHTMLReflowMetrics& aDesiredSize, 1.369 + nsRowGroupReflowState& aReflowState, 1.370 + nsReflowStatus& aStatus, 1.371 + bool* aPageBreakBeforeEnd = nullptr); 1.372 + 1.373 + nsresult SplitRowGroup(nsPresContext* aPresContext, 1.374 + nsHTMLReflowMetrics& aDesiredSize, 1.375 + const nsHTMLReflowState& aReflowState, 1.376 + nsTableFrame* aTableFrame, 1.377 + nsReflowStatus& aStatus, 1.378 + bool aRowForcedPageBreak); 1.379 + 1.380 + void SplitSpanningCells(nsPresContext& aPresContext, 1.381 + const nsHTMLReflowState& aReflowState, 1.382 + nsTableFrame& aTableFrame, 1.383 + nsTableRowFrame& aFirstRow, 1.384 + nsTableRowFrame& aLastRow, 1.385 + bool aFirstRowIsTopOfPage, 1.386 + nscoord aSpanningRowBottom, 1.387 + nsTableRowFrame*& aContRowFrame, 1.388 + nsTableRowFrame*& aFirstTruncatedRow, 1.389 + nscoord& aDesiredHeight); 1.390 + 1.391 + void CreateContinuingRowFrame(nsPresContext& aPresContext, 1.392 + nsIFrame& aRowFrame, 1.393 + nsIFrame** aContRowFrame); 1.394 + 1.395 + bool IsSimpleRowFrame(nsTableFrame* aTableFrame, 1.396 + nsIFrame* aFrame); 1.397 + 1.398 + void GetNextRowSibling(nsIFrame** aRowFrame); 1.399 + 1.400 + void UndoContinuedRow(nsPresContext* aPresContext, 1.401 + nsTableRowFrame* aRow); 1.402 + 1.403 +private: 1.404 + // border widths in pixels in the collapsing border model 1.405 + BCPixelSize mRightContBorderWidth; 1.406 + BCPixelSize mBottomContBorderWidth; 1.407 + BCPixelSize mLeftContBorderWidth; 1.408 + 1.409 +public: 1.410 + bool IsRepeatable() const; 1.411 + void SetRepeatable(bool aRepeatable); 1.412 + bool HasStyleHeight() const; 1.413 + void SetHasStyleHeight(bool aValue); 1.414 + bool HasInternalBreakBefore() const; 1.415 + bool HasInternalBreakAfter() const; 1.416 +}; 1.417 + 1.418 + 1.419 +inline bool nsTableRowGroupFrame::IsRepeatable() const 1.420 +{ 1.421 + return (mState & NS_ROWGROUP_REPEATABLE) == NS_ROWGROUP_REPEATABLE; 1.422 +} 1.423 + 1.424 +inline void nsTableRowGroupFrame::SetRepeatable(bool aRepeatable) 1.425 +{ 1.426 + if (aRepeatable) { 1.427 + mState |= NS_ROWGROUP_REPEATABLE; 1.428 + } else { 1.429 + mState &= ~NS_ROWGROUP_REPEATABLE; 1.430 + } 1.431 +} 1.432 + 1.433 +inline bool nsTableRowGroupFrame::HasStyleHeight() const 1.434 +{ 1.435 + return (mState & NS_ROWGROUP_HAS_STYLE_HEIGHT) == NS_ROWGROUP_HAS_STYLE_HEIGHT; 1.436 +} 1.437 + 1.438 +inline void nsTableRowGroupFrame::SetHasStyleHeight(bool aValue) 1.439 +{ 1.440 + if (aValue) { 1.441 + mState |= NS_ROWGROUP_HAS_STYLE_HEIGHT; 1.442 + } else { 1.443 + mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT; 1.444 + } 1.445 +} 1.446 + 1.447 +inline void 1.448 +nsTableRowGroupFrame::GetContinuousBCBorderWidth(nsMargin& aBorder) 1.449 +{ 1.450 + int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); 1.451 + aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips, 1.452 + mRightContBorderWidth); 1.453 + aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, 1.454 + mBottomContBorderWidth); 1.455 + aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, 1.456 + mLeftContBorderWidth); 1.457 + return; 1.458 +} 1.459 +#endif