# HG changeset patch # User Robert O'Callahan # Date 1425466934 -46800 # Thu Mar 05 00:02:14 2015 +1300 # Node ID cc211536a13785aa9ea3d0959f6222aca148ce02 # Parent 9eae92906f5f0982279ad01e8f95211031920714 Bug 1082249. Invalidate background-attachment:fixed table-part backgrounds when scrolled. r=mattwoodrow diff --git a/layout/base/nsDisplayListInvalidation.cpp b/layout/base/nsDisplayListInvalidation.cpp --- a/layout/base/nsDisplayListInvalidation.cpp +++ b/layout/base/nsDisplayListInvalidation.cpp @@ -110,8 +110,16 @@ nsDisplaySVGEffectsGeometry::nsDisplaySV {} void nsDisplaySVGEffectsGeometry::MoveBy(const nsPoint& aOffset) { mBounds.MoveBy(aOffset); mFrameOffsetToReferenceFrame += aOffset; } + +nsDisplayTableItemGeometry::nsDisplayTableItemGeometry(nsDisplayTableItem* aItem, + nsDisplayListBuilder* aBuilder, + const nsPoint& aFrameOffsetToViewport) + : nsDisplayItemGenericGeometry(aItem, aBuilder) + , nsImageGeometryMixin(aItem, aBuilder) + , mFrameOffsetToViewport(aFrameOffsetToViewport) +{} diff --git a/layout/base/nsDisplayListInvalidation.h b/layout/base/nsDisplayListInvalidation.h --- a/layout/base/nsDisplayListInvalidation.h +++ b/layout/base/nsDisplayListInvalidation.h @@ -8,21 +8,22 @@ #include "mozilla/Attributes.h" #include "FrameLayerBuilder.h" #include "imgIContainer.h" #include "nsRect.h" #include "nsColor.h" #include "gfxRect.h" +class nsDisplayBackgroundImage; class nsDisplayItem; class nsDisplayListBuilder; -class nsDisplayBackgroundImage; +class nsDisplaySVGEffects; +class nsDisplayTableItem; class nsDisplayThemedBackground; -class nsDisplaySVGEffects; /** * This stores the geometry of an nsDisplayItem, and the area * that will be affected when painting the item. * * It is used to retain information about display items so they * can be compared against new display items in the next paint. */ @@ -242,9 +243,21 @@ public: virtual void MoveBy(const nsPoint& aOffset) MOZ_OVERRIDE; gfxRect mBBox; gfxPoint mUserSpaceOffset; nsPoint mFrameOffsetToReferenceFrame; }; +class nsDisplayTableItemGeometry + : public nsDisplayItemGenericGeometry + , public nsImageGeometryMixin +{ +public: + nsDisplayTableItemGeometry(nsDisplayTableItem* aItem, + nsDisplayListBuilder* aBuilder, + const nsPoint& aFrameOffsetToViewport); + + nsPoint mFrameOffsetToViewport; +}; + #endif /*NSDISPLAYLISTINVALIDATION_H_*/ diff --git a/layout/generic/nsFrameStateBits.h b/layout/generic/nsFrameStateBits.h --- a/layout/generic/nsFrameStateBits.h +++ b/layout/generic/nsFrameStateBits.h @@ -590,16 +590,19 @@ FRAME_STATE_BIT(TableRow, 30, NS_TABLE_R FRAME_STATE_GROUP(TableRowGroup, nsTableRowGroupFrame) FRAME_STATE_BIT(TableRowGroup, 27, NS_ROWGROUP_HAS_ROW_CURSOR) FRAME_STATE_BIT(TableRowGroup, 30, NS_ROWGROUP_HAS_STYLE_HEIGHT) // thead or tfoot should be repeated on every printed page FRAME_STATE_BIT(TableRowGroup, 31, NS_ROWGROUP_REPEATABLE) +FRAME_STATE_GROUP(Table, nsTableFrame) + +FRAME_STATE_BIT(Table, 28, NS_TABLE_PART_HAS_FIXED_BACKGROUND) #ifdef DEFINED_FRAME_STATE_GROUP #undef DEFINED_FRAME_STATE_GROUP #undef FRAME_STATE_GROUP #endif #ifdef DEFINED_FRAME_STATE_BIT #undef DEFINED_FRAME_STATE_BIT diff --git a/layout/reftests/scrolling/fixed-table-1.html b/layout/reftests/scrolling/fixed-table-1.html new file mode 100644 --- /dev/null +++ b/layout/reftests/scrolling/fixed-table-1.html @@ -0,0 +1,48 @@ + + + + + +

