Bug 1329091 - Keep mask style value to determine whether cached mask layer is corrupt.
MozReview-Commit-ID: J2CFFi5pN7H
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -1571,54 +1571,49 @@ struct MaskLayerUserData : public LayerU
};
/*
* User data for layers which will be used as masks for css positioned mask.
*/
struct CSSMaskLayerUserData : public LayerUserData
{
CSSMaskLayerUserData()
- : mFrame(nullptr)
+ : mMaskStyle(nsStyleImageLayers::LayerType::Mask)
{ }
CSSMaskLayerUserData(nsIFrame* aFrame, const nsIntSize& aMaskSize)
- : mFrame(aFrame),
- mMaskSize(aMaskSize)
- { }
-
- CSSMaskLayerUserData& operator=(const CSSMaskLayerUserData& aOther)
+ : mMaskSize(aMaskSize),
+ mMaskStyle(aFrame->StyleSVGReset()->mMask)
{
- mFrame = aOther.mFrame;
+ }
+
+ void operator=(CSSMaskLayerUserData&& aOther)
+ {
mMaskSize = aOther.mMaskSize;
-
- return *this;
+ mMaskStyle = Move(aOther.mMaskStyle);
}
bool
operator==(const CSSMaskLayerUserData& aOther) const
{
- if (mFrame != aOther.mFrame) {
- return false;
- }
-
// Even if the frame is valid, check the size of the display item's
// boundary is still necessary. For example, if we scale the masked frame
// by adding a transform property on it, the masked frame is valid itself
// but we have to regenerate mask according to the new size in device
// space.
if (mMaskSize != aOther.mMaskSize) {
return false;
}
- return true;
+ return mMaskStyle == aOther.mMaskStyle;
}
private:
- nsIFrame* mFrame;
nsIntSize mMaskSize;
+ nsStyleImageLayers mMaskStyle;
};
/*
* A helper object to create a draw target for painting mask and create a
* image container to hold the drawing result. The caller can then bind this
* image container with a image mask layer via ImageLayer::SetContainer.
*/
class MaskImageData
@@ -3928,17 +3923,17 @@ ContainerState::SetupMaskLayerForCSSMask
RefPtr<ImageContainer> imgContainer =
imageData.CreateImageAndImageContainer();
if (!imgContainer) {
return;
}
maskLayer->SetContainer(imgContainer);
- *oldUserData = newUserData;
+ *oldUserData = Move(newUserData);
aLayer->SetMaskLayer(maskLayer);
}
/*
* Iterate through the non-clip items in aList and its descendants.
* For each item we compute the effective clip rect. Each item is assigned
* to a layer. We invalidate the areas in PaintedLayers where an item
* has moved from one PaintedLayer to another. Also,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2598,16 +2598,89 @@ nsStyleImageLayers::operator=(const nsSt
mMaskModeCount = std::max(mMaskModeCount, count);
mBlendModeCount = std::max(mBlendModeCount, count);
mCompositeCount = std::max(mCompositeCount, count);
}
return *this;
}
+nsStyleImageLayers&
+nsStyleImageLayers::operator=(nsStyleImageLayers&& aOther)
+{
+ mAttachmentCount = aOther.mAttachmentCount;
+ mClipCount = aOther.mClipCount;
+ mOriginCount = aOther.mOriginCount;
+ mRepeatCount = aOther.mRepeatCount;
+ mPositionXCount = aOther.mPositionXCount;
+ mPositionYCount = aOther.mPositionYCount;
+ mImageCount = aOther.mImageCount;
+ mSizeCount = aOther.mSizeCount;
+ mMaskModeCount = aOther.mMaskModeCount;
+ mBlendModeCount = aOther.mBlendModeCount;
+ mCompositeCount = aOther.mCompositeCount;
+ mLayers = Move(aOther.mLayers);
+
+ uint32_t count = mLayers.Length();
+ if (count != aOther.mLayers.Length()) {
+ NS_WARNING("truncating counts due to out-of-memory");
+ mAttachmentCount = std::max(mAttachmentCount, count);
+ mClipCount = std::max(mClipCount, count);
+ mOriginCount = std::max(mOriginCount, count);
+ mRepeatCount = std::max(mRepeatCount, count);
+ mPositionXCount = std::max(mPositionXCount, count);
+ mPositionYCount = std::max(mPositionYCount, count);
+ mImageCount = std::max(mImageCount, count);
+ mSizeCount = std::max(mSizeCount, count);
+ mMaskModeCount = std::max(mMaskModeCount, count);
+ mBlendModeCount = std::max(mBlendModeCount, count);
+ mCompositeCount = std::max(mCompositeCount, count);
+ }
+
+ return *this;
+}
+
+bool nsStyleImageLayers::operator==(const nsStyleImageLayers& aOther) const
+{
+ if (mAttachmentCount != aOther.mAttachmentCount ||
+ mClipCount != aOther.mClipCount ||
+ mOriginCount != aOther.mOriginCount ||
+ mRepeatCount != aOther.mRepeatCount ||
+ mPositionXCount != aOther.mPositionXCount ||
+ mPositionYCount != aOther.mPositionYCount ||
+ mImageCount != aOther.mImageCount ||
+ mSizeCount != aOther.mSizeCount ||
+ mMaskModeCount != aOther.mMaskModeCount ||
+ mBlendModeCount != aOther.mBlendModeCount) {
+ return false;
+ }
+
+ if (mLayers.Length() != aOther.mLayers.Length()) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < mLayers.Length(); i++) {
+ if (mLayers[i].mPosition != aOther.mLayers[i].mPosition ||
+ !DefinitelyEqualURIs(mLayers[i].mSourceURI, aOther.mLayers[i].mSourceURI) ||
+ mLayers[i].mImage != aOther.mLayers[i].mImage ||
+ mLayers[i].mSize != aOther.mLayers[i].mSize ||
+ mLayers[i].mClip != aOther.mLayers[i].mClip ||
+ mLayers[i].mOrigin != aOther.mLayers[i].mOrigin ||
+ mLayers[i].mAttachment != aOther.mLayers[i].mAttachment ||
+ mLayers[i].mBlendMode != aOther.mLayers[i].mBlendMode ||
+ mLayers[i].mComposite != aOther.mLayers[i].mComposite ||
+ mLayers[i].mMaskMode != aOther.mLayers[i].mMaskMode ||
+ mLayers[i].mRepeat != aOther.mLayers[i].mRepeat) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool
nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition, LayerType aType)
{
if (aPosition.mXPosition.mPercent == 0.0f &&
aPosition.mXPosition.mLength == 0 &&
aPosition.mXPosition.mHasPercent &&
aPosition.mYPosition.mPercent == 0.0f &&
aPosition.mYPosition.mLength == 0 &&
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -620,16 +620,23 @@ public:
return Length() == aOther.Length() &&
mFirstElement == aOther.mFirstElement &&
mOtherElements == aOther.mOtherElements;
}
bool operator!=(const nsStyleAutoArray& aOther) const {
return !(*this == aOther);
}
+ nsStyleAutoArray& operator=(nsStyleAutoArray&& aOther) {
+ mFirstElement = aOther.mFirstElement;
+ mOtherElements.SwapElements(aOther.mOtherElements);
+
+ return *this;
+ }
+
size_t Length() const {
return mOtherElements.Length() + 1;
}
const T& operator[](size_t aIndex) const {
return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
}
T& operator[](size_t aIndex) {
return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
@@ -894,16 +901,18 @@ struct nsStyleImageLayers {
}
}
nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
nsStyleImageLayers::LayerType aType) const;
bool HasLayerWithImage() const;
nsStyleImageLayers& operator=(const nsStyleImageLayers& aOther);
+ nsStyleImageLayers& operator=(nsStyleImageLayers&& aOther);
+ bool operator==(const nsStyleImageLayers& aOther) const;
static const nsCSSPropertyID kBackgroundLayerTable[];
static const nsCSSPropertyID kMaskLayerTable[];
#define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
#define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < (layers_).mImageCount, "Invalid layer start!"); \