mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1461313 - Handle invalid clip-path URIs with WebRender. r=mstange
In the case of an invalid clip-path, the browser is supposed to discard the mask entirely. In the non-webrender codepath this would happen implicitly because the computed MaskUsage would have no flags set, and so no actions would be taken on the gfxContext which contained the display items rasterized so far. In the WebRender codepath, though, we invoke the code on a A8 drawtarget that's zero-filled, so if PaintMask fails to rasterize anything into it, it gets treated as a "mask everything out" mask. Instead, this patch makes it so that we detect the scenario where the computed MaskUsage is a no-op, and ensure that we don't apply the mask in that case. An alternative approach considered was to initialize the A8 drawtarget to white instead of black but in cases where there is an actual mask, the rest of the code assumes it is zero-filled and so that doesn't work. MozReview-Commit-ID: Hw7nCiUXVJl --HG-- extra : rebase_source : 241d550fa0ed1b3bd088c73d9565b166acbcece8
This commit is contained in:
parent
05d14001f5
commit
78dba184db
@ -1543,8 +1543,7 @@ PaintItemByDrawTarget(nsDisplayItem* aItem,
|
||||
switch (aItem->GetType()) {
|
||||
case DisplayItemType::TYPE_MASK:
|
||||
context->SetMatrix(context->CurrentMatrix().PreScale(aScale.width, aScale.height).PreTranslate(-aOffset.x, -aOffset.y));
|
||||
static_cast<nsDisplayMask*>(aItem)->PaintMask(aDisplayListBuilder, context);
|
||||
isInvalidated = true;
|
||||
static_cast<nsDisplayMask*>(aItem)->PaintMask(aDisplayListBuilder, context, &isInvalidated);
|
||||
break;
|
||||
case DisplayItemType::TYPE_SVG_WRAPPER:
|
||||
{
|
||||
|
4
gfx/tests/reftest/1461313-ref.html
Normal file
4
gfx/tests/reftest/1461313-ref.html
Normal file
@ -0,0 +1,4 @@
|
||||
<!doctype html>
|
||||
<body>
|
||||
<div style="background-color: green; width: 100px; height: 100px;"></div>
|
||||
</body>
|
9
gfx/tests/reftest/1461313.html
Normal file
9
gfx/tests/reftest/1461313.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!doctype html>
|
||||
<style>
|
||||
body {
|
||||
clip-path: url(non-existent-resource);
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div style="background-color: green; width: 100px; height: 100px;"></div>
|
||||
</body>
|
@ -14,3 +14,4 @@ fuzzy(100,30) == 1149923.html 1149923-ref.html # use fuzzy due to few distorted
|
||||
== 1444904.html 1444904-ref.html
|
||||
== 1451168.html 1451168-ref.html
|
||||
fuzzy(5-32,21908-26354) fuzzy-if(webrender,0-1,0-3) == 1463802.html 1463802-ref.html
|
||||
== 1461313.html 1461313-ref.html
|
||||
|
@ -9200,7 +9200,8 @@ nsDisplayMask::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
bool
|
||||
nsDisplayMask::PaintMask(nsDisplayListBuilder* aBuilder,
|
||||
gfxContext* aMaskContext)
|
||||
gfxContext* aMaskContext,
|
||||
bool* aMaskPainted)
|
||||
{
|
||||
MOZ_ASSERT(aMaskContext->GetDrawTarget()->GetFormat() == SurfaceFormat::A8);
|
||||
|
||||
@ -9214,7 +9215,10 @@ nsDisplayMask::PaintMask(nsDisplayListBuilder* aBuilder,
|
||||
nullptr,
|
||||
mHandleOpacity, imgParmas);
|
||||
ComputeMaskGeometry(params);
|
||||
nsSVGIntegrationUtils::PaintMask(params);
|
||||
bool painted = nsSVGIntegrationUtils::PaintMask(params);
|
||||
if (aMaskPainted) {
|
||||
*aMaskPainted = painted;
|
||||
}
|
||||
|
||||
nsDisplayMaskGeometry::UpdateDrawResult(this, imgParmas.result);
|
||||
|
||||
|
@ -6093,7 +6093,9 @@ public:
|
||||
* Paint mask onto aMaskContext in mFrame's coordinate space and
|
||||
* return whether the mask layer was painted successfully.
|
||||
*/
|
||||
bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
|
||||
bool PaintMask(nsDisplayListBuilder* aBuilder,
|
||||
gfxContext* aMaskContext,
|
||||
bool* aMaskPainted = nullptr);
|
||||
|
||||
const nsTArray<nsRect>& GetDestRects()
|
||||
{
|
||||
|
@ -593,7 +593,7 @@ CreateAndPaintMaskSurface(const PaintFramesParams& aParams,
|
||||
// For a SVG doc:
|
||||
// SVG 1.1 say that if we fail to resolve a mask, we should draw the
|
||||
// object unmasked.
|
||||
// Left patinResult.maskSurface empty, the caller should paint all
|
||||
// Left paintResult.maskSurface empty, the caller should paint all
|
||||
// masked content as if this mask is an opaque white one(no mask).
|
||||
paintResult.transparentBlackMask =
|
||||
!(aParams.frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
|
||||
@ -760,16 +760,19 @@ private:
|
||||
gfxContext* mContext;
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
||||
{
|
||||
nsSVGUtils::MaskUsage maskUsage;
|
||||
nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
|
||||
maskUsage);
|
||||
if (!maskUsage.shouldDoSomething()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIFrame* frame = aParams.frame;
|
||||
if (!ValidateSVGFrame(frame)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfxContext& ctx = aParams.ctx;
|
||||
@ -819,7 +822,7 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
||||
ctx.SetColor(Color(1.0, 1.0, 1.0, 1.0));
|
||||
ctx.Fill();
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -852,6 +855,8 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
||||
&clipMaskTransform, maskSurface,
|
||||
ctx.CurrentMatrix());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -168,9 +168,10 @@ public:
|
||||
|
||||
/**
|
||||
* Paint mask of non-SVG frame onto a given context, aParams.ctx.
|
||||
* aParams.ctx must contain an A8 surface.
|
||||
* aParams.ctx must contain an A8 surface. Returns false if the mask
|
||||
* didn't get painted and should be ignored at the call site.
|
||||
*/
|
||||
static void
|
||||
static bool
|
||||
PaintMask(const PaintFramesParams& aParams);
|
||||
|
||||
/**
|
||||
|
@ -613,6 +613,14 @@ public:
|
||||
: shouldGenerateMaskLayer(false), shouldGenerateClipMaskLayer(false),
|
||||
shouldApplyClipPath(false), shouldApplyBasicShape(false), opacity(0.0)
|
||||
{ }
|
||||
|
||||
bool shouldDoSomething() {
|
||||
return shouldGenerateMaskLayer
|
||||
|| shouldGenerateClipMaskLayer
|
||||
|| shouldApplyClipPath
|
||||
|| shouldApplyBasicShape
|
||||
|| opacity != 1.0;
|
||||
}
|
||||
};
|
||||
|
||||
static void DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
|
||||
|
Loading…
Reference in New Issue
Block a user