+
  +
+ +
  +
+ +
  +
+ +
  +
+

+ +
  +
+ + +
  +
+ + +
  +
 
+ +

+
  +
+ +
  +
+ +
  +
+

+ +
  +
 
+ + diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list --- a/layout/reftests/scrolling/reftest.list +++ b/layout/reftests/scrolling/reftest.list @@ -1,11 +1,12 @@ skip-if(B2G&&browserIsRemote) HTTP == deferred-anchor.xhtml#d deferred-anchor-ref.xhtml#d == deferred-anchor2.xhtml deferred-anchor-ref.xhtml#d HTTP == fixed-1.html fixed-1.html?ref +HTTP == fixed-table-1.html fixed-table-1.html?ref HTTP == fixed-opacity-1.html fixed-opacity-1.html?ref skip-if(B2G) HTTP == fixed-opacity-2.html fixed-opacity-2.html?ref skip-if(B2G) random-if(gtk2Widget) fuzzy-if(Android,3,60) HTTP == fixed-text-1.html fixed-text-1.html?ref HTTP == fixed-text-2.html fixed-text-2.html?ref random-if(Android&&!browserIsRemote) skip-if(B2G&&browserIsRemote) == iframe-border-radius.html iframe-border-radius-ref.html # bug 760269 random-if(Android) HTTP == image-1.html image-1.html?ref random-if(Android&&!browserIsRemote) HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref # bug 760269 skip-if(B2G) random-if(cocoaWidget) HTTP == opacity-mixed-scrolling-2.html opacity-mixed-scrolling-2.html?ref # see bug 625357 diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -423,66 +423,38 @@ public: HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; - virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) MOZ_OVERRIDE; - NS_DISPLAY_DECL_NAME("TableCellBackground", TYPE_TABLE_CELL_BACKGROUND) }; void nsDisplayTableCellBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { DrawResult result = static_cast(mFrame)-> PaintBackground(*aCtx, mVisibleRect, ToReferenceFrame(), aBuilder->GetBackgroundPaintFlags()); - nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result); + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); } nsRect nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { // revert from nsDisplayTableItem's implementation ... cell backgrounds // don't overflow the cell return nsDisplayItem::GetBounds(aBuilder, aSnap); } -nsDisplayItemGeometry* -nsDisplayTableCellBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder) -{ - return new nsDisplayItemGenericImageGeometry(this, aBuilder); -} - -void -nsDisplayTableCellBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) -{ - auto geometry = - static_cast(aGeometry); - - if (aBuilder->ShouldSyncDecodeImages() && - geometry->ShouldInvalidateToSyncDecodeImages()) { - bool snap; - aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap)); - } - - nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); -} - void nsTableCellFrame::InvalidateFrame(uint32_t aDisplayItemKey) { nsIFrame::InvalidateFrame(aDisplayItemKey); GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey); } void nsTableCellFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey) { diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1078,45 +1078,74 @@ nsTableFrame::GetChildLists(nsTArrayGetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); } -/* static */ void +void nsDisplayTableItem::UpdateForFrameBackground(nsIFrame* aFrame) { nsStyleContext *bgSC; if (!nsCSSRendering::FindBackground(aFrame, &bgSC)) return; if (!bgSC->StyleBackground()->HasFixedBackground()) return; mPartHasFixedBackground = true; } +nsDisplayItemGeometry* +nsDisplayTableItem::AllocateGeometry(nsDisplayListBuilder* aBuilder) +{ + return new nsDisplayTableItemGeometry(this, aBuilder, + mFrame->GetOffsetTo(mFrame->PresContext()->PresShell()->GetRootFrame())); +} + +void +nsDisplayTableItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) +{ + auto geometry = + static_cast(aGeometry); + + bool invalidateForAttachmentFixed = false; + if (mPartHasFixedBackground) { + nsPoint frameOffsetToViewport = mFrame->GetOffsetTo( + mFrame->PresContext()->PresShell()->GetRootFrame()); + invalidateForAttachmentFixed = + frameOffsetToViewport != geometry->mFrameOffsetToViewport; + } + + if (invalidateForAttachmentFixed || + (aBuilder->ShouldSyncDecodeImages() && + geometry->ShouldInvalidateToSyncDecodeImages())) { + bool snap; + aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap)); + } + + nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); +} + class nsDisplayTableBorderBackground : public nsDisplayTableItem { public: nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder, nsTableFrame* aFrame) : nsDisplayTableItem(aBuilder, aFrame) { MOZ_COUNT_CTOR(nsDisplayTableBorderBackground); } #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayTableBorderBackground() { MOZ_COUNT_DTOR(nsDisplayTableBorderBackground); } #endif - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; - virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND) }; #ifdef DEBUG static bool IsFrameAllowedInTable(nsIAtom* aType) @@ -1126,49 +1155,26 @@ IsFrameAllowedInTable(nsIAtom* aType) nsGkAtoms::tableRowGroupFrame == aType || nsGkAtoms::scrollFrame == aType || nsGkAtoms::tableFrame == aType || nsGkAtoms::tableColFrame == aType || nsGkAtoms::tableColGroupFrame == aType; } #endif -nsDisplayItemGeometry* -nsDisplayTableBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder) -{ - return new nsDisplayItemGenericImageGeometry(this, aBuilder); -} - -void -nsDisplayTableBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) -{ - auto geometry = - static_cast(aGeometry); - - if (aBuilder->ShouldSyncDecodeImages() && - geometry->ShouldInvalidateToSyncDecodeImages()) { - bool snap; - aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap)); - } - - nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); -} - void nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { DrawResult result = static_cast(mFrame)-> PaintTableBorderBackground(*aCtx, mVisibleRect, ToReferenceFrame(), aBuilder->GetBackgroundPaintFlags()); - nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result); + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); } static int32_t GetTablePartRank(nsDisplayItem* aItem) { nsIAtom* type = aItem->Frame()->GetType(); if (type == nsGkAtoms::tableFrame) return 0; if (type == nsGkAtoms::tableRowGroupFrame) @@ -1281,16 +1287,29 @@ AnyTablePartHasBorderOrBackground(nsIFra if (AnyTablePartHasBorderOrBackground(f->PrincipalChildList().FirstChild(), nullptr)) return true; } return false; } +static void +UpdateItemForColGroupBackgrounds(nsDisplayTableItem* item, + const nsFrameList& aFrames) { + for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) { + nsTableColGroupFrame* cg = static_cast(e.get()); + item->UpdateForFrameBackground(cg); + for (nsTableColFrame* colFrame = cg->GetFirstColumn(); colFrame; + colFrame = colFrame->GetNextCol()) { + item->UpdateForFrameBackground(colFrame); + } + } +} + // table paint code is concerned primarily with borders and bg color // SEC: TODO: adjust the rect for captions void nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255)); @@ -1315,16 +1334,19 @@ nsTableFrame::BuildDisplayList(nsDisplay if (aBuilder->IsForEventDelivery() || AnyTablePartHasBorderOrBackground(this, GetNextSibling()) || AnyTablePartHasBorderOrBackground(mColGroups.FirstChild(), nullptr)) { item = new (aBuilder) nsDisplayTableBorderBackground(aBuilder, this); aLists.BorderBackground()->AppendNewToTop(item); } } DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item); + if (item) { + UpdateItemForColGroupBackgrounds(item, mColGroups); + } } nsMargin nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const { if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode() || !IsBorderCollapse()) return nsMargin(0,0,0,0); diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -52,16 +52,21 @@ public: mPartHasFixedBackground(false) {} // With collapsed borders, parts of the collapsed border can extend outside // the table part frames, so allow this display element to blow out to our // overflow rect. This is also useful for row frames that have spanning // cells extending outside them. virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion *aInvalidRegion) MOZ_OVERRIDE; + void UpdateForFrameBackground(nsIFrame* aFrame); private: bool mPartHasFixedBackground; }; class nsAutoPushCurrentTableItem { @@ -105,16 +110,17 @@ private: * The principal child list contains row group frames. There is also an * additional child list, kColGroupList, which contains the col group frames. */ class nsTableFrame : public nsContainerFrame { typedef mozilla::image::DrawResult DrawResult; public: + NS_DECL_QUERYFRAME_TARGET(nsTableFrame) NS_DECL_FRAMEARENA_HELPERS NS_DECLARE_FRAME_PROPERTY(PositionedTablePartArray, DeleteValue>) /** nsTableOuterFrame has intimate knowledge of the inner table frame */ friend class nsTableOuterFrame; diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -530,63 +530,36 @@ public: MOZ_COUNT_CTOR(nsDisplayTableRowBackground); } #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayTableRowBackground() { MOZ_COUNT_DTOR(nsDisplayTableRowBackground); } #endif - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; - virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("TableRowBackground", TYPE_TABLE_ROW_BACKGROUND) }; -nsDisplayItemGeometry* -nsDisplayTableRowBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder) -{ - return new nsDisplayItemGenericImageGeometry(this, aBuilder); -} - -void -nsDisplayTableRowBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) -{ - auto geometry = - static_cast(aGeometry); - - if (aBuilder->ShouldSyncDecodeImages() && - geometry->ShouldInvalidateToSyncDecodeImages()) { - bool snap; - aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap)); - } - - nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); -} - void nsDisplayTableRowBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(mFrame); TableBackgroundPainter painter(tableFrame, TableBackgroundPainter::eOrigin_TableRow, mFrame->PresContext(), *aCtx, mVisibleRect, ToReferenceFrame(), aBuilder->GetBackgroundPaintFlags()); DrawResult result = painter.PaintRow(static_cast(mFrame)); - nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result); + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); } void nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nsDisplayTableItem* item = nullptr; diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -142,64 +142,37 @@ public: MOZ_COUNT_CTOR(nsDisplayTableRowGroupBackground); } #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayTableRowGroupBackground() { MOZ_COUNT_DTOR(nsDisplayTableRowGroupBackground); } #endif - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; - virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("TableRowGroupBackground", TYPE_TABLE_ROW_GROUP_BACKGROUND) }; -nsDisplayItemGeometry* -nsDisplayTableRowGroupBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder) -{ - return new nsDisplayItemGenericImageGeometry(this, aBuilder); -} - -void -nsDisplayTableRowGroupBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, - const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) -{ - auto geometry = - static_cast(aGeometry); - - if (aBuilder->ShouldSyncDecodeImages() && - geometry->ShouldInvalidateToSyncDecodeImages()) { - bool snap; - aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap)); - } - - nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); -} - void nsDisplayTableRowGroupBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(mFrame); TableBackgroundPainter painter(tableFrame, TableBackgroundPainter::eOrigin_TableRowGroup, mFrame->PresContext(), *aCtx, mVisibleRect, ToReferenceFrame(), aBuilder->GetBackgroundPaintFlags()); DrawResult result = painter.PaintRowGroup(static_cast(mFrame)); - nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result); + nsDisplayTableItemGeometry::UpdateDrawResult(this, result); } // Handle the child-traversal part of DisplayGenericTablePart static void DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nscoord overflowAbove;