diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 6caabf4bb9db..ba6b022ae2e1 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -862,6 +862,28 @@ public: } } + /** + * An alternative default implementation of ComputeInvalidationRegion, + * that instead invalidates only the changed area between the two items. + */ + void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder, + const nsDisplayItemBoundsGeometry* aGeometry, + nsRegion* aInvalidRegion) + { + bool snap; + nsRect bounds = GetBounds(aBuilder, &snap); + + if (!aGeometry->mBounds.IsEqualInterior(bounds)) { + nscoord radii[8]; + if (aGeometry->mHasRoundedCorners || + GetUnderlyingFrame()->GetBorderRadii(radii)) { + aInvalidRegion->Or(aGeometry->mBounds, bounds); + } else { + aInvalidRegion->Xor(aGeometry->mBounds, bounds); + } + } + } + /** * Called when the area rendered by this display item has changed (been * invalidated or changed geometry) since the last paint. This includes @@ -1815,6 +1837,19 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE + { + return new nsDisplayItemBoundsGeometry(this, aBuilder); + } + + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion* aInvalidRegion) + { + const nsDisplayItemBoundsGeometry* geometry = static_cast(aGeometry); + ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion); + } + NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR) private: @@ -1965,6 +2000,19 @@ public: return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize()); } + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE + { + return new nsDisplayItemBoundsGeometry(this, aBuilder); + } + + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion* aInvalidRegion) + { + const nsDisplayItemBoundsGeometry* geometry = static_cast(aGeometry); + ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion); + } + NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR) #ifdef MOZ_DUMP_PAINTING virtual void WriteDebugInfo(FILE *aOutput) { diff --git a/layout/base/nsDisplayListInvalidation.cpp b/layout/base/nsDisplayListInvalidation.cpp index 0ced943c0d4a..6d0c84e656c3 100644 --- a/layout/base/nsDisplayListInvalidation.cpp +++ b/layout/base/nsDisplayListInvalidation.cpp @@ -30,6 +30,19 @@ nsDisplayItemGenericGeometry::MoveBy(const nsPoint& aOffset) mBorderRect.MoveBy(aOffset); } +nsDisplayItemBoundsGeometry::nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder) + : nsDisplayItemGeometry(aItem, aBuilder) +{ + nscoord radii[8]; + mHasRoundedCorners = aItem->GetUnderlyingFrame()->GetBorderRadii(radii); +} + +void +nsDisplayItemBoundsGeometry::MoveBy(const nsPoint& aOffset) +{ + mBounds.MoveBy(aOffset); +} + nsDisplayBorderGeometry::nsDisplayBorderGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder) : nsDisplayItemGeometry(aItem, aBuilder) , mContentRect(aItem->GetContentRect()) diff --git a/layout/base/nsDisplayListInvalidation.h b/layout/base/nsDisplayListInvalidation.h index 9960e1e452e6..8c1cf3a94869 100644 --- a/layout/base/nsDisplayListInvalidation.h +++ b/layout/base/nsDisplayListInvalidation.h @@ -63,6 +63,16 @@ public: nsRect mBorderRect; }; +class nsDisplayItemBoundsGeometry : public nsDisplayItemGeometry +{ +public: + nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder); + + virtual void MoveBy(const nsPoint& aOffset); + + bool mHasRoundedCorners; +}; + class nsDisplayBorderGeometry : public nsDisplayItemGeometry { public: diff --git a/layout/generic/nsCanvasFrame.h b/layout/generic/nsCanvasFrame.h index 95c17da0bc97..622d1e6b46f7 100644 --- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -159,6 +159,20 @@ public: // We need to override so we don't consider border-radius. aOutFrames->AppendElement(mFrame); } + + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE + { + return new nsDisplayItemBoundsGeometry(this, aBuilder); + } + + virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, + const nsDisplayItemGeometry* aGeometry, + nsRegion* aInvalidRegion) + { + const nsDisplayItemBoundsGeometry* geometry = static_cast(aGeometry); + ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion); + } + virtual void NotifyRenderingChanged() MOZ_OVERRIDE { mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage());