diff options
Diffstat (limited to 'layout/tables/nsTableRowFrame.h')
-rw-r--r-- | layout/tables/nsTableRowFrame.h | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h new file mode 100644 index 000000000..a6aba81e7 --- /dev/null +++ b/layout/tables/nsTableRowFrame.h @@ -0,0 +1,437 @@ +/* -*- 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 "nsTablePainter.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_TARGET(nsTableRowFrame) + NS_DECL_QUERYFRAME + NS_DECL_FRAMEARENA_HELPERS + + virtual ~nsTableRowFrame(); + + virtual void Init(nsIContent* aContent, + nsContainerFrame* aParent, + nsIFrame* aPrevInFlow) override; + + virtual void DestroyFrom(nsIFrame* aDestructRoot) override; + + /** @see nsIFrame::DidSetStyleContext */ + virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) 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, + nsStyleContext* aContext); + + nsTableRowGroupFrame* GetTableRowGroupFrame() const + { + nsIFrame* parent = GetParent(); + MOZ_ASSERT(parent && parent->GetType() == nsGkAtoms::tableRowGroupFrame); + 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 nsRect& aDirtyRect, + const nsDisplayListSet& aLists) override; + + nsTableCellFrame* GetFirstCell() ; + + /** 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(); + + /** + * Get the "type" of the frame + * + * @see nsGkAtoms::tableRowFrame + */ + virtual nsIAtom* GetType() const override; + +#ifdef DEBUG_FRAME_DUMP + virtual nsresult GetFrameName(nsAString& aResult) const override; +#endif + + virtual mozilla::WritingMode GetWritingMode() const override + { return GetTableFrame()->GetWritingMode(); } + + 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); + + /** 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 + { + return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart)); + } + + virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override; + virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override; + virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); } + +#ifdef ACCESSIBILITY + virtual mozilla::a11y::AccType AccessibleType() override; +#endif + +protected: + + /** protected constructor. + * @see NewFrame + */ + explicit nsTableRowFrame(nsStyleContext *aContext); + + 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::GetRowIndex() const +{ + return int32_t(mBits.mRowIndex); +} + +inline void nsTableRowFrame::SetRowIndex (int aRowIndex) +{ + 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) +{ + return mozilla::LogicalMargin( + aWM, nsPresContext::CSSPixelsToAppUnits(mBStartBorderWidth), 0, + nsPresContext::CSSPixelsToAppUnits(mBEndBorderWidth), 0); +} + +inline void +nsTableRowFrame::GetContinuousBCBorderWidth(mozilla::WritingMode aWM, + mozilla::LogicalMargin& aBorder) +{ + int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); + aBorder.IEnd(aWM) = BC_BORDER_START_HALF_COORD(aPixelsToTwips, + mIStartContBorderWidth); + aBorder.BStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + mBStartContBorderWidth); + aBorder.IStart(aWM) = BC_BORDER_END_HALF_COORD(aPixelsToTwips, + mIEndContBorderWidth); +} + +inline nscoord nsTableRowFrame::GetOuterBStartContBCBorderWidth() +{ + int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); + return BC_BORDER_START_HALF_COORD(aPixelsToTwips, mBStartContBorderWidth); +} + +#endif |