forked from mirrors/gecko-dev
		
	 aad8d26078
			
		
	
	
		aad8d26078
		
	
	
	
	
		
			
			This is needed for patch 4. This is based both on the wording in the spec and the discussion in https://github.com/w3c/csswg-drafts/issues/2987, and also doesn't support them for nsMathMLContainerFrame, which is similar to inlines and ruby. Differential Revision: https://phabricator.services.mozilla.com/D2815 --HG-- extra : rebase_source : b7e23fb248fa34957ca2d539134e872f5a03f5a8
		
			
				
	
	
		
			458 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			458 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| #ifndef nsTableRowFrame_h__
 | |
| #define nsTableRowFrame_h__
 | |
| 
 | |
| #include "mozilla/Attributes.h"
 | |
| #include "nscore.h"
 | |
| #include "nsContainerFrame.h"
 | |
| #include "nsTableRowGroupFrame.h"
 | |
| #include "mozilla/WritingModes.h"
 | |
| 
 | |
| class  nsTableCellFrame;
 | |
| namespace mozilla {
 | |
| struct TableCellReflowInput;
 | |
| } // namespace mozilla
 | |
| 
 | |
| /**
 | |
|  * nsTableRowFrame is the frame that maps table rows
 | |
|  * (HTML tag TR). This class cannot be reused
 | |
|  * outside of an nsTableRowGroupFrame.  It assumes that its parent is an nsTableRowGroupFrame,
 | |
|  * and its children are nsTableCellFrames.
 | |
|  *
 | |
|  * @see nsTableFrame
 | |
|  * @see nsTableRowGroupFrame
 | |
|  * @see nsTableCellFrame
 | |
|  */
 | |
| class nsTableRowFrame : public nsContainerFrame
 | |
| {
 | |
|   using TableCellReflowInput = mozilla::TableCellReflowInput;
 | |
| 
 | |
| public:
 | |
|   NS_DECL_QUERYFRAME
 | |
|   NS_DECL_FRAMEARENA_HELPERS(nsTableRowFrame)
 | |
| 
 | |
|   virtual ~nsTableRowFrame();
 | |
| 
 | |
|   virtual void Init(nsIContent*       aContent,
 | |
|                     nsContainerFrame* aParent,
 | |
|                     nsIFrame*         aPrevInFlow) override;
 | |
| 
 | |
|   virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
 | |
| 
 | |
|   /** @see nsIFrame::DidSetComputedStyle */
 | |
|   virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
 | |
| 
 | |
|   virtual void AppendFrames(ChildListID     aListID,
 | |
|                             nsFrameList&    aFrameList) override;
 | |
|   virtual void InsertFrames(ChildListID     aListID,
 | |
|                             nsIFrame*       aPrevFrame,
 | |
|                             nsFrameList&    aFrameList) override;
 | |
|   virtual void RemoveFrame(ChildListID     aListID,
 | |
|                            nsIFrame*       aOldFrame) override;
 | |
| 
 | |
|   /** instantiate a new instance of nsTableRowFrame.
 | |
|     * @param aPresShell the pres shell for this frame
 | |
|     *
 | |
|     * @return           the frame that was created
 | |
|     */
 | |
|   friend nsTableRowFrame* NS_NewTableRowFrame(nsIPresShell* aPresShell,
 | |
|                                               ComputedStyle* aStyle);
 | |
| 
 | |
|   nsTableRowGroupFrame* GetTableRowGroupFrame() const
 | |
|   {
 | |
|     nsIFrame* parent = GetParent();
 | |
|     MOZ_ASSERT(parent && parent->IsTableRowGroupFrame());
 | |
|     return static_cast<nsTableRowGroupFrame*>(parent);
 | |
|   }
 | |
| 
 | |
|   nsTableFrame* GetTableFrame() const
 | |
|   {
 | |
|     return GetTableRowGroupFrame()->GetTableFrame();
 | |
|   }
 | |
| 
 | |
|   virtual nsMargin GetUsedMargin() const override;
 | |
|   virtual nsMargin GetUsedBorder() const override;
 | |
|   virtual nsMargin GetUsedPadding() const override;
 | |
| 
 | |
|   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
 | |
|                                 const nsDisplayListSet& aLists) override;
 | |
| 
 | |
|   // Implemented in nsTableCellFrame.h, because it needs to know about the
 | |
|   // nsTableCellFrame class, but we can't include nsTableCellFrame.h here.
 | |
