Bug 1309804 - Part 3. Use nsChangeHint_UpdateBackgroundPosition in position mask.
MozReview-Commit-ID: CeLPAN8OdhF
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -6911,16 +6911,31 @@ ComputeMaskGeometry(PaintFramesParams& a
nsDisplayMask::nsDisplayMask(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
bool aHandleOpacity,
const DisplayItemScrollClip* aScrollClip)
: nsDisplaySVGEffects(aBuilder, aFrame, aList, aHandleOpacity, aScrollClip)
{
MOZ_COUNT_CTOR(nsDisplayMask);
+
+ nsPresContext* presContext = mFrame->PresContext();
+ uint32_t flags = aBuilder->GetBackgroundPaintFlags() |
+ nsCSSRendering::PAINTBG_MASK_IMAGE;
+ const nsStyleSVGReset *svgReset = aFrame->StyleSVGReset();
+ NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
+ bool isTransformedFixed;
+ nsBackgroundLayerState state =
+ nsCSSRendering::PrepareImageLayer(presContext, aFrame, flags,
+ mFrame->GetRectRelativeToSelf(),
+ mFrame->GetRectRelativeToSelf(),
+ svgReset->mMask.mLayers[i],
+ &isTransformedFixed);
+ mDestRects.AppendElement(state.mDestArea);
+ }
}
#ifdef NS_BUILD_REFCNT_LOGGING
nsDisplayMask::~nsDisplayMask()
{
MOZ_COUNT_DTOR(nsDisplayMask);
}
#endif
@@ -7037,16 +7052,27 @@ nsDisplayMask::ComputeInvalidationRegion
// space and on the frame's BBox. We need to invalidate if either of these
// change relative to the reference frame.
// Invalidations from our inactive layer manager are not enough to catch
// some of these cases because filters can produce output even if there's
// nothing in the filter input.
aInvalidRegion->Or(bounds, geometry->mBounds);
}
+ if (mDestRects.Length() != geometry->mDestRects.Length()) {
+ aInvalidRegion->Or(bounds, geometry->mBounds);
+ } else {
+ for (size_t i = 0; i < mDestRects.Length(); i++) {
+ if (!mDestRects[i].IsEqualInterior(geometry->mDestRects[i])) {
+ aInvalidRegion->Or(bounds, geometry->mBounds);
+ break;
+ }
+ }
+ }
+
if (aBuilder->ShouldSyncDecodeImages() &&
geometry->ShouldInvalidateToSyncDecodeImages()) {
const nsStyleSVGReset *svgReset = mFrame->StyleSVGReset();
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
const nsStyleImage& image = svgReset->mMask.mLayers[i].mImage;
if (image.GetType() == eStyleImageType_Image ) {
aInvalidRegion->Or(*aInvalidRegion, bounds);
break;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -3904,16 +3904,23 @@ public:
nsRegion* aInvalidRegion) override;
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(nsACString& aTo);
#endif
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager);
+
+ const nsTArray<nsRect>& GetDestRects()
+ {
+ return mDestRects;
+ }
+private:
+ nsTArray<nsRect> mDestRects;
};
/**
* A display item to paint a stacking context with filter effects set by the
* stacking context root frame's style.
*/
class nsDisplayFilter : public nsDisplaySVGEffects {
public:
--- a/layout/base/nsDisplayListInvalidation.cpp
+++ b/layout/base/nsDisplayListInvalidation.cpp
@@ -114,16 +114,17 @@ nsDisplaySolidColorRegionGeometry::MoveB
}
nsDisplayMaskGeometry::nsDisplayMaskGeometry(nsDisplayMask* aItem, nsDisplayListBuilder* aBuilder)
: nsDisplayItemGeometry(aItem, aBuilder)
, nsImageGeometryMixin(aItem, aBuilder)
, mBBox(aItem->BBoxInUserSpace())
, mUserSpaceOffset(aItem->UserSpaceOffset())
, mFrameOffsetToReferenceFrame(aItem->ToReferenceFrame())
+ , mDestRects(aItem->GetDestRects())
{}
void
nsDisplayMaskGeometry::MoveBy(const nsPoint& aOffset)
{
mBounds.MoveBy(aOffset);
mFrameOffsetToReferenceFrame += aOffset;
}
--- a/layout/base/nsDisplayListInvalidation.h
+++ b/layout/base/nsDisplayListInvalidation.h
@@ -271,16 +271,18 @@ class nsDisplayMaskGeometry : public nsD
public:
nsDisplayMaskGeometry(nsDisplayMask* aItem, nsDisplayListBuilder* aBuilder);
virtual void MoveBy(const nsPoint& aOffset) override;
gfxRect mBBox;
gfxPoint mUserSpaceOffset;
nsPoint mFrameOffsetToReferenceFrame;
+
+ nsTArray<nsRect> mDestRects;
};
class nsCharClipGeometry : public nsDisplayItemGenericGeometry
{
public:
nsCharClipGeometry(nsCharClipDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
nscoord mVisIStartEdge;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2365,35 +2365,29 @@ nsStyleImageLayers::nsStyleImageLayers(c
mCompositeCount = std::max(mCompositeCount, count);
}
}
nsChangeHint
nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aNewLayers,
nsStyleImageLayers::LayerType aType) const
{
- nsChangeHint positionChangeHint =
- (aType == nsStyleImageLayers::LayerType::Background)
- ? nsChangeHint_UpdateBackgroundPosition
- : nsChangeHint_RepaintFrame;
-
nsChangeHint hint = nsChangeHint(0);
const nsStyleImageLayers& moreLayers =
mImageCount > aNewLayers.mImageCount ?
*this : aNewLayers;
const nsStyleImageLayers& lessLayers =
mImageCount > aNewLayers.mImageCount ?
aNewLayers : *this;
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
if (i < lessLayers.mImageCount) {
nsChangeHint layerDifference =
- moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i],
- positionChangeHint);
+ moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i]);
hint |= layerDifference;
if (layerDifference &&
((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
(lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}
} else {
hint |= nsChangeHint_RepaintFrame;
@@ -2671,18 +2665,17 @@ nsStyleImageLayers::Layer::operator==(co
mSize == aOther.mSize &&
mImage == aOther.mImage &&
mMaskMode == aOther.mMaskMode &&
mComposite == aOther.mComposite &&
DefinitelyEqualURIs(mSourceURI, aOther.mSourceURI);
}
nsChangeHint
-nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aNewLayer,
- nsChangeHint aPositionChangeHint) const
+nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aNewLayer) const
{
nsChangeHint hint = nsChangeHint(0);
if (!DefinitelyEqualURIs(mSourceURI, aNewLayer.mSourceURI)) {
hint |= nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects;
// If Layer::mSourceURI links to a SVG mask, it has a fragment. Not vice
// versa. Here are examples of URI contains a fragment, two of them link
// to a SVG mask:
@@ -2728,17 +2721,17 @@ nsStyleImageLayers::Layer::CalcDifferenc
mSize != aNewLayer.mSize ||
mImage != aNewLayer.mImage ||
mMaskMode != aNewLayer.mMaskMode ||
mComposite != aNewLayer.mComposite) {
hint |= nsChangeHint_RepaintFrame;
}
if (mPosition != aNewLayer.mPosition) {
- hint |= aPositionChangeHint;
+ hint |= nsChangeHint_UpdateBackgroundPosition;
}
return hint;
}
// --------------------
// nsStyleBackground
//
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -735,19 +735,17 @@ struct nsStyleImageLayers {
// True if the rendering of this layer might change when the size
// of the background positioning area changes. This is true for any
// non-solid-color background whose position or size depends on
// the size of the positioning area. It's also true for SVG images
// whose root <svg> node has a viewBox.
bool RenderingMightDependOnPositioningAreaSizeChange() const;
// Compute the change hint required by changes in just this layer.
- // aPositionChangeHint indicates the hint for position change.
- nsChangeHint CalcDifference(const Layer& aNewLayer,
- nsChangeHint aPositionChangeHint) const;
+ nsChangeHint CalcDifference(const Layer& aNewLayer) const;
// An equality operator that compares the images using URL-equality
// rather than pointer-equality.
bool operator==(const Layer& aOther) const;
bool operator!=(const Layer& aOther) const {
return !(*this == aOther);
}
};
@@ -3664,16 +3662,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
void Destroy(nsPresContext* aContext);
nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
static nsChangeHint MaxDifference() {
return nsChangeHint_UpdateEffects |
nsChangeHint_UpdateOverflow |
nsChangeHint_NeutralChange |
nsChangeHint_RepaintFrame |
+ nsChangeHint_UpdateBackgroundPosition |
NS_STYLE_HINT_REFLOW;
}
static nsChangeHint DifferenceAlwaysHandledForDescendants() {
// CalcDifference never returns the reflow hints that are sometimes
// handled for descendants as hints not handled for descendants.
return nsChangeHint_NeedReflow |
nsChangeHint_ReflowChangesSizeOrPosition |
nsChangeHint_ClearAncestorIntrinsics;