diff --git a/layout/painting/nsDisplayItemTypesList.h b/layout/painting/nsDisplayItemTypesList.h index 71036dd05cc5..be3950e4d8f4 100644 --- a/layout/painting/nsDisplayItemTypesList.h +++ b/layout/painting/nsDisplayItemTypesList.h @@ -56,6 +56,9 @@ DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY) DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT) DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND) DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION) +DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND) +DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND) +DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_BACKGROUND) DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE) DECLARE_DISPLAY_ITEM_TYPE(TEXT) DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW) diff --git a/layout/tables/moz.build b/layout/tables/moz.build index fba649593d4f..1a23480a0120 100644 --- a/layout/tables/moz.build +++ b/layout/tables/moz.build @@ -21,6 +21,7 @@ UNIFIED_SOURCES += [ 'nsTableColFrame.cpp', 'nsTableColGroupFrame.cpp', 'nsTableFrame.cpp', + 'nsTablePainter.cpp', 'nsTableRowFrame.cpp', 'nsTableRowGroupFrame.cpp', 'nsTableWrapperFrame.cpp', diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 8084eff709ea..09090847bed8 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -12,6 +12,7 @@ #include "nsTableColFrame.h" #include "nsTableRowFrame.h" #include "nsTableRowGroupFrame.h" +#include "nsTablePainter.h" #include "nsStyleContext.h" #include "nsStyleConsts.h" #include "nsPresContext.h" @@ -385,6 +386,19 @@ nsTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext, return nsCSSRendering::PaintStyleImageLayer(params, aRenderingContext); } +// Called by nsTablePainter +DrawResult +nsTableCellFrame::PaintCellBackground(nsRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsPoint aPt, + uint32_t aFlags) +{ + if (!StyleVisibility()->IsVisible()) { + return DrawResult::SUCCESS; + } + + return PaintBackground(aRenderingContext, aDirtyRect, aPt, aFlags); +} + nsresult nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame, nsDisplayListBuilder* aBuilder, diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h index 296dc03a682d..1fda36b31803 100644 --- a/layout/tables/nsTableCellFrame.h +++ b/layout/tables/nsTableCellFrame.h @@ -112,6 +112,11 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; + DrawResult PaintCellBackground(nsRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsPoint aPt, + uint32_t aFlags); + + virtual nsresult ProcessBorders(nsTableFrame* aFrame, nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists); diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 2d78bb3fe5ad..1fc52c66e92d 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -23,6 +23,7 @@ #include "nsTableRowFrame.h" #include "nsTableRowGroupFrame.h" #include "nsTableWrapperFrame.h" +#include "nsTablePainter.h" #include "BasicTableLayoutStrategy.h" #include "FixedTableLayoutStrategy.h" @@ -1277,6 +1278,36 @@ nsDisplayTableBorderCollapse::Paint(nsDisplayListBuilder* aBuilder, static_cast(mFrame)->PaintBCBorders(*drawTarget, mVisibleRect - pt); } +class nsDisplayTableBorderBackground : public nsDisplayTableItem { +public: + nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder, + nsTableFrame* aFrame, + bool aDrawsBackground) : + nsDisplayTableItem(aBuilder, aFrame, aDrawsBackground) { + MOZ_COUNT_CTOR(nsDisplayTableBorderBackground); + } +#ifdef NS_BUILD_REFCNT_LOGGING + virtual ~nsDisplayTableBorderBackground() { + MOZ_COUNT_DTOR(nsDisplayTableBorderBackground); + } +#endif + + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) override; + NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND) +}; + +void +nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) +{ + DrawResult result = static_cast(mFrame)-> + PaintTableBorderBackground(aBuilder, *aCtx, mVisibleRect, + ToReferenceFrame()); + + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); +} + /* static */ void nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) @@ -1485,6 +1516,59 @@ nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const return GetOuterBCBorder(wm).GetPhysicalMargin(wm); } +// XXX We don't put the borders and backgrounds in tree order like we should. +// That requires some major surgery which we aren't going to do right now. +DrawResult +nsTableFrame::PaintTableBorderBackground(nsDisplayListBuilder* aBuilder, + nsRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsPoint aPt) +{ + nsPresContext* presContext = PresContext(); + + uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags(); + PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages() + ? PaintBorderFlags::SYNC_DECODE_IMAGES + : PaintBorderFlags(); + + TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table, + presContext, aRenderingContext, + aDirtyRect, aPt, bgFlags); + nsMargin deflate = GetDeflationForBackground(presContext); + // If 'deflate' is (0,0,0,0) then we'll paint the table background + // in a separate display item, so don't do it here. + DrawResult result = + painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0)); + + if (StyleVisibility()->IsVisible()) { + if (!IsBorderCollapse()) { + Sides skipSides = GetSkipSides(); + nsRect rect(aPt, mRect.Size()); + + result &= + nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, + aDirtyRect, rect, mStyleContext, + borderFlags, skipSides); + } else { + DrawTarget* drawTarget = aRenderingContext.GetDrawTarget(); + + gfxPoint devPixelOffset = + nsLayoutUtils::PointToGfxPoint(aPt, + PresContext()->AppUnitsPerDevPixel()); + + // XXX we should probably get rid of this translation at some stage + // But that would mean modifying PaintBCBorders, ugh + AutoRestoreTransform autoRestoreTransform(drawTarget); + drawTarget->SetTransform( + drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset))); + + PaintBCBorders(*drawTarget, aDirtyRect - aPt); + } + } + + return result; +} + nsIFrame::LogicalSides nsTableFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const { diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index a53f52b2c146..a15015431c76 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -266,6 +266,16 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; + /** + * Paint the background of the table and its parts (column groups, + * columns, row groups, rows, and cells), and the table border, and all + * internal borders if border-collapse is on. + */ + DrawResult PaintTableBorderBackground(nsDisplayListBuilder* aBuilder, + nsRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsPoint aPt); + /** Get the outer half (i.e., the part outside the height and width of * the table) of the largest segment (?) of border-collapsed border on * the table on each side, or 0 for non border-collapsed tables. diff --git a/layout/tables/nsTablePainter.cpp b/layout/tables/nsTablePainter.cpp new file mode 100644 index 000000000000..3acff80963ea --- /dev/null +++ b/layout/tables/nsTablePainter.cpp @@ -0,0 +1,695 @@ +/* -*- 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/. */ + +#include "nsTableFrame.h" +#include "nsTableRowGroupFrame.h" +#include "nsTableRowFrame.h" +#include "nsTableColGroupFrame.h" +#include "nsTableColFrame.h" +#include "nsTableCellFrame.h" +#include "nsTablePainter.h" +#include "nsCSSRendering.h" +#include "nsDisplayList.h" +#include "mozilla/WritingModes.h" + +/* ~*~ Table Background Painting ~*~ + + Mozilla's Table Background painting follows CSS2.1:17.5.1 + That section does not, however, describe the effect of + borders on background image positioning. What we do is: + + - in separate borders, the borders are passed in so that + their width figures in image positioning, even for rows/cols, which + don't have visible borders. This is done to allow authors + to position row backgrounds by, for example, aligning the + top left corner with the top left padding corner of the + top left table cell in the row in cases where all cells + have consistent border widths. If we didn't honor these + invisible borders, there would be no way to align + backgrounds with the padding edges, and designs would be + lost underneath the border. + + - in collapsing borders, because the borders collapse, we + use the -continuous border- width to synthesize a border + style and pass that in instead of using the element's + assigned style directly. + + The continuous border on a given edge of an element is + the collapse of all borders guaranteed to be continuous + along that edge. Cell borders are ignored (because, for + example, setting a thick border on the leftmost cell + should not shift the row background over; this way a + striped background set on will line up across rows + even if the cells are assigned arbitrary border widths. + + For example, the continuous border on the top edge of a + row group is the collapse of any row group, row, and + table borders involved. (The first row group's top would + be [table-top + row group top + first row top]. It's bottom + would be [row group bottom + last row bottom + next row + top + next row group top].) + The top edge of a column group likewise includes the + table top, row group top, and first row top borders. However, + it *also* includes its own top border, since that is guaranteed + to be continuous. It does not include column borders because + those are not guaranteed to be continuous: there may be two + columns with different borders in a single column group. + + An alternative would be to define the continuous border as + [table? + row group + row] for horizontal + [table? + col group + col] for vertical + This makes it easier to line up backgrounds across elements + despite varying border widths, but it does not give much + flexibility in aligning /to/ those border widths. +*/ + + +/* ~*~ TableBackgroundPainter ~*~ + + The TableBackgroundPainter is created and destroyed in one painting call. + Its principal function is PaintTable, which paints all table element + backgrounds. The initial code in that method sets up an array of column + data that caches the background styles and the border sizes for the + columns and colgroups in TableBackgroundData structs in mCols. Data for + BC borders are calculated and stashed in a synthesized border style struct + in the data struct since collapsed borders aren't the same width as style- + assigned borders. The data struct optimizes by only doing this if there's + an image background; otherwise we don't care. //XXX should also check background-origin + The class then loops through the row groups, rows, and cells. At the cell + level, it paints the backgrounds, one over the other, inside the cell rect. + + The exception to this pattern is when a table element creates a (pseudo) + stacking context. Elements with stacking contexts (e.g., 'opacity' applied) + are passed through, which means their data (and their + descendants' data) are not cached. The full loop is still executed, however, + so that underlying layers can get painted at the cell level. + + The TableBackgroundPainter is then destroyed. + + Elements with stacking contexts set up their own painter to finish the + painting process, since they were skipped. They call the appropriate + sub-part of the loop (e.g. PaintRow) which will paint the frame and + descendants. + + XXX views are going + */ + +using namespace mozilla; +using namespace mozilla::image; + +TableBackgroundPainter::TableBackgroundData::TableBackgroundData() + : mFrame(nullptr) + , mVisible(false) + , mUsesSynthBorder(false) +{ +} + +TableBackgroundPainter::TableBackgroundData::TableBackgroundData(nsIFrame* aFrame) + : mFrame(aFrame) + , mRect(aFrame->GetRect()) + , mVisible(mFrame->IsVisibleForPainting()) + , mUsesSynthBorder(false) +{ +} + +inline bool +TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder() const +{ + /* we only need accurate border data when positioning background images*/ + if (!mVisible) { + return false; + } + + const nsStyleImageLayers& layers = mFrame->StyleBackground()->mImage; + NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, layers) { + if (!layers.mLayers[i].mImage.IsEmpty()) + return true; + } + return false; +} + +void +TableBackgroundPainter::TableBackgroundData::SetBCBorder(const nsMargin& aBorder) +{ + mUsesSynthBorder = true; + mSynthBorderWidths = aBorder; +} + +nsStyleBorder +TableBackgroundPainter::TableBackgroundData::StyleBorder(const nsStyleBorder& aZeroBorder) const +{ + MOZ_ASSERT(mVisible, "Don't call StyleBorder on an invisible TableBackgroundData"); + + if (mUsesSynthBorder) { + nsStyleBorder result = aZeroBorder; + NS_FOR_CSS_SIDES(side) { + result.SetBorderWidth(side, mSynthBorderWidths.Side(side)); + } + return result; + } + + MOZ_ASSERT(mFrame); + + return *mFrame->StyleBorder(); +} + +TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame, + Origin aOrigin, + nsPresContext* aPresContext, + nsRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + const nsPoint& aRenderPt, + uint32_t aBGPaintFlags) + : mPresContext(aPresContext), + mRenderingContext(aRenderingContext), + mRenderPt(aRenderPt), + mDirtyRect(aDirtyRect), + mOrigin(aOrigin), + mZeroBorder(aPresContext), + mBGPaintFlags(aBGPaintFlags) +{ + MOZ_COUNT_CTOR(TableBackgroundPainter); + + NS_FOR_CSS_SIDES(side) { + mZeroBorder.SetBorderStyle(side, NS_STYLE_BORDER_STYLE_SOLID); + mZeroBorder.SetBorderWidth(side, 0); + } + + mIsBorderCollapse = aTableFrame->IsBorderCollapse(); +#ifdef DEBUG + mCompatMode = mPresContext->CompatibilityMode(); +#endif + mNumCols = aTableFrame->GetColCount(); +} + +TableBackgroundPainter::~TableBackgroundPainter() +{ + MOZ_COUNT_DTOR(TableBackgroundPainter); +} + +DrawResult +TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame, + nsTableRowGroupFrame* aFirstRowGroup, + nsTableRowGroupFrame* aLastRowGroup, + const nsMargin& aDeflate) +{ + MOZ_ASSERT(aTableFrame, "null frame"); + TableBackgroundData tableData(aTableFrame); + tableData.mRect.MoveTo(0,0); //using table's coords + tableData.mRect.Deflate(aDeflate); + WritingMode wm = aTableFrame->GetWritingMode(); + if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) { + if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) { + //only handle non-degenerate tables; we need a more robust BC model + //to make degenerate tables' borders reasonable to deal with + LogicalMargin border(wm); + LogicalMargin tempBorder(wm); + nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1); + if (colFrame) { + colFrame->GetContinuousBCBorderWidth(wm, tempBorder); + } + border.IEnd(wm) = tempBorder.IEnd(wm); + + aLastRowGroup->GetContinuousBCBorderWidth(wm, tempBorder); + border.BEnd(wm) = tempBorder.BEnd(wm); + + nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow(); + if (rowFrame) { + rowFrame->GetContinuousBCBorderWidth(wm, tempBorder); + border.BStart(wm) = tempBorder.BStart(wm); + } + + border.IStart(wm) = aTableFrame->GetContinuousIStartBCBorderWidth(); + + tableData.SetBCBorder(border.GetPhysicalMargin(wm)); + } + } + + DrawResult result = DrawResult::SUCCESS; + + if (tableData.IsVisible()) { + nsCSSRendering::PaintBGParams params = + nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, + mDirtyRect, + tableData.mRect + mRenderPt, + tableData.mFrame, + mBGPaintFlags); + + result &= + nsCSSRendering::PaintStyleImageLayerWithSC(params, mRenderingContext, + tableData.mFrame->StyleContext(), + tableData.StyleBorder(mZeroBorder)); + } + + return result; +} + +void +TableBackgroundPainter::TranslateContext(nscoord aDX, + nscoord aDY) +{ + mRenderPt += nsPoint(aDX, aDY); + for (auto& col : mCols) { + col.mCol.mRect.MoveBy(-aDX, -aDY); + } + for (auto& colGroup : mColGroups) { + colGroup.mRect.MoveBy(-aDX, -aDY); + } +} + +TableBackgroundPainter::ColData::ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData) + : mCol(aFrame) + , mColGroup(aColGroupBGData) +{ +} + +DrawResult +TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame, + const nsMargin& aDeflate, + bool aPaintTableBackground) +{ + NS_PRECONDITION(aTableFrame, "null table frame"); + + nsTableFrame::RowGroupArray rowGroups; + aTableFrame->OrderRowGroups(rowGroups); + WritingMode wm = aTableFrame->GetWritingMode(); + + DrawResult result = DrawResult::SUCCESS; + + if (rowGroups.Length() < 1) { //degenerate case + if (aPaintTableBackground) { + result &= PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0)); + } + /* No cells; nothing else to paint */ + return result; + } + + if (aPaintTableBackground) { + result &= + PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1], + aDeflate); + } + + /*Set up column background/border data*/ + if (mNumCols > 0) { + nsFrameList& colGroupList = aTableFrame->GetColGroups(); + NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup"); + + // Collect all col group frames first so that we know how many there are. + nsTArray colGroupFrames; + for (nsTableColGroupFrame* cgFrame = static_cast(colGroupList.FirstChild()); + cgFrame; cgFrame = static_cast(cgFrame->GetNextSibling())) { + + if (cgFrame->GetColCount() < 1) { + //No columns, no cells, so no need for data + continue; + } + colGroupFrames.AppendElement(cgFrame); + } + + // Ensure that mColGroups won't reallocate during the loop below, because + // we grab references to its contents and need those to stay valid until + // mColGroups is destroyed as part of TablePainter destruction. + mColGroups.SetCapacity(colGroupFrames.Length()); + + LogicalMargin border(wm); + /* BC iStart borders aren't stored on cols, but the previous column's + iEnd border is the next one's iStart border.*/ + //Start with table's iStart border. + nscoord lastIStartBorder = aTableFrame->GetContinuousIStartBCBorderWidth(); + + for (nsTableColGroupFrame* cgFrame : colGroupFrames) { + /*Create data struct for column group*/ + TableBackgroundData& cgData = *mColGroups.AppendElement(TableBackgroundData(cgFrame)); + if (mIsBorderCollapse && cgData.ShouldSetBCBorder()) { + border.IStart(wm) = lastIStartBorder; + cgFrame->GetContinuousBCBorderWidth(wm, border); + cgData.SetBCBorder(border.GetPhysicalMargin(wm)); + } + + /*Loop over columns in this colgroup*/ + for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col; + col = static_cast(col->GetNextSibling())) { + MOZ_ASSERT(size_t(col->GetColIndex()) == mCols.Length()); + // Store a reference to the colGroup in the ColData element. + ColData& colData = *mCols.AppendElement(ColData(col, cgData)); + //Bring column mRect into table's coord system + colData.mCol.mRect.MoveBy(cgData.mRect.x, cgData.mRect.y); + if (mIsBorderCollapse) { + border.IStart(wm) = lastIStartBorder; + lastIStartBorder = col->GetContinuousBCBorderWidth(wm, border); + if (colData.mCol.ShouldSetBCBorder()) { + colData.mCol.SetBCBorder(border.GetPhysicalMargin(wm)); + } + } + } + } + } + + for (uint32_t i = 0; i < rowGroups.Length(); i++) { + nsTableRowGroupFrame* rg = rowGroups[i]; + TableBackgroundData rowGroupBGData(rg); + // Need to compute the right rect via GetOffsetTo, since the row + // group may not be a child of the table. + rowGroupBGData.mRect.MoveTo(rg->GetOffsetTo(aTableFrame)); + + // We have to draw backgrounds not only within the overflow region of this + // row group, but also possibly (in the case of column / column group + // backgrounds) at its pre-relative-positioning location. + nsRect rgVisualOverflow = rg->GetVisualOverflowRectRelativeToSelf(); + nsRect rgOverflowRect = rgVisualOverflow + rg->GetPosition(); + nsRect rgNormalRect = rgVisualOverflow + rg->GetNormalPosition(); + + if (rgOverflowRect.Union(rgNormalRect).Intersects(mDirtyRect - mRenderPt)) { + result &= + PaintRowGroup(rg, rowGroupBGData, rg->IsPseudoStackingContextFromStyle()); + } + } + + return result; +} + +DrawResult +TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame) +{ + return PaintRowGroup(aFrame, TableBackgroundData(aFrame), false); +} + +DrawResult +TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame, + TableBackgroundData aRowGroupBGData, + bool aPassThrough) +{ + MOZ_ASSERT(aFrame, "null frame"); + + nsTableRowFrame* firstRow = aFrame->GetFirstRow(); + WritingMode wm = aFrame->GetWritingMode(); + + /* Load row group data */ + if (aPassThrough) { + aRowGroupBGData.MakeInvisible(); + } else { + if (mIsBorderCollapse && aRowGroupBGData.ShouldSetBCBorder()) { + LogicalMargin border(wm); + if (firstRow) { + //pick up first row's bstart border (= rg bstart border) + firstRow->GetContinuousBCBorderWidth(wm, border); + /* (row group doesn't store its bstart border) */ + } + //overwrite sides+bottom borders with rg's own + aFrame->GetContinuousBCBorderWidth(wm, border); + aRowGroupBGData.SetBCBorder(border.GetPhysicalMargin(wm)); + } + aPassThrough = !aRowGroupBGData.IsVisible(); + } + + /* translate everything into row group coord system*/ + if (eOrigin_TableRowGroup != mOrigin) { + TranslateContext(aRowGroupBGData.mRect.x, aRowGroupBGData.mRect.y); + } + nsRect rgRect = aRowGroupBGData.mRect; + aRowGroupBGData.mRect.MoveTo(0, 0); + + /* Find the right row to start with */ + + // Note that mDirtyRect - mRenderPt is guaranteed to be in the row + // group's coordinate system here, so passing its .y to + // GetFirstRowContaining is ok. + nscoord overflowAbove; + nsIFrame* cursor = aFrame->GetFirstRowContaining(mDirtyRect.y - mRenderPt.y, &overflowAbove); + + // Sadly, it seems like there may be non-row frames in there... or something? + // There are certainly null-checks in GetFirstRow() and GetNextRow(). :( + while (cursor && !cursor->IsTableRowFrame()) { + cursor = cursor->GetNextSibling(); + } + + // It's OK if cursor is null here. + nsTableRowFrame* row = static_cast(cursor); + if (!row) { + // No useful cursor; just start at the top. Don't bother to set up a + // cursor; if we've gotten this far then we've already built the display + // list for the rowgroup, so not having a cursor means that there's some + // good reason we don't have a cursor and we shouldn't create one here. + row = firstRow; + } + + DrawResult result = DrawResult::SUCCESS; + + /* Finally paint */ + for (; row; row = row->GetNextRow()) { + TableBackgroundData rowBackgroundData(row); + + // Be sure to consider our positions both pre- and post-relative + // positioning, since we potentially need to paint at both places. + nscoord rowY = std::min(rowBackgroundData.mRect.y, row->GetNormalPosition().y); + + // Intersect wouldn't handle rowspans. + if (cursor && + (mDirtyRect.YMost() - mRenderPt.y) <= (rowY - overflowAbove)) { + // All done; cells originating in later rows can't intersect mDirtyRect. + break; + } + + result &= + PaintRow(row, aRowGroupBGData, rowBackgroundData, + aPassThrough || row->IsPseudoStackingContextFromStyle()); + } + + /* translate back into table coord system */ + if (eOrigin_TableRowGroup != mOrigin) { + TranslateContext(-rgRect.x, -rgRect.y); + } + + return result; +} + +DrawResult +TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame) +{ + return PaintRow(aFrame, TableBackgroundData(), TableBackgroundData(aFrame), false); +} + +DrawResult +TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame, + const TableBackgroundData& aRowGroupBGData, + TableBackgroundData aRowBGData, + bool aPassThrough) +{ + MOZ_ASSERT(aFrame, "null frame"); + + /* Load row data */ + WritingMode wm = aFrame->GetWritingMode(); + if (aPassThrough) { + aRowBGData.MakeInvisible(); + } else { + if (mIsBorderCollapse && aRowBGData.ShouldSetBCBorder()) { + LogicalMargin border(wm); + nsTableRowFrame* nextRow = aFrame->GetNextRow(); + if (nextRow) { //outer bStart after us is inner bEnd for us + border.BEnd(wm) = nextRow->GetOuterBStartContBCBorderWidth(); + } + else { //acquire rg's bEnd border + nsTableRowGroupFrame* rowGroup = static_cast(aFrame->GetParent()); + rowGroup->GetContinuousBCBorderWidth(wm, border); + } + //get the rest of the borders; will overwrite all but bEnd + aFrame->GetContinuousBCBorderWidth(wm, border); + + aRowBGData.SetBCBorder(border.GetPhysicalMargin(wm)); + } + aPassThrough = !aRowBGData.IsVisible(); + } + + /* Translate */ + if (eOrigin_TableRow == mOrigin) { + /* If we originate from the row, then make the row the origin. */ + aRowBGData.mRect.MoveTo(0, 0); + } + //else: Use row group's coord system -> no translation necessary + + DrawResult result = DrawResult::SUCCESS; + + for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) { + nsRect cellBGRect, rowBGRect, rowGroupBGRect, colBGRect; + ComputeCellBackgrounds(cell, aRowGroupBGData, aRowBGData, + cellBGRect, rowBGRect, + rowGroupBGRect, colBGRect); + + // Find the union of all the cell background layers. + nsRect combinedRect(cellBGRect); + combinedRect.UnionRect(combinedRect, rowBGRect); + combinedRect.UnionRect(combinedRect, rowGroupBGRect); + combinedRect.UnionRect(combinedRect, colBGRect); + + if (combinedRect.Intersects(mDirtyRect)) { + bool passCell = aPassThrough || cell->IsPseudoStackingContextFromStyle(); + result &= + PaintCell(cell, aRowGroupBGData, aRowBGData, cellBGRect, rowBGRect, + rowGroupBGRect, colBGRect, passCell); + } + } + + return result; +} + +DrawResult +TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell, + const TableBackgroundData& aRowGroupBGData, + const TableBackgroundData& aRowBGData, + nsRect& aCellBGRect, + nsRect& aRowBGRect, + nsRect& aRowGroupBGRect, + nsRect& aColBGRect, + bool aPassSelf) +{ + MOZ_ASSERT(aCell, "null frame"); + + const nsStyleTableBorder* cellTableStyle; + cellTableStyle = aCell->StyleTableBorder(); + if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW != cellTableStyle->mEmptyCells && + aCell->GetContentEmpty() && !mIsBorderCollapse) { + return DrawResult::SUCCESS; + } + + int32_t colIndex; + aCell->GetColIndex(colIndex); + // We're checking mNumCols instead of mCols.Length() here because mCols can + // be empty even if mNumCols > 0. + NS_ASSERTION(size_t(colIndex) < mNumCols, "out-of-bounds column index"); + if (size_t(colIndex) >= mNumCols) { + return DrawResult::SUCCESS; + } + + // If callers call PaintRowGroup or PaintRow directly, we haven't processed + // our columns. Ignore column / col group backgrounds in that case. + bool haveColumns = !mCols.IsEmpty(); + + DrawResult result = DrawResult::SUCCESS; + + //Paint column group background + if (haveColumns && mCols[colIndex].mColGroup.IsVisible()) { + nsCSSRendering::PaintBGParams params = + nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, + mDirtyRect, + mCols[colIndex].mColGroup.mRect + mRenderPt, + mCols[colIndex].mColGroup.mFrame, + mBGPaintFlags); + params.bgClipRect = &aColBGRect; + result &= + nsCSSRendering::PaintStyleImageLayerWithSC(params, mRenderingContext, + mCols[colIndex].mColGroup.mFrame->StyleContext(), + mCols[colIndex].mColGroup.StyleBorder(mZeroBorder)); + } + + //Paint column background + if (haveColumns && mCols[colIndex].mCol.IsVisible()) { + nsCSSRendering::PaintBGParams params = + nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, + mDirtyRect, + mCols[colIndex].mCol.mRect + mRenderPt, + mCols[colIndex].mCol.mFrame, + mBGPaintFlags); + params.bgClipRect = &aColBGRect; + result &= + nsCSSRendering::PaintStyleImageLayerWithSC(params, mRenderingContext, + mCols[colIndex].mCol.mFrame->StyleContext(), + mCols[colIndex].mCol.StyleBorder(mZeroBorder)); + } + + //Paint row group background + if (aRowGroupBGData.IsVisible()) { + nsCSSRendering::PaintBGParams params = + nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, + mDirtyRect, + aRowGroupBGData.mRect + mRenderPt, + aRowGroupBGData.mFrame, mBGPaintFlags); + params.bgClipRect = &aRowGroupBGRect; + result &= + nsCSSRendering::PaintStyleImageLayerWithSC(params, mRenderingContext, + aRowGroupBGData.mFrame->StyleContext(), + aRowGroupBGData.StyleBorder(mZeroBorder)); + } + + //Paint row background + if (aRowBGData.IsVisible()) { + nsCSSRendering::PaintBGParams params = + nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, + mDirtyRect, + aRowBGData.mRect + mRenderPt, + aRowBGData.mFrame, mBGPaintFlags); + params.bgClipRect = &aRowBGRect; + result &= + nsCSSRendering::PaintStyleImageLayerWithSC(params, mRenderingContext, + aRowBGData.mFrame->StyleContext(), + aRowBGData.StyleBorder(mZeroBorder)); + } + + //Paint cell background in border-collapse unless we're just passing + if (mIsBorderCollapse && !aPassSelf) { + result &= + aCell->PaintCellBackground(mRenderingContext, mDirtyRect, + aCellBGRect.TopLeft(), mBGPaintFlags); + } + + return result; +} + +void +TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell, + const TableBackgroundData& aRowGroupBGData, + const TableBackgroundData& aRowBGData, + nsRect& aCellBGRect, + nsRect& aRowBGRect, + nsRect& aRowGroupBGRect, + nsRect& aColBGRect) +{ + // We need to compute table background layer rects for this cell space, + // adjusted for possible relative positioning. This behavior is not specified + // at the time of this writing, but the approach below should be web + // compatible. + // + // Our goal is that relative positioning of a table part should leave + // backgrounds *under* that part unchanged. ("Under" being defined by CSS 2.1 + // Section 17.5.1.) If a cell is positioned, we do not expect the row + // background to move. On the other hand, the backgrounds of layers *above* + // the positioned part are taken along for the ride -- for example, + // positioning a row group will also cause the row background to be drawn in + // the new location, unless it has further positioning applied. + // + // Each table part layer has its position stored in the coordinate space of + // the layer below (which is to say, its geometric parent), and the stored + // position is the post-relative-positioning one. The position of each + // background layer rect is thus determined by peeling off successive table + // part layers, removing the contribution of each layer's positioning one by + // one. Every rect we generate will be the same size, the size of the cell + // space. + + // We cannot rely on the row group background data to be available, since some + // callers enter through PaintRow. + nsIFrame* rowGroupFrame = + aRowGroupBGData.mFrame ? aRowGroupBGData.mFrame : aRowBGData.mFrame->GetParent(); + + // The cell background goes at the cell's position, translated to use the same + // coordinate system as aRowBGData. + aCellBGRect = aCell->GetRect() + aRowBGData.mRect.TopLeft() + mRenderPt; + + // The row background goes at the normal position of the cell, which is to say + // the position without relative positioning applied. + aRowBGRect = aCellBGRect + (aCell->GetNormalPosition() - aCell->GetPosition()); + + // The row group background goes at the position we'd find the cell if neither + // the cell's relative positioning nor the row's were applied. + aRowGroupBGRect = aRowBGRect + + (aRowBGData.mFrame->GetNormalPosition() - aRowBGData.mFrame->GetPosition()); + + // The column and column group backgrounds (they're always at the same + // location, since relative positioning doesn't apply to columns or column + // groups) are drawn at the position we'd find the cell if none of the cell's, + // row's, or row group's relative positioning were applied. + aColBGRect = aRowGroupBGRect + + (rowGroupFrame->GetNormalPosition() - rowGroupFrame->GetPosition()); + +} diff --git a/layout/tables/nsTablePainter.h b/layout/tables/nsTablePainter.h new file mode 100644 index 000000000000..dfba42156507 --- /dev/null +++ b/layout/tables/nsTablePainter.h @@ -0,0 +1,268 @@ +/* -*- 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 nsTablePainter_h__ +#define nsTablePainter_h__ + +#include "imgIContainer.h" + +#include "celldata.h" + +// flags for Paint, PaintChild, PaintChildren are currently only used by tables. +//Table-based paint call; not a direct call as with views +#define NS_PAINT_FLAG_TABLE_BG_PAINT 0x00000001 +//Cells should paint their backgrounds only, no children +#define NS_PAINT_FLAG_TABLE_CELL_BG_PASS 0x00000002 + +class nsIFrame; +class nsTableFrame; +class nsTableRowGroupFrame; +class nsTableRowFrame; +class nsTableCellFrame; + +class TableBackgroundPainter +{ + /* + * Helper class for painting table backgrounds + * + */ + + typedef mozilla::image::DrawResult DrawResult; + + public: + + enum Origin { eOrigin_Table, eOrigin_TableRowGroup, eOrigin_TableRow }; + + /** Public constructor + * @param aTableFrame - the table's table frame + * @param aOrigin - what type of table frame is creating this instance + * @param aPresContext - the presentation context + * @param aRenderingContext - the rendering context + * @param aDirtyRect - the area that needs to be painted, + * relative to aRenderingContext + * @param aPt - offset of the table frame relative to + * aRenderingContext + * @param aBGPaintFlags - Flags of the nsCSSRendering::PAINTBG_* variety + */ + TableBackgroundPainter(nsTableFrame* aTableFrame, + Origin aOrigin, + nsPresContext* aPresContext, + nsRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + const nsPoint& aPt, + uint32_t aBGPaintFlags); + + /** Destructor */ + ~TableBackgroundPainter(); + + /* ~*~ The Border Collapse Painting Issue ~*~ + + In border-collapse, the *table* paints the cells' borders, + so we need to make sure the backgrounds get painted first + (underneath) by doing a cell-background-only painting pass. + */ + + /* ~*~ Using nsTablePainter Background Painting ~*~ + + A call to PaintTable will normally paint all of the table's + elements (except for the table background, if aPaintTableBackground + is false). + Elements with views however, will be skipped and must create their + own painter to call the appropriate paint function in their ::Paint + method (e.g. painter.PaintRow in nsTableRow::Paint) + */ + + /** Paint background for the table frame (if requested) and its children + * down through cells. + * (Cells themselves will only be painted in border collapse) + * Table must do a flagged TABLE_BG_PAINT ::Paint call on its + * children afterwards + * @param aTableFrame - the table frame + * @param aDeflate - deflation needed to bring table's mRect + * to the outer grid lines in border-collapse + * @param aPaintTableBackground - if true, the table background + * is included, otherwise it isn't + * @returns DrawResult::SUCCESS if all painting was successful. If some + * painting failed or an improved result could be achieved by sync + * decoding images, returns another value. + */ + DrawResult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate, + bool aPaintTableBackground); + + /** Paint background for the row group and its children down through cells + * (Cells themselves will only be painted in border collapse) + * Standards mode only + * Table Row Group must do a flagged TABLE_BG_PAINT ::Paint call on its + * children afterwards + * @param aFrame - the table row group frame + * @returns DrawResult::SUCCESS if all painting was successful. If some + * painting failed or an improved result could be achieved by sync + * decoding images, returns another value. + */ + DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame); + + /** Paint background for the row and its children down through cells + * (Cells themselves will only be painted in border collapse) + * Standards mode only + * Table Row must do a flagged TABLE_BG_PAINT ::Paint call on its + * children afterwards + * @param aFrame - the table row frame + * @returns DrawResult::SUCCESS if all painting was successful. If some + * painting failed or an improved result could be achieved by sync + * decoding images, returns another value. + */ + DrawResult PaintRow(nsTableRowFrame* aFrame); + + private: + struct TableBackgroundData; + + /** Paint table frame's background + * @param aTableFrame - the table frame + * @param aFirstRowGroup - the first (in layout order) row group + * may be null + * @param aLastRowGroup - the last (in layout order) row group + * may be null + * @param aDeflate - adjustment to frame's rect (used for quirks BC) + * may be null + */ + DrawResult PaintTableFrame(nsTableFrame* aTableFrame, + nsTableRowGroupFrame* aFirstRowGroup, + nsTableRowGroupFrame* aLastRowGroup, + const nsMargin& aDeflate); + + /* aPassThrough params indicate whether to paint the element or to just + * pass through and paint underlying layers only. + * aRowGroupBGData is not a const reference because the function modifies + * its copy. Same for aRowBGData in PaintRow. + * See Public versions for function descriptions + */ + DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame, + TableBackgroundData aRowGroupBGData, + bool aPassThrough); + + DrawResult PaintRow(nsTableRowFrame* aFrame, + const TableBackgroundData& aRowGroupBGData, + TableBackgroundData aRowBGData, + bool aPassThrough); + + /** Paint table background layers for this cell space + * Also paints cell's own background in border-collapse mode + * @param aCell - the cell + * @param aRowGroupBGData - background drawing info for the row group + * @param aRowBGData - background drawing info for the row + * @param aCellBGRect - background rect for the cell + * @param aRowBGRect - background rect for the row + * @param aRowGroupBGRect - background rect for the row group + * @param aColBGRect - background rect for the column and column group + * @param aPassSelf - pass this cell; i.e. paint only underlying layers + */ + DrawResult PaintCell(nsTableCellFrame* aCell, + const TableBackgroundData& aRowGroupBGData, + const TableBackgroundData& aRowBGData, + nsRect& aCellBGRect, + nsRect& aRowBGRect, + nsRect& aRowGroupBGRect, + nsRect& aColBGRect, + bool aPassSelf); + + /** Compute table background layer positions for this cell space + * @param aCell - the cell + * @param aRowGroupBGData - background drawing info for the row group + * @param aRowBGData - background drawing info for the row + * @param aCellBGRectOut - outparam: background rect for the cell + * @param aRowBGRectOut - outparam: background rect for the row + * @param aRowGroupBGRectOut - outparam: background rect for the row group + * @param aColBGRectOut - outparam: background rect for the column + and column group + */ + void ComputeCellBackgrounds(nsTableCellFrame* aCell, + const TableBackgroundData& aRowGroupBGData, + const TableBackgroundData& aRowBGData, + nsRect& aCellBGRect, + nsRect& aRowBGRect, + nsRect& aRowGroupBGRect, + nsRect& aColBGRect); + + /** Translate mRenderingContext, mDirtyRect, and mCols' column and + * colgroup coords + * @param aDX - origin's x-coord change + * @param aDY - origin's y-coord change + */ + void TranslateContext(nscoord aDX, + nscoord aDY); + + struct TableBackgroundData { + public: + /** + * Construct an empty TableBackgroundData instance, which is invisible. + */ + TableBackgroundData(); + + /** + * Construct a TableBackgroundData instance for a frame. Visibility will + * be derived from the frame and can be overridden using MakeInvisible(). + */ + explicit TableBackgroundData(nsIFrame* aFrame); + + /** Destructor */ + ~TableBackgroundData() {} + + /** Data is valid & frame is visible */ + bool IsVisible() const { return mVisible; } + + /** Override visibility of the frame, force it to be invisible */ + void MakeInvisible() { mVisible = false; } + + /** True if need to set border-collapse border; must call SetFull beforehand */ + bool ShouldSetBCBorder() const; + + /** Set border-collapse border with aBorderWidth as widths */ + void SetBCBorder(const nsMargin& aBorderWidth); + + /** + * @param aZeroBorder An nsStyleBorder instance that has been initialized + * for the right nsPresContext, with all border widths + * set to zero and border styles set to solid. + * @return The nsStyleBorder that should be used for rendering + * this background. + */ + nsStyleBorder StyleBorder(const nsStyleBorder& aZeroBorder) const; + + nsIFrame* const mFrame; + + /** mRect is the rect of mFrame in the current coordinate system */ + nsRect mRect; + + private: + nsMargin mSynthBorderWidths; + bool mVisible; + bool mUsesSynthBorder; + }; + + struct ColData { + ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData); + TableBackgroundData mCol; + TableBackgroundData& mColGroup; // reference to col's parent colgroup's data, owned by TablePainter in mColGroups + }; + + nsPresContext* mPresContext; + nsRenderingContext& mRenderingContext; + nsPoint mRenderPt; + nsRect mDirtyRect; +#ifdef DEBUG + nsCompatibility mCompatMode; +#endif + bool mIsBorderCollapse; + Origin mOrigin; //user's table frame type + + nsTArray mColGroups; + nsTArray mCols; + size_t mNumCols; + + nsStyleBorder mZeroBorder; //cached zero-width border + uint32_t mBGPaintFlags; +}; + +#endif diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 9dead7481d1b..509c572e23ee 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -577,6 +577,45 @@ nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput) return GetInitialBSize(); } +/** + * We need a custom display item for table row backgrounds. This is only used + * when the table row is the root of a stacking context (e.g., has 'opacity'). + * Table row backgrounds can extend beyond the row frame bounds, when + * the row contains row-spanning cells. + */ +class nsDisplayTableRowBackground : public nsDisplayTableItem { +public: + nsDisplayTableRowBackground(nsDisplayListBuilder* aBuilder, + nsTableRowFrame* aFrame) : + nsDisplayTableItem(aBuilder, aFrame) { + MOZ_COUNT_CTOR(nsDisplayTableRowBackground); + } +#ifdef NS_BUILD_REFCNT_LOGGING + virtual ~nsDisplayTableRowBackground() { + MOZ_COUNT_DTOR(nsDisplayTableRowBackground); + } +#endif + + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) override; + NS_DISPLAY_DECL_NAME("TableRowBackground", TYPE_TABLE_ROW_BACKGROUND) +}; + +void +nsDisplayTableRowBackground::Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) +{ + auto rowFrame = static_cast(mFrame); + TableBackgroundPainter painter(rowFrame->GetTableFrame(), + TableBackgroundPainter::eOrigin_TableRow, + mFrame->PresContext(), *aCtx, + mVisibleRect, ToReferenceFrame(), + aBuilder->GetBackgroundPaintFlags()); + + DrawResult result = painter.PaintRow(rowFrame); + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); +} + void nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index 6259271ffb05..63f27f2d5016 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -8,6 +8,7 @@ #include "mozilla/Attributes.h" #include "nscore.h" #include "nsContainerFrame.h" +#include "nsTablePainter.h" #include "nsTableRowGroupFrame.h" #include "mozilla/WritingModes.h" diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index b1482da82c88..9d0b575c59db 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -198,6 +198,46 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame return NS_OK; } +/** + * We need a custom display item for table row backgrounds. This is only used + * when the table row is the root of a stacking context (e.g., has 'opacity'). + * Table row backgrounds can extend beyond the row frame bounds, when + * the row contains row-spanning cells. + */ +class nsDisplayTableRowGroupBackground : public nsDisplayTableItem { +public: + nsDisplayTableRowGroupBackground(nsDisplayListBuilder* aBuilder, + nsTableRowGroupFrame* aFrame) : + nsDisplayTableItem(aBuilder, aFrame) { + MOZ_COUNT_CTOR(nsDisplayTableRowGroupBackground); + } +#ifdef NS_BUILD_REFCNT_LOGGING + virtual ~nsDisplayTableRowGroupBackground() { + MOZ_COUNT_DTOR(nsDisplayTableRowGroupBackground); + } +#endif + + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) override; + + NS_DISPLAY_DECL_NAME("TableRowGroupBackground", TYPE_TABLE_ROW_GROUP_BACKGROUND) +}; + +void +nsDisplayTableRowGroupBackground::Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) +{ + auto rgFrame = static_cast(mFrame); + TableBackgroundPainter painter(rgFrame->GetTableFrame(), + TableBackgroundPainter::eOrigin_TableRowGroup, + mFrame->PresContext(), *aCtx, + mVisibleRect, ToReferenceFrame(), + aBuilder->GetBackgroundPaintFlags()); + + DrawResult result = painter.PaintRowGroup(rgFrame); + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); +} + // Handle the child-traversal part of DisplayGenericTablePart static void DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index 66098d2ba024..477c71629290 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -10,6 +10,7 @@ #include "nsContainerFrame.h" #include "nsIAtom.h" #include "nsILineIterator.h" +#include "nsTablePainter.h" #include "nsTArray.h" #include "nsTableFrame.h" #include "mozilla/WritingModes.h"