|   inline nsTableCellFrame* GetFirstCell() const;
 | |
| 
 | |
|   /** calls Reflow for all of its child cells.
 | |
|     * Cells with rowspan=1 are all set to the same height and stacked horizontally.
 | |
|     * <P> Cells are not split unless absolutely necessary.
 | |
|     * <P> Cells are resized in nsTableFrame::BalanceColumnWidths
 | |
|     * and nsTableFrame::ShrinkWrapChildren
 | |
|     *
 | |
|     * @param aDesiredSize width set to width of the sum of the cells, height set to
 | |
|     *                     height of cells with rowspan=1.
 | |
|     *
 | |
|     * @see nsIFrame::Reflow
 | |
|     * @see nsTableFrame::BalanceColumnWidths
 | |
|     * @see nsTableFrame::ShrinkWrapChildren
 | |
|     */
 | |
|   virtual void Reflow(nsPresContext*           aPresContext,
 | |
|                       ReflowOutput&     aDesiredSize,
 | |
|                       const ReflowInput& aReflowInput,
 | |
|                       nsReflowStatus&          aStatus) override;
 | |
| 
 | |
|   void DidResize();
 | |
| 
 | |
| #ifdef DEBUG_FRAME_DUMP
 | |
|   virtual nsresult GetFrameName(nsAString& aResult) const override;
 | |
| #endif
 | |
| 
 | |
|   void UpdateBSize(nscoord           aBSize,
 | |
|                    nscoord           aAscent,
 | |
|                    nscoord           aDescent,
 | |
|                    nsTableFrame*     aTableFrame = nullptr,
 | |
|                    nsTableCellFrame* aCellFrame  = nullptr);
 | |
| 
 | |
|   void ResetBSize(nscoord aRowStyleBSize);
 | |
| 
 | |
|   // calculate the bsize, considering content bsize of the
 | |
|   // cells and the style bsize of the row and cells, excluding pct bsizes
 | |
|   nscoord CalcBSize(const ReflowInput& aReflowInput);
 | |
| 
 | |
|   // Support for cells with 'vertical-align: baseline'.
 | |
| 
 | |
|   /**
 | |
|    * returns the max-ascent amongst all the cells that have
 | |
|    * 'vertical-align: baseline', *including* cells with rowspans.
 | |
|    * returns 0 if we don't have any cell with 'vertical-align: baseline'
 | |
|    */
 | |
|   nscoord GetMaxCellAscent() const;
 | |
| 
 | |
|   /* return the row ascent
 | |
|    */
 | |
|   nscoord GetRowBaseline(mozilla::WritingMode aWritingMode);
 | |
| 
 | |
|   /** returns the ordinal position of this row in its table */
 | |
|   virtual int32_t GetRowIndex() const;
 | |
| 
 | |
|   /** set this row's starting row index */
 | |
|   void SetRowIndex (int aRowIndex);
 | |
| 
 | |
|   // See nsTableFrame.h
 | |
|   int32_t GetAdjustmentForStoredIndex(int32_t aStoredIndex) const;
 | |
| 
 | |
|   // See nsTableFrame.h
 | |
|   void AddDeletedRowIndex();
 | |
| 
 | |
|   /** used by row group frame code */
 | |
|   nscoord ReflowCellFrame(nsPresContext*           aPresContext,
 | |
|                           const ReflowInput& aReflowInput,
 | |
|                           bool                     aIsTopOfPage,
 | |
|                           nsTableCellFrame*        aCellFrame,
 | |
|                           nscoord                  aAvailableBSize,
 | |
|                           nsReflowStatus&          aStatus);
 | |
|   /**
 | |
|     * Collapse the row if required, apply col and colgroup visibility: collapse
 | |
|     * info to the cells in the row.
 | |
|     * @return the amount to shift bstart-wards all following rows
 | |
|     * @param aRowOffset     - shift the row bstart-wards by this amount
 | |
|     * @param aISize         - new isize of the row
 | |
|     * @param aCollapseGroup - parent rowgroup is collapsed so this row needs
 | |
|     *                         to be collapsed
 | |
|     * @param aDidCollapse   - the row has been collapsed
 | |
|     */
 | |
|   nscoord CollapseRowIfNecessary(nscoord aRowOffset,
 | |
|                                  nscoord aISize,
 | |
|                                  bool    aCollapseGroup,
 | |
|                                  bool&   aDidCollapse);
 | |
