--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -3908,20 +3908,17 @@ ContainerState::SetupMaskLayerForCSSMask
NS_WARNING("Could not create DrawTarget for mask layer.");
return;
}
RefPtr<gfxContext> maskCtx = gfxContext::CreateOrNull(dt);
maskCtx->SetMatrix(gfxMatrix::Translation(-itemRect.TopLeft()));
maskCtx->Multiply(gfxMatrix::Scaling(mParameters.mXScale, mParameters.mYScale));
- if (!aMaskItem->PaintMask(mBuilder, maskCtx)) {
- // Mostly because of mask resource is not ready.
- return;
- }
+ aMaskItem->PaintMask(mBuilder, maskCtx);
RefPtr<ImageContainer> imgContainer =
imageData.CreateImageAndImageContainer();
if (!imgContainer) {
return;
}
maskLayer->SetContainer(imgContainer);
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8408,36 +8408,35 @@ nsDisplayMask::BuildLayer(nsDisplayListB
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
aContainerParameters, nullptr);
return container.forget();
}
-bool
+void
nsDisplayMask::PaintMask(nsDisplayListBuilder* aBuilder,
gfxContext* aMaskContext)
{
MOZ_ASSERT(aMaskContext->GetDrawTarget()->GetFormat() == SurfaceFormat::A8);
- uint32_t flags = aBuilder->ShouldSyncDecodeImages()
- ? imgIContainer::FLAG_SYNC_DECODE
- : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
+ imgDrawingParams imgParmas(aBuilder->ShouldSyncDecodeImages()
+ ? imgIContainer::FLAG_SYNC_DECODE
+ : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsSVGIntegrationUtils::PaintFramesParams params(*aMaskContext,
mFrame, mVisibleRect,
borderArea, aBuilder,
nullptr,
- mHandleOpacity, flags);
+ mHandleOpacity, imgParmas);
ComputeMaskGeometry(params);
- image::DrawResult result = nsSVGIntegrationUtils::PaintMask(params);
-
- nsDisplayMaskGeometry::UpdateDrawResult(this, result);
- return (result == image::DrawResult::SUCCESS) ? true : false;
+ nsSVGIntegrationUtils::PaintMask(params);
+
+ nsDisplayMaskGeometry::UpdateDrawResult(this, imgParmas.result);
}
LayerState
nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
if (ShouldPaintOnMaskLayer(aManager)) {
@@ -8525,43 +8524,42 @@ nsDisplayMask::ComputeInvalidationRegion
void
nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager)
{
MOZ_ASSERT(!ShouldPaintOnMaskLayer(aManager));
- uint32_t flags = aBuilder->ShouldSyncDecodeImages()
- ? imgIContainer::FLAG_SYNC_DECODE
- : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
- nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
- nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
- mFrame, mVisibleRect,
- borderArea, aBuilder,
- aManager,
- mHandleOpacity, flags);
-
// Clip the drawing target by mVisibleRect, which contains the visible
// region of the target frame and its out-of-flow and inflow descendants.
gfxContext* context = aCtx->ThebesContext();
Rect bounds =
NSRectToRect(mVisibleRect, mFrame->PresContext()->AppUnitsPerDevPixel());
bounds.RoundOut();
context->Clip(bounds);
+ imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
+ ? imgIContainer::FLAG_SYNC_DECODE
+ : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
+ nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
+ nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
+ mFrame, mVisibleRect,
+ borderArea, aBuilder,
+ aManager,
+ mHandleOpacity, imgParams);
+
ComputeMaskGeometry(params);
- image::DrawResult result =
- nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
+ nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
context->PopClip();
- nsDisplayMaskGeometry::UpdateDrawResult(this, result);
+ nsDisplayMaskGeometry::UpdateDrawResult(this, imgParams.result);
}
#ifdef MOZ_DUMP_PAINTING
void
nsDisplayMask::PrintEffects(nsACString& aTo)
{
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
@@ -8720,27 +8718,26 @@ nsDisplayFilter::ComputeInvalidationRegi
}
}
void
nsDisplayFilter::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager)
{
- uint32_t flags = aBuilder->ShouldSyncDecodeImages()
- ? imgIContainer::FLAG_SYNC_DECODE
- : imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
+ imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
+ ? imgIContainer::FLAG_SYNC_DECODE
+ : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
mFrame, mVisibleRect,
borderArea, aBuilder,
aManager,
- mHandleOpacity, flags);
- imgDrawingParams imgParams(flags);
- nsSVGIntegrationUtils::PaintFilter(params, imgParams);
+ mHandleOpacity, imgParams);
+ nsSVGIntegrationUtils::PaintFilter(params);
nsDisplayFilterGeometry::UpdateDrawResult(this, imgParams.result);
}
#ifdef MOZ_DUMP_PAINTING
void
nsDisplayFilter::PrintEffects(nsACString& aTo)
{
nsIFrame* firstFrame =
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -4430,17 +4430,17 @@ public:
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager);
/*
* Paint mask onto aMaskContext in mFrame's coordinate space.
*/
- bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
+ void PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
const nsTArray<nsRect>& GetDestRects()
{
return mDestRects;
}
private:
// According to mask property and the capability of aManager, determine
// whether paint mask onto a dedicate mask layer.
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -114,36 +114,35 @@ ComposeExtraMask(DrawTarget* aTarget, co
aTarget->SetTransform(aExtraMasksTransform * aTarget->GetTransform());
aTarget->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)),
aExtraMask,
Point(0, 0),
DrawOptions(1.0, CompositionOp::OP_IN));
aTarget->SetTransform(origin);
}
-DrawResult
+void
nsSVGClipPathFrame::PaintClipMask(gfxContext& aMaskContext,
nsIFrame* aClippedFrame,
const gfxMatrix& aMatrix,
Matrix* aMaskTransform,
SourceSurface* aExtraMask,
const Matrix& aExtraMasksTransform)
{
static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
// A clipPath can reference another clipPath, creating a chain of clipPaths
// that must all be applied. We re-enter this method for each clipPath in a
// chain, so we need to protect against reference chain related crashes etc.:
AutoReferenceChainGuard refChainGuard(this, &mIsBeingProcessed,
&sRefChainLengthCounter);
if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
- return DrawResult::SUCCESS; // Break reference chain
+ return; // Break reference chain
}
- DrawResult result = DrawResult::SUCCESS;
DrawTarget* maskDT = aMaskContext.GetDrawTarget();
MOZ_ASSERT(maskDT->GetFormat() == SurfaceFormat::A8);
// Paint this clipPath's contents into aMaskDT:
// We need to set mMatrixForChildren here so that under the PaintSVG calls
// on our children (below) our GetCanvasTM() method will return the correct
// transform.
mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;
@@ -154,18 +153,17 @@ nsSVGClipPathFrame::PaintClipMask(gfxCon
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(this, true, maskUsage);
if (maskUsage.shouldApplyClipPath) {
clipPathThatClipsClipPath->ApplyClipPath(aMaskContext, aClippedFrame,
aMatrix);
} else if (maskUsage.shouldGenerateClipMaskLayer) {
Matrix maskTransform;
- RefPtr<SourceSurface> maskSurface;
- Tie(result, maskSurface) =
+ RefPtr<SourceSurface> maskSurface =
clipPathThatClipsClipPath->GetClipMask(aMaskContext, aClippedFrame,
aMatrix, &maskTransform);
aMaskContext.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
maskSurface, maskTransform);
// The corresponding PopGroupAndBlend call below will mask the
// blend using |maskSurface|.
}
@@ -185,17 +183,16 @@ nsSVGClipPathFrame::PaintClipMask(gfxCon
gfxMatrix maskTransfrom = aMaskContext.CurrentMatrix();
maskTransfrom.Invert();
if (aExtraMask) {
ComposeExtraMask(maskDT, maskTransfrom, aExtraMask, aExtraMasksTransform);
}
*aMaskTransform = ToMatrix(maskTransfrom);
- return result;
}
void
nsSVGClipPathFrame::PaintFrameIntoMask(nsIFrame *aFrame,
nsIFrame* aClippedFrame,
gfxContext& aTarget,
const gfxMatrix& aMatrix)
{
@@ -218,18 +215,17 @@ nsSVGClipPathFrame::PaintFrameIntoMask(n
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(aFrame, true, maskUsage);
DrawResult result = DrawResult::SUCCESS;
if (maskUsage.shouldApplyClipPath) {
clipPathThatClipsChild->ApplyClipPath(aTarget, aClippedFrame, aMatrix);
} else if (maskUsage.shouldGenerateClipMaskLayer) {
Matrix maskTransform;
- RefPtr<SourceSurface> maskSurface;
- Tie(result, maskSurface) =
+ RefPtr<SourceSurface> maskSurface =
clipPathThatClipsChild->GetClipMask(aTarget, aClippedFrame,
aMatrix, &maskTransform);
aTarget.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
maskSurface, maskTransform);
// The corresponding PopGroupAndBlend call below will mask the
// blend using |maskSurface|.
}
@@ -253,44 +249,43 @@ nsSVGClipPathFrame::PaintFrameIntoMask(n
if (maskUsage.shouldGenerateClipMaskLayer) {
aTarget.PopGroupAndBlend();
} else if (maskUsage.shouldApplyClipPath) {
aTarget.PopClip();
}
}
-mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
+already_AddRefed<SourceSurface>
nsSVGClipPathFrame::GetClipMask(gfxContext& aReferenceContext,
nsIFrame* aClippedFrame,
const gfxMatrix& aMatrix,
Matrix* aMaskTransform,
SourceSurface* aExtraMask,
const Matrix& aExtraMasksTransform)
{
IntPoint offset;
RefPtr<DrawTarget> maskDT = CreateClipMask(aReferenceContext, offset);
if (!maskDT) {
- return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+ return nullptr;
}
RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(maskDT);
if (!maskContext) {
gfxCriticalError() << "SVGClipPath context problem " << gfx::hexa(maskDT);
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
maskContext->SetMatrix(aReferenceContext.CurrentMatrix() *
gfxMatrix::Translation(-offset));
- DrawResult result = PaintClipMask(*maskContext, aClippedFrame, aMatrix,
- aMaskTransform, aExtraMask,
- aExtraMasksTransform);
+ PaintClipMask(*maskContext, aClippedFrame, aMatrix, aMaskTransform,
+ aExtraMask, aExtraMasksTransform);
RefPtr<SourceSurface> surface = maskDT->Snapshot();
- return MakePair(result, Move(surface));
+ return surface.forget();
}
bool
nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,
const gfxPoint &aPoint)
{
static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
--- a/layout/svg/nsSVGClipPathFrame.h
+++ b/layout/svg/nsSVGClipPathFrame.h
@@ -17,16 +17,17 @@ class nsSVGDisplayableFrame;
class nsSVGClipPathFrame final : public nsSVGContainerFrame
{
friend nsIFrame*
NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
typedef mozilla::gfx::Matrix Matrix;
typedef mozilla::gfx::SourceSurface SourceSurface;
typedef mozilla::image::DrawResult DrawResult;
+ typedef mozilla::image::imgDrawingParams imgDrawingParams;
protected:
explicit nsSVGClipPathFrame(nsStyleContext* aContext)
: nsSVGContainerFrame(aContext, mozilla::LayoutFrameType::SVGClipPath)
, mIsBeingProcessed(false)
{
AddStateBits(NS_FRAME_IS_NONDISPLAY);
}
@@ -72,17 +73,17 @@ public:
* current transform.
* @param [out] aMaskTransform The transform to use with the returned
* surface.
* @param [in, optional] aExtraMask An extra surface that the returned
* surface should be masked with.
* @param [in, optional] aExtraMasksTransform The transform to use with
* aExtraMask. Should be passed when aExtraMask is passed.
*/
- mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
+ already_AddRefed<SourceSurface>
GetClipMask(gfxContext& aReferenceContext, nsIFrame* aClippedFrame,
const gfxMatrix& aMatrix, Matrix* aMaskTransform,
SourceSurface* aExtraMask = nullptr,
const Matrix& aExtraMasksTransform = Matrix());
/**
* Paint mask directly onto a given context(aMaskContext).
*
@@ -93,17 +94,17 @@ public:
* current transform.
* @param [out] aMaskTransform The transform to use with the returned
* surface.
* @param [in, optional] aExtraMask An extra surface that the returned
* surface should be masked with.
* @param [in, optional] aExtraMasksTransform The transform to use with
* aExtraMask. Should be passed when aExtraMask is passed.
*/
- DrawResult
+ void
PaintClipMask(gfxContext& aMaskContext, nsIFrame* aClippedFrame,
const gfxMatrix& aMatrix, Matrix* aMaskTransform,
SourceSurface* aExtraMask, const Matrix& aExtraMasksTransform);
/**
* aPoint is expected to be in aClippedFrame's SVG user space.
*/
bool PointIsInsideClipPath(nsIFrame* aClippedFrame, const gfxPoint &aPoint);
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -406,17 +406,17 @@ private:
gfxPoint mUserSpaceToFrameSpaceOffset;
};
typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
/**
* Paint css-positioned-mask onto a given target(aMaskDT).
*/
-static DrawResult
+static void
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);
@@ -434,83 +434,69 @@ PaintMaskSurface(const PaintFramesParams
RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(aMaskDT);
MOZ_ASSERT(maskContext);
maskContext->SetMatrix(aMaskSurfaceMatrix);
// Multiple SVG masks interleave with image mask. Paint each layer onto
// aMaskDT one at a time.
for (int i = aMaskFrames.Length() - 1; i >= 0 ; i--) {
nsSVGMaskFrame *maskFrame = aMaskFrames[i];
- DrawResult result = DrawResult::SUCCESS;
CompositionOp compositionOp = (i == int(aMaskFrames.Length() - 1))
? CompositionOp::OP_OVER
: nsCSSRendering::GetGFXCompositeMode(svgReset->mMask.mLayers[i].mComposite);
// maskFrame != nullptr means we get a SVG mask.
// maskFrame == nullptr means we get an image mask.
if (maskFrame) {
Matrix svgMaskMatrix;
nsSVGMaskFrame::MaskParams params(maskContext, aParams.frame,
cssPxToDevPxMatrix,
aOpacity, &svgMaskMatrix,
svgReset->mMask.mLayers[i].mMaskMode,
- aParams.flags);
- RefPtr<SourceSurface> svgMask;
- Tie(result, svgMask) = maskFrame->GetMaskForMaskedFrame(params);
-
+ aParams.imgParams);
+ RefPtr<SourceSurface> svgMask = maskFrame->GetMaskForMaskedFrame(params);
if (svgMask) {
- MOZ_ASSERT(result == DrawResult::SUCCESS);
gfxContextMatrixAutoSaveRestore matRestore(maskContext);
maskContext->Multiply(ThebesMatrix(svgMaskMatrix));
aMaskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask,
Point(0, 0),
DrawOptions(1.0, compositionOp));
}
-
- if (result != DrawResult::SUCCESS) {
- return result;
- }
} else {
gfxContextMatrixAutoSaveRestore matRestore(maskContext);
maskContext->Multiply(gfxMatrix::Translation(-devPixelOffsetToUserSpace));
nsRenderingContext rc(maskContext);
nsCSSRendering::PaintBGParams params =
nsCSSRendering::PaintBGParams::ForSingleLayer(*presContext,
aParams.dirtyRect,
aParams.borderArea,
aParams.frame,
aParams.builder->GetBackgroundPaintFlags() |
nsCSSRendering::PAINTBG_MASK_IMAGE,
i, compositionOp,
aOpacity);
- result =
+ aParams.imgParams.result &=
nsCSSRendering::PaintStyleImageLayerWithSC(params, rc, aSC,
*aParams.frame->StyleBorder());
- if (result != DrawResult::SUCCESS) {
- return result;
- }
}
}
-
- return DrawResult::SUCCESS;
}
struct MaskPaintResult {
RefPtr<SourceSurface> maskSurface;
Matrix maskTransform;
- DrawResult result;
bool transparentBlackMask;
bool opacityApplied;
MaskPaintResult()
- : result(DrawResult::SUCCESS), transparentBlackMask(false),
- opacityApplied(false)
+ : transparentBlackMask(false)
+ , opacityApplied(false)
{}
};
static MaskPaintResult
CreateAndPaintMaskSurface(const PaintFramesParams& aParams,
float aOpacity, nsStyleContext* aSC,
const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
const nsPoint& aOffsetToUserSpace)
@@ -524,18 +510,18 @@ CreateAndPaintMaskSurface(const PaintFra
// Optimization for single SVG mask.
if (((aMaskFrames.Length() == 1) && aMaskFrames[0])) {
gfxMatrix cssPxToDevPxMatrix =
nsSVGUtils::GetCSSPxToDevPxMatrix(aParams.frame);
paintResult.opacityApplied = true;
nsSVGMaskFrame::MaskParams params(&ctx, aParams.frame, cssPxToDevPxMatrix,
aOpacity, &paintResult.maskTransform,
svgReset->mMask.mLayers[0].mMaskMode,
- aParams.flags);
- Tie(paintResult.result, paintResult.maskSurface) =
+ aParams.imgParams);
+ paintResult.maskSurface =
aMaskFrames[0]->GetMaskForMaskedFrame(params);
if (!paintResult.maskSurface) {
paintResult.transparentBlackMask = true;
}
return paintResult;
}
@@ -545,37 +531,36 @@ CreateAndPaintMaskSurface(const PaintFra
paintResult.transparentBlackMask = true;
return paintResult;
}
RefPtr<DrawTarget> maskDT =
ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
SurfaceFormat::A8);
if (!maskDT || !maskDT->IsValid()) {
- paintResult.result = DrawResult::TEMPORARY_ERROR;
return paintResult;
}
// 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
- ? aOpacity : 1.0,
- aSC, aMaskFrames, maskSurfaceMatrix,
- aOffsetToUserSpace);
- if (paintResult.result != DrawResult::SUCCESS) {
+ PaintMaskSurface(aParams, maskDT,
+ paintResult.opacityApplied ? aOpacity : 1.0,
+ aSC, aMaskFrames, maskSurfaceMatrix,
+ aOffsetToUserSpace);
+
+ if (aParams.imgParams.result != DrawResult::SUCCESS) {
// Now we know the status of mask resource since we used it while painting.
// According to the return value of PaintMaskSurface, we know whether mask
// resource is resolvable or not.
//
// For a HTML doc:
// According to css-masking spec, always create a mask surface when
// we have any item in maskFrame even if all of those items are
// non-resolvable <mask-sources> or <images>.
@@ -752,35 +737,34 @@ public:
void SetContext(gfxContext* aContext) {
mContext = aContext;
}
private:
gfxContext* mContext;
};
-DrawResult
+void
nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
{
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
maskUsage);
nsIFrame* frame = aParams.frame;
if (!ValidateSVGFrame(frame)) {
- return DrawResult::SUCCESS;
+ return;
}
gfxContext& ctx = aParams.ctx;
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
- DrawResult result = DrawResult::SUCCESS;
RefPtr<DrawTarget> maskTarget = ctx.GetDrawTarget();
if (maskUsage.shouldGenerateMaskLayer &&
maskUsage.shouldGenerateClipMaskLayer) {
// We will paint both mask of positioned mask and clip-path into
// maskTarget.
//
// Create one extra draw target for drawing positioned mask, so that we do
@@ -811,58 +795,52 @@ nsSVGIntegrationUtils::PaintMask(const P
basicShapeSR.SetContext(&ctx);
nsCSSClipPathInstance::ApplyBasicShapeClip(ctx, frame);
if (!maskUsage.shouldGenerateMaskLayer) {
// Only have basic-shape clip-path effect. Fill clipped region by
// opaque white.
ctx.SetColor(Color(1.0, 1.0, 1.0, 1.0));
ctx.Fill();
- return result;
+ return;
}
}
// Paint mask onto ctx.
if (maskUsage.shouldGenerateMaskLayer) {
matSR.Restore();
matSR.SetContext(&ctx);
EffectOffsets offsets = MoveContextOriginToUserSpace(frame, aParams);
- result = PaintMaskSurface(aParams, maskTarget,
- shouldPushOpacity ? 1.0 : maskUsage.opacity,
- firstFrame->StyleContext(), maskFrames,
- ctx.CurrentMatrix(),
- offsets.offsetToUserSpace);
- if (result != DrawResult::SUCCESS) {
- return result;
- }
+ PaintMaskSurface(aParams, maskTarget,
+ shouldPushOpacity ? 1.0 : maskUsage.opacity,
+ firstFrame->StyleContext(), maskFrames,
+ ctx.CurrentMatrix(),
+ offsets.offsetToUserSpace);
}
// Paint clip-path onto ctx.
if (maskUsage.shouldGenerateClipMaskLayer || maskUsage.shouldApplyClipPath) {
matSR.Restore();
matSR.SetContext(&ctx);
MoveContextOriginToUserSpace(firstFrame, aParams);
Matrix clipMaskTransform;
gfxMatrix cssPxToDevPxMatrix = nsSVGUtils::GetCSSPxToDevPxMatrix(frame);
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
RefPtr<SourceSurface> maskSurface =
maskUsage.shouldGenerateMaskLayer ? maskTarget->Snapshot() : nullptr;
- result =
- clipPathFrame->PaintClipMask(ctx, frame, cssPxToDevPxMatrix,
+ clipPathFrame->PaintClipMask(ctx, frame, cssPxToDevPxMatrix,
&clipMaskTransform, maskSurface,
ToMatrix(ctx.CurrentMatrix()));
}
-
- return result;
}
-DrawResult
+void
nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
{
MOZ_ASSERT(UsingMaskOrClipPathForFrame(aParams.frame),
"Should not use this method when no mask or clipPath effect"
"on this frame");
/* SVG defines the following rendering model:
*
@@ -873,27 +851,26 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
* We handle #3 here and perform a couple of optimizations:
*
* + Use cairo's clipPath when representable natively (single object
* clip region).
*
* + Merge opacity and masking if both used together.
*/
nsIFrame* frame = aParams.frame;
- DrawResult result = DrawResult::SUCCESS;
if (!ValidateSVGFrame(frame)) {
- return result;
+ return;
}
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(aParams.frame, aParams.handleOpacity,
maskUsage);
if (maskUsage.opacity == 0.0f) {
- return DrawResult::SUCCESS;
+ return;
}
gfxContext& context = aParams.ctx;
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(&context);
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
nsIFrame* firstFrame =
@@ -928,50 +905,47 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
// instead of the first continuation frame.
EffectOffsets offsets = MoveContextOriginToUserSpace(frame, aParams);
MaskPaintResult paintResult =
CreateAndPaintMaskSurface(aParams, maskUsage.opacity,
firstFrame->StyleContext(),
maskFrames, offsets.offsetToUserSpace);
if (paintResult.transparentBlackMask) {
- return paintResult.result;
+ return;
}
- result &= paintResult.result;
maskSurface = paintResult.maskSurface;
if (maskSurface) {
shouldPushMask = true;
maskTransform = paintResult.maskTransform;
opacityApplied = paintResult.opacityApplied;
}
}
if (maskUsage.shouldGenerateClipMaskLayer) {
matSR.Restore();
matSR.SetContext(&context);
MoveContextOriginToUserSpace(firstFrame, aParams);
Matrix clipMaskTransform;
- DrawResult clipMaskResult;
- RefPtr<SourceSurface> clipMaskSurface;
- Tie(clipMaskResult, clipMaskSurface) =
+ RefPtr<SourceSurface> clipMaskSurface =
clipPathFrame->GetClipMask(context, frame, cssPxToDevPxMatrix,
&clipMaskTransform, maskSurface,
- maskTransform);
+ maskTransform);
if (clipMaskSurface) {
maskSurface = clipMaskSurface;
maskTransform = clipMaskTransform;
} else {
// Either entire surface is clipped out, or gfx buffer allocation
// failure in nsSVGClipPathFrame::GetClipMask.
- return clipMaskResult;
+ return;
}
- result &= clipMaskResult;
+
shouldPushMask = true;
}
// opacity != 1.0f.
if (!maskUsage.shouldGenerateClipMaskLayer &&
!maskUsage.shouldGenerateMaskLayer) {
MOZ_ASSERT(maskUsage.opacity != 1.0f);
@@ -1050,22 +1024,20 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
if (maskUsage.shouldApplyClipPath || maskUsage.shouldApplyBasicShape) {
context.PopClip();
}
if (shouldPushMask) {
context.PopGroupAndBlend();
}
- return result;
}
void
-nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams,
- imgDrawingParams& aImgParams)
+nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams)
{
MOZ_ASSERT(!aParams.builder->IsForGenerateGlyphMask(),
"Filter effect is discarded while generating glyph mask.");
MOZ_ASSERT(aParams.frame->StyleEffects()->HasFilters(),
"Should not use this method when no filter effect on this frame");
nsIFrame* frame = aParams.frame;
if (!ValidateSVGFrame(frame)) {
@@ -1110,17 +1082,17 @@ nsSVGIntegrationUtils::PaintFilter(const
DebugOnly<bool> invertible = reverseScaleMatrix.Invert();
MOZ_ASSERT(invertible);
context.SetMatrix(reverseScaleMatrix * context.CurrentMatrix());
gfxMatrix tm =
scaleMatrix * nsSVGUtils::GetCSSPxToDevPxMatrix(frame);
nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(),
tm, &callback, &dirtyRegion,
- aImgParams);
+ aParams.imgParams);
if (opacity != 1.0f) {
context.PopGroupAndBlend();
}
}
class PaintFrameCallback : public gfxDrawingCallback {
public:
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -128,64 +128,66 @@ public:
/**
* Returns true if the given point is not clipped out by effects.
* @param aPt in appunits relative to aFrame
*/
static bool
HitTestFrameForEffects(nsIFrame* aFrame, const nsPoint& aPt);
- struct PaintFramesParams {
+ struct MOZ_STACK_CLASS PaintFramesParams {
gfxContext& ctx;
nsIFrame* frame;
const nsRect& dirtyRect;
const nsRect& borderArea;
nsDisplayListBuilder* builder;
mozilla::layers::LayerManager* layerManager;
bool handleOpacity; // If true, PaintMaskAndClipPath/ PaintFilter should
// apply css opacity.
IntRect maskRect;
- uint32_t flags; // Image flags of the imgIContainer::FLAG_* variety.
+ imgDrawingParams& imgParams;
explicit PaintFramesParams(gfxContext& aCtx, nsIFrame* aFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsDisplayListBuilder* aBuilder,
mozilla::layers::LayerManager* aLayerManager,
- bool aHandleOpacity, uint32_t aFlags)
+ bool aHandleOpacity,
+ imgDrawingParams& aImgParams)
: ctx(aCtx), frame(aFrame), dirtyRect(aDirtyRect),
borderArea(aBorderArea), builder(aBuilder),
- layerManager(aLayerManager), handleOpacity(aHandleOpacity)
+ layerManager(aLayerManager), handleOpacity(aHandleOpacity),
+ imgParams(aImgParams)
{ }
};
/**
* Paint non-SVG frame with mask, clipPath and opacity effect.
*/
- static DrawResult
+ static void
PaintMaskAndClipPath(const PaintFramesParams& aParams);
/**
* Paint mask of non-SVG frame onto a given context, aParams.ctx.
* aParams.ctx must contain an A8 surface.
*/
- static DrawResult
+ static void
PaintMask(const PaintFramesParams& aParams);
/**
* Return true if all the mask resource of aFrame are ready.
*/
static bool
IsMaskResourceReady(nsIFrame* aFrame);
/**
* Paint non-SVG frame with filter and opacity effect.
*/
static void
- PaintFilter(const PaintFramesParams& aParams, imgDrawingParams& aImgParams);
+ PaintFilter(const PaintFramesParams& aParams);
/**
* @param aRenderingContext the target rendering context in which the paint
* server will be rendered
* @param aTarget the target frame onto which the paint server will be
* rendered
* @param aPaintServer a first-continuation frame to use as the source
* @param aFilter a filter to be applied when scaling
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -197,26 +197,26 @@ ComputeAlphaMask(const uint8_t *aSourceD
nsIFrame*
NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsSVGMaskFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame)
-mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
+already_AddRefed<SourceSurface>
nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
{
// Make sure we break reference loops and over long reference chains:
static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
AutoReferenceChainGuard refChainGuard(this, &mInUse,
&sRefChainLengthCounter);
if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
// Break reference chain
- return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+ return nullptr;
}
gfxRect maskArea = GetMaskArea(aParams.maskedFrame);
gfxContext* context = aParams.ctx;
// Get the clip extents in device space:
// Minimizing the mask surface extents (using both the current clip extents
// and maskArea) is important for performance.
context->Save();
@@ -228,73 +228,72 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
bool resultOverflows;
IntSize maskSurfaceSize =
nsSVGUtils::ConvertToSurfaceSize(maskSurfaceRect.Size(), &resultOverflows);
if (resultOverflows || maskSurfaceSize.IsEmpty()) {
// Return value other then DrawResult::SUCCESS, so the caller can skip
// painting the masked frame(aParams.maskedFrame).
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
RefPtr<DrawTarget> maskDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
maskSurfaceSize, SurfaceFormat::B8G8R8A8);
if (!maskDT || !maskDT->IsValid()) {
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
gfxMatrix maskSurfaceMatrix =
context->CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
RefPtr<gfxContext> tmpCtx = gfxContext::CreateOrNull(maskDT);
MOZ_ASSERT(tmpCtx); // already checked the draw target above
tmpCtx->SetMatrix(maskSurfaceMatrix);
mMatrixForChildren = GetMaskTransform(aParams.maskedFrame) *
aParams.toUserSpace;
- imgDrawingParams imgParams(aParams.flags);
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
// The CTM of each frame referencing us can be different
nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
}
gfxMatrix m = mMatrixForChildren;
if (kid->GetContent()->IsSVGElement()) {
m = static_cast<nsSVGElement*>(kid->GetContent())->
PrependLocalTransformsTo(m, eUserSpaceToParent);
}
- nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, imgParams);
+ nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, aParams.imgParams);
}
RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
if (!maskSnapshot) {
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
DataSourceSurface::MappedSurface map;
if (!maskSurface ||
!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
// Create alpha channel mask for output
RefPtr<DataSourceSurface> destMaskSurface =
Factory::CreateDataSourceSurface(maskSurfaceSize, SurfaceFormat::A8);
if (!destMaskSurface) {
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
DataSourceSurface::MappedSurface destMap;
if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
- return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
+ return nullptr;
}
uint8_t maskType;
if (aParams.maskMode == NS_STYLE_MASK_MODE_MATCH_SOURCE) {
maskType = StyleSVGReset()->mMaskType;
} else {
maskType = aParams.maskMode == NS_STYLE_MASK_MODE_LUMINANCE
? NS_STYLE_MASK_TYPE_LUMINANCE : NS_STYLE_MASK_TYPE_ALPHA;
@@ -317,22 +316,21 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
maskSurfaceSize, aParams.opacity);
}
maskSurface->Unmap();
destMaskSurface->Unmap();
// Moz2D transforms in the opposite direction to Thebes
if (!maskSurfaceMatrix.Invert()) {
- return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
+ return nullptr;
}
*aParams.maskTransform = ToMatrix(maskSurfaceMatrix);
- RefPtr<SourceSurface> surface = destMaskSurface.forget();
- return MakePair(imgParams.result, Move(surface));
+ return destMaskSurface.forget();
}
gfxRect
nsSVGMaskFrame::GetMaskArea(nsIFrame* aMaskedFrame)
{
SVGMaskElement *maskElem = static_cast<SVGMaskElement*>(mContent);
uint16_t units =
--- a/layout/svg/nsSVGMaskFrame.h
+++ b/layout/svg/nsSVGMaskFrame.h
@@ -4,17 +4,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __NS_SVGMASKFRAME_H__
#define __NS_SVGMASKFRAME_H__
#include "mozilla/Attributes.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
-#include "mozilla/Pair.h"
#include "gfxPattern.h"
#include "gfxMatrix.h"
#include "nsSVGContainerFrame.h"
#include "nsSVGUtils.h"
class gfxContext;
/**
@@ -55,30 +54,37 @@ public:
struct MaskParams {
gfxContext* ctx;
nsIFrame* maskedFrame;
const gfxMatrix& toUserSpace;
float opacity;
Matrix* maskTransform;
uint8_t maskMode;
- uint32_t flags; // Image flags of the imgIContainer::FLAG_* variety.
+ imgDrawingParams& imgParams;
explicit MaskParams(gfxContext* aCtx, nsIFrame* aMaskedFrame,
const gfxMatrix& aToUserSpace, float aOpacity,
Matrix* aMaskTransform, uint8_t aMaskMode,
- uint32_t aFlags)
+ imgDrawingParams& aImgParams)
: ctx(aCtx), maskedFrame(aMaskedFrame), toUserSpace(aToUserSpace),
opacity(aOpacity), maskTransform(aMaskTransform), maskMode(aMaskMode),
- flags(aFlags)
+ imgParams(aImgParams)
{ }
};
// nsSVGMaskFrame method:
- mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
+
+ /**
+ * Generate a mask surface for the target frame.
+ *
+ * The return surface can be null, it's the caller's responsibility to
+ * null-check before dereferencing.
+ */
+ already_AddRefed<SourceSurface>
GetMaskForMaskedFrame(MaskParams& aParams);
gfxRect
GetMaskArea(nsIFrame* aMaskedFrame);
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -788,37 +788,33 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
// mask:url(#id-which-does-not-exist)
// Since we only uses nsSVGUtils with SVG elements, not like mask on an
// HTML element, we should treat an unresolvable mask as no-mask here.
if (maskUsage.shouldGenerateMaskLayer && maskFrame) {
uint8_t maskMode =
aFrame->StyleSVGReset()->mMask.mLayers[0].mMaskMode;
nsSVGMaskFrame::MaskParams params(&aContext, aFrame, aTransform,
maskUsage.opacity, &maskTransform,
- maskMode, aImgParams.imageFlags);
- Tie(aImgParams.result, maskSurface) =
- maskFrame->GetMaskForMaskedFrame(params);
+ maskMode, aImgParams);
+ maskSurface = maskFrame->GetMaskForMaskedFrame(params);
if (!maskSurface) {
// Either entire surface is clipped out, or gfx buffer allocation
// failure in nsSVGMaskFrame::GetMaskForMaskedFrame.
return;
}
shouldPushMask = true;
}
if (maskUsage.shouldGenerateClipMaskLayer) {
Matrix clippedMaskTransform;
- DrawResult clipMaskResult;
- RefPtr<SourceSurface> clipMaskSurface;
- Tie(clipMaskResult, clipMaskSurface) =
+ RefPtr<SourceSurface> clipMaskSurface =
clipPathFrame->GetClipMask(aContext, aFrame, aTransform,
&clippedMaskTransform, maskSurface,
maskTransform);
- aImgParams.result &= clipMaskResult;
if (clipMaskSurface) {
maskSurface = clipMaskSurface;
maskTransform = clippedMaskTransform;
} else {
// Either entire surface is clipped out, or gfx buffer allocation
// failure in nsSVGClipPathFrame::GetClipMask.
return;
}