Bug 1362000 - Part 1. nsDisplayMask is invalid if the resource frame(nsSVGMaskFrame/ nsSVGClipPathFrame) is invalid.
This bug is becasue we keep using an invalid mask layer. There are two way to fix
it:
1. Create a nsSVGRenderingObserver to receive mask/clip-path content change, and
invalid masked/clipped frame. CSS filter uses this approach(please refers to
nsSVGRenderingObserve in nsSVGEffects.cpp).
2. Overwrite nsDisplayMask::IsInvalid. This approach is better than the first one
since we will not repaint masked/clipped frame but only regenerate mask-layer.
MozReview-Commit-ID: 6LwqcM84G0o
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8416,16 +8416,41 @@ nsDisplayMask::PaintMask(nsDisplayListBu
mHandleOpacity, flags);
ComputeMaskGeometry(params);
image::DrawResult result = nsSVGIntegrationUtils::PaintMask(params);
nsDisplayMaskGeometry::UpdateDrawResult(this, result);
return (result == image::DrawResult::SUCCESS) ? true : false;
}
+bool
+nsDisplayMask::IsInvalid(nsRect& aRect)
+{
+ nsIFrame* firstFrame =
+ nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
+ nsSVGEffects::EffectProperties effectProperties =
+ nsSVGEffects::GetEffectProperties(firstFrame);
+
+ // Check whether all SVG masks are valid.
+ nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
+ for (uint32_t i = 0; i < maskFrames.Length(); i++) {
+ if (maskFrames[i] && !maskFrames[i]->IsInvalid(aRect)) {
+ return true;
+ }
+ }
+
+ // Check whether clip-path is valid.
+ nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
+ if (clipPathFrame && !clipPathFrame->IsInvalid(aRect)) {
+ return true;
+ }
+
+ return nsDisplaySVGEffects::IsInvalid(aRect);
+}
+
LayerState
nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
if (ShouldPaintOnMaskLayer(aManager)) {
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters,
mList, GetAnimatedGeometryRoot());
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -4409,16 +4409,19 @@ public:
* Paint mask onto aMaskContext in mFrame's coordinate space.
*/
bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
const nsTArray<nsRect>& GetDestRects()
{
return mDestRects;
}
+
+ virtual bool IsInvalid(nsRect& aRect) override;
+
private:
// According to mask property and the capability of aManager, determine
// whether paint mask onto a dedicate mask layer.
bool ShouldPaintOnMaskLayer(LayerManager* aManager);
nsTArray<nsRect> mDestRects;
};