| 
 | |
|   /**
 | |
|    * Insert a cell frame after the last cell frame that has a col index
 | |
|    * that is less than aColIndex.  If no such cell frame is found the
 | |
|    * frame to insert is prepended to the child list.
 | |
|    * @param aFrame the cell frame to insert
 | |
|    * @param aColIndex the col index
 | |
|    */
 | |
|   void InsertCellFrame(nsTableCellFrame* aFrame,
 | |
|                        int32_t           aColIndex);
 | |
| 
 | |
|   nsresult CalculateCellActualBSize(nsTableCellFrame*    aCellFrame,
 | |
|                                     nscoord&             aDesiredBSize,
 | |
|                                     mozilla::WritingMode aWM);
 | |
| 
 | |
|   bool IsFirstInserted() const;
 | |
|   void   SetFirstInserted(bool aValue);
 | |
| 
 | |
|   nscoord GetContentBSize() const;
 | |
|   void    SetContentBSize(nscoord aTwipValue);
 | |
| 
 | |
|   bool HasStyleBSize() const;
 | |
| 
 | |
|   bool HasFixedBSize() const;
 | |
|   void   SetHasFixedBSize(bool aValue);
 | |
| 
 | |
|   bool HasPctBSize() const;
 | |
|   void   SetHasPctBSize(bool aValue);
 | |
| 
 | |
|   nscoord GetFixedBSize() const;
 | |
|   void    SetFixedBSize(nscoord aValue);
 | |
| 
 | |
|   float   GetPctBSize() const;
 | |
|   void    SetPctBSize(float  aPctValue,
 | |
|                        bool aForce = false);
 | |
| 
 | |
|   nscoord GetInitialBSize(nscoord aBasis = 0) const;
 | |
| 
 | |
|   nsTableRowFrame* GetNextRow() const;
 | |
| 
 | |
|   bool    HasUnpaginatedBSize();
 | |
|   void    SetHasUnpaginatedBSize(bool aValue);
 | |
|   nscoord GetUnpaginatedBSize();
 | |
|   void    SetUnpaginatedBSize(nsPresContext* aPresContext, nscoord aValue);
 | |
| 
 | |
|   nscoord GetBStartBCBorderWidth() const { return mBStartBorderWidth; }
 | |
|   nscoord GetBEndBCBorderWidth() const { return mBEndBorderWidth; }
 | |
|   void SetBStartBCBorderWidth(BCPixelSize aWidth) { mBStartBorderWidth = aWidth; }
 | |
|   void SetBEndBCBorderWidth(BCPixelSize aWidth) { mBEndBorderWidth = aWidth; }
 | |
|   mozilla::LogicalMargin GetBCBorderWidth(mozilla::WritingMode aWM);
 | |
| 
 | |
|   /**
 | |
|    * Gets inner border widths before collapsing with cell borders
 | |
|    * Caller must get block-end border from next row or from table
 | |
|    * GetContinuousBCBorderWidth will not overwrite that border
 | |
|    * see nsTablePainter about continuous borders
 | |
|    */
 | |
|   void GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
 | |
|                                   mozilla::LogicalMargin& aBorder);
 | |
| 
 | |
|   /**
 | |
|    * @returns outer block-start bc border == prev row's block-end inner
 | |
|    */
 | |
|   nscoord GetOuterBStartContBCBorderWidth();
 | |
|   /**
 | |
|    * Sets full border widths before collapsing with cell borders
 | |
|    * @param aForSide - side to set; only accepts iend, istart, and bstart
 | |
|    */
 | |
|   void SetContinuousBCBorderWidth(mozilla::LogicalSide aForSide,
 | |
|                                   BCPixelSize aPixelValue);
 | |
| 
 | |
|   virtual bool IsFrameOfType(uint32_t aFlags) const override
 | |
|   {
 | |
|     if (aFlags & eSupportsContainLayoutAndPaint) {
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
 | |
|   }
 | |
| 
 | |
|   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true) override;
 | |
|   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true) override;
 | |
|   virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
 | |
| 
 | |
| #ifdef ACCESSIBILITY
 | |
|   virtual mozilla::a11y::AccType AccessibleType() override;
 | |
| #endif
 | |
| 
 | |
| protected:
 | |
| 
 | |
|   /** protected constructor.
 | |
|     * @see NewFrame
 | |
|     */
 | |
