diff options
Diffstat (limited to 'layout/tables/nsTableRowFrame.h')
-rw-r--r-- | layout/tables/nsTableRowFrame.h | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h new file mode 100644 index 0000000000..6f7b5e340e --- /dev/null +++ b/layout/tables/nsTableRowFrame.h @@ -0,0 +1,432 @@ +/* -*- 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 { +class PresShell; +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(); + + void Init(nsIContent* aContent, nsContainerFrame* aParent, + nsIFrame* aPrevInFlow) override; + + void Destroy(DestroyContext&) override; + + void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override; + + void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override; + void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, + const nsLineList::iterator* aPrevFrameLine, + nsFrameList&& aFrameList) override; + void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) 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(mozilla::PresShell* 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(); + } + + nsMargin GetUsedMargin() const override; + nsMargin GetUsedBorder() const override; + nsMargin GetUsedPadding() const override; + + void BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aLists) override; + + void PaintCellBackgroundsForFrame(nsIFrame* aFrame, + nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aLists, + const nsPoint& aOffset = nsPoint()); + + // 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. + * + * Cells are not split unless absolutely necessary. + * + * 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 + */ + void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, + const ReflowInput& aReflowInput, + nsReflowStatus& aStatus) override; + + void DidResize(); + +#ifdef DEBUG_FRAME_DUMP + 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 + */ + Maybe<nscoord> GetRowBaseline(mozilla::WritingMode aWM); + + /** 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); + + BCPixelSize GetBStartBCBorderWidth() const { return mBStartBorderWidth; } + BCPixelSize 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); + + bool IsFrameOfType(uint32_t aFlags) const override { + if (aFlags & (eSupportsContainLayoutAndPaint | eSupportsAspectRatio)) { + return false; + } + + return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart)); + } + + void InvalidateFrame(uint32_t aDisplayItemKey = 0, + bool aRebuildDisplayItems = true) override; + void InvalidateFrameWithRect(const nsRect& aRect, + uint32_t aDisplayItemKey = 0, + bool aRebuildDisplayItems = true) override; + void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); } + +#ifdef ACCESSIBILITY + mozilla::a11y::AccType AccessibleType() override; +#endif + + protected: + /** protected constructor. + * @see NewFrame + */ + explicit nsTableRowFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, + ClassID aID = kClassID); + + void InitChildReflowInput(nsPresContext& aPresContext, + const mozilla::LogicalSize& aAvailSize, + bool aBorderCollapse, + TableCellReflowInput& aReflowInput); + + LogicalSides GetLogicalSkipSides() 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 = 0; + // the bsize based on a style percentage bsize on either the row or any cell + // if mHasPctBSize is set + nscoord mStylePctBSize = 0; + // the bsize based on a style pixel bsize on the row or any + // cell if mHasFixedBSize is set + nscoord mStyleFixedBSize = 0; + + // max-ascent and max-descent amongst all cells that have + // 'vertical-align: baseline' + nscoord mMaxCellAscent = 0; // does include cells with rowspan > 1 + nscoord mMaxCellDescent = 0; // 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 = 0; + BCPixelSize mBEndBorderWidth = 0; + BCPixelSize mIEndContBorderWidth = 0; + BCPixelSize mBStartContBorderWidth = 0; + BCPixelSize mIStartContBorderWidth = 0; + + /** + * 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 = mozilla::AppUnitsPerCSSPixel(); + return BC_BORDER_START_HALF_COORD(aPixelsToTwips, mBStartContBorderWidth); +} + +#endif |