Bug 1323912 - Part 4. Apply opacity in indirect image mask painting path.
MozReview-Commit-ID: IKKKMccyMsO
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -415,46 +415,31 @@ public:
}
private:
nsDisplayListBuilder* mBuilder;
LayerManager* mLayerManager;
nsPoint mOffset;
};
-/**
- * Returns true if any of the masks is an image mask (and not an SVG mask).
- */
-static bool
-HasNonSVGMask(const nsTArray<nsSVGMaskFrame*>& aMaskFrames)
-{
- for (size_t i = 0; i < aMaskFrames.Length() ; i++) {
- nsSVGMaskFrame *maskFrame = aMaskFrames[i];
- if (!maskFrame) {
- return true;
- }
- }
-
- return false;
-}
-
typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
/**
* Paint css-positioned-mask onto a given target(aMaskDT).
*/
static DrawResult
PaintMaskSurface(const PaintFramesParams& aParams,
DrawTarget* aMaskDT, float aOpacity, nsStyleContext* aSC,
const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
const gfxMatrix& aMaskSurfaceMatrix,
const nsPoint& aOffsetToUserSpace)
{
MOZ_ASSERT(aMaskFrames.Length() > 0);
MOZ_ASSERT(aMaskDT->GetFormat() == SurfaceFormat::A8);
+ MOZ_ASSERT(aOpacity == 1.0 || aMaskFrames.Length() == 1);
const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
gfxMatrix cssPxToDevPxMatrix =
nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);
nsPresContext* presContext = aParams.frame->PresContext();
gfxPoint devPixelOffsetToUserSpace =
nsLayoutUtils::PointToGfxPoint(aOffsetToUserSpace,
@@ -504,17 +489,18 @@ PaintMaskSurface(const PaintFramesParams
nsRenderingContext rc(maskContext);
nsCSSRendering::PaintBGParams params =
nsCSSRendering::PaintBGParams::ForSingleLayer(*presContext,
rc, aParams.dirtyRect,
aParams.borderArea,
aParams.frame,
aParams.builder->GetBackgroundPaintFlags() |
nsCSSRendering::PAINTBG_MASK_IMAGE,
- i, compositionOp);
+ i, compositionOp,
+ aOpacity);
result =
nsCSSRendering::PaintStyleImageLayerWithSC(params, aSC,
*aParams.frame->StyleBorder());
if (result != DrawResult::SUCCESS) {
return result;
}
}
@@ -575,20 +561,21 @@ CreateAndPaintMaskSurface(const PaintFra
RefPtr<DrawTarget> maskDT =
ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
SurfaceFormat::A8);
if (!maskDT || !maskDT->IsValid()) {
paintResult.result = DrawResult::TEMPORARY_ERROR;
return paintResult;
}
- // Set aAppliedOpacity as true only if all mask layers are svg mask.
- // In this case, we will apply opacity into the final mask surface, so the
- // caller does not need to apply it again.
- paintResult.opacityApplied = !HasNonSVGMask(aMaskFrames);
+ // We can paint mask along with opacity only if
+ // 1. There is only one mask, or
+ // 2. No overlap among masks.
+ // Collision detect in #2 is not that trivial, we only accept #1 here.
+ paintResult.opacityApplied = (aMaskFrames.Length() == 1);
// Set context's matrix on maskContext, offset by the maskSurfaceRect's
// position. This makes sure that we combine the masks in device space.
gfxMatrix maskSurfaceMatrix =
ctx.CurrentMatrix() * gfxMatrix::Translation(-aParams.maskRect.TopLeft());
paintResult.result = PaintMaskSurface(aParams, maskDT,
paintResult.opacityApplied