|   explicit nsTableRowFrame(ComputedStyle* aStyle, ClassID aID = kClassID);
 | |
| 
 | |
|   void InitChildReflowInput(nsPresContext&              aPresContext,
 | |
|                             const mozilla::LogicalSize& aAvailSize,
 | |
|                             bool                        aBorderCollapse,
 | |
|                             TableCellReflowInput&     aReflowInput);
 | |
| 
 | |
|   virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
 | |
| 
 | |
|   // row-specific methods
 | |
| 
 | |
|   nscoord ComputeCellXOffset(const ReflowInput& aState,
 | |
|                              nsIFrame*                aKidFrame,
 | |
|                              const nsMargin&          aKidMargin) const;
 | |
|   /**
 | |
|    * Called for incremental/dirty and resize reflows. If aDirtyOnly is true then
 | |
|    * only reflow dirty cells.
 | |
|    */
 | |
|   void ReflowChildren(nsPresContext*           aPresContext,
 | |
|                       ReflowOutput&     aDesiredSize,
 | |
|                       const ReflowInput& aReflowInput,
 | |
|                       nsTableFrame&            aTableFrame,
 | |
|                       nsReflowStatus&          aStatus);
 | |
| 
 | |
| private:
 | |
|   struct RowBits {
 | |
|     unsigned mRowIndex:29;
 | |
|     unsigned mHasFixedBSize:1; // set if the dominating style bsize on the row or any cell is pixel based
 | |
|     unsigned mHasPctBSize:1;   // set if the dominating style bsize on the row or any cell is pct based
 | |
|     unsigned mFirstInserted:1; // if true, then it was the bstart-most newly inserted row
 | |
|   } mBits;
 | |
| 
 | |
|   // the desired bsize based on the content of the tallest cell in the row
 | |
|   nscoord mContentBSize;
 | |
|   // the bsize based on a style percentage bsize on either the row or any cell
 | |
|   // if mHasPctBSize is set
 | |
|   nscoord mStylePctBSize;
 | |
|   // the bsize based on a style pixel bsize on the row or any
 | |
|   // cell if mHasFixedBSize is set
 | |
|   nscoord mStyleFixedBSize;
 | |
| 
 | |
|   // max-ascent and max-descent amongst all cells that have 'vertical-align: baseline'
 | |
|   nscoord mMaxCellAscent;  // does include cells with rowspan > 1
 | |
|   nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1
 | |
| 
 | |
|   // border widths in pixels in the collapsing border model of the *inner*
 | |
|   // half of the border only
 | |
|   BCPixelSize mBStartBorderWidth;
 | |
|   BCPixelSize mBEndBorderWidth;
 | |
|   BCPixelSize mIEndContBorderWidth;
 | |
|   BCPixelSize mBStartContBorderWidth;
 | |
|   BCPixelSize mIStartContBorderWidth;
 | |
| 
 | |
|   /**
 | |
|    * Sets the NS_ROW_HAS_CELL_WITH_STYLE_BSIZE bit to indicate whether
 | |
|    * this row has any cells that have non-auto-bsize.  (Row-spanning
 | |
|    * cells are ignored.)
 | |
|    */
 | |
|   void InitHasCellWithStyleBSize(nsTableFrame* aTableFrame);
 | |
| 
 | |
| };
 | |
| 
 | |
| inline int32_t
 | |
| nsTableRowFrame::GetAdjustmentForStoredIndex(int32_t aStoredIndex) const
 | |
| {
 | |
|   nsTableRowGroupFrame* parentFrame = GetTableRowGroupFrame();
 | |
|   return parentFrame->GetAdjustmentForStoredIndex(aStoredIndex);
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::AddDeletedRowIndex()
 | |
| {
 | |
|   nsTableRowGroupFrame* parentFrame = GetTableRowGroupFrame();
 | |
|   parentFrame->AddDeletedRowIndex(int32_t(mBits.mRowIndex));
 | |
| }
 | |
| 
 | |
| inline int32_t nsTableRowFrame::GetRowIndex() const
 | |
| {
 | |
|   int32_t storedRowIndex = int32_t(mBits.mRowIndex);
 | |
|   int32_t rowIndexAdjustment = GetAdjustmentForStoredIndex(storedRowIndex);
 | |
|   return (storedRowIndex - rowIndexAdjustment);
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
 | |
| {
 | |
|   // Note: Setting the index of a row (as in the case of adding new rows) should
 | |
|   // be preceded by a call to nsTableFrame::RecalculateRowIndices()
 | |
|   // so as to correctly clear mDeletedRowIndexRanges.
 | |
|   MOZ_ASSERT(GetTableRowGroupFrame()->
 | |
|                GetTableFrame()->IsDeletedRowIndexRangesEmpty(),
 | |
|              "mDeletedRowIndexRanges should be empty here!");
 | |
|   mBits.mRowIndex = aRowIndex;
 | |
| }
 | |
| 
 | |
| inline bool nsTableRowFrame::IsFirstInserted() const
 | |
| {
 | |
|   return bool(mBits.mFirstInserted);
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::SetFirstInserted(bool aValue)
 | |
| {
 | |
|   mBits.mFirstInserted = aValue;
 | |
| }
 | |
| 
 | |
| inline bool nsTableRowFrame::HasStyleBSize() const
 | |
| {
 | |
|   return (bool)mBits.mHasFixedBSize || (bool)mBits.mHasPctBSize;
 | |
| }
 | |
| 
 | |
| inline bool nsTableRowFrame::HasFixedBSize() const
 | |
| {
 | |
|   return (bool)mBits.mHasFixedBSize;
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::SetHasFixedBSize(bool aValue)
 | |
| {
 | |
|   mBits.mHasFixedBSize = aValue;
 | |
| }
 | |
| 
 | |
| inline bool nsTableRowFrame::HasPctBSize() const
 | |
| {
 | |
|   return (bool)mBits.mHasPctBSize;
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::SetHasPctBSize(bool aValue)
 | |
| {
 | |
|   mBits.mHasPctBSize = aValue;
 | |
| }
 | |
| 
 | |
| inline nscoord nsTableRowFrame::GetContentBSize() const
 | |
| {
 | |
|   return mContentBSize;
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::SetContentBSize(nscoord aValue)
 | |
| {
 | |
|   mContentBSize = aValue;
 | |
| }
 | |
| 
 | |
| inline nscoord nsTableRowFrame::GetFixedBSize() const
 | |
| {
 | |
|   if (mBits.mHasFixedBSize) {
 | |
|     return mStyleFixedBSize;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| inline float nsTableRowFrame::GetPctBSize() const
 | |
| {
 | |
|   if (mBits.mHasPctBSize) {
 | |
|     return (float)mStylePctBSize / 100.0f;
 | |
|   }
 | |
|   return 0.0f;
 | |
| }
 | |
| 
 | |
| inline bool nsTableRowFrame::HasUnpaginatedBSize()
 | |
| {
 | |
|   return HasAnyStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE);
 | |
| }
 | |
| 
 | |
| inline void nsTableRowFrame::SetHasUnpaginatedBSize(bool aValue)
 | |
| {
 | |
|   if (aValue) {
 | |
|     AddStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE);
 | |
|   } else {
 | |
|     RemoveStateBits(NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE);
 | |
|   }
 | |
| }
 | |
| 
 | |
| inline mozilla::LogicalMargin
 | |
| nsTableRowFrame::GetBCBorderWidth(mozilla::WritingMode aWM)
 | |
| {
 | |
|   nsPresContext* presContext = PresContext();
 | |
|   return mozilla::LogicalMargin(
 | |
|     aWM, presContext->DevPixelsToAppUnits(mBStartBorderWidth), 0,
 | |
|     presContext->DevPixelsToAppUnits(mBEndBorderWidth), 0);
 | |
| }
 | |
| 
 | |
| inline void
 | |
| nsTableRowFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM,
 | |
|                                             mozilla::LogicalMargin& aBorder)
 | |
| {
 | |
|   int32_t d2a = PresContext()->AppUnitsPerDevPixel();
 | |
|   aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(d2a,
 | |
|                                                  mIStartContBorderWidth);
 | |
|   aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(d2a,
 | |
|                                                  mBStartContBorderWidth);
 | |
|   aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(d2a,
 | |
|                                                  mIEndContBorderWidth);
 | |
| }
 | |
| 
 | |
| inline nscoord nsTableRowFrame::GetOuterBStartContBCBorderWidth()
 | |
| {
 | |
|   int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
 | |
|   return BC_BORDER_START_HALF_COORD(aPixelsToTwips, mBStartContBorderWidth);
 | |
| }
 | |
| 
 | |
| #endif
 |