зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1234485 - Part 12. Extract PaintMaskSurface from GenerateMaskSurface. r=mstange
MozReview-Commit-ID: Bg4Kt6yCtNe --HG-- extra : rebase_source : e13ce7753bede0e9edc58f8406c60d4120fbd329
This commit is contained in:
Родитель
575b4ea688
Коммит
bb74527cff
|
@ -429,67 +429,34 @@ HasNonSVGMask(const nsTArray<nsSVGMaskFrame*>& aMaskFrames)
|
|||
|
||||
typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
|
||||
|
||||
/**
|
||||
* Paint css-positioned-mask onto a given target(aMaskDT).
|
||||
*/
|
||||
static DrawResult
|
||||
GenerateMaskSurface(const PaintFramesParams& aParams,
|
||||
float aOpacity, nsStyleContext* aSC,
|
||||
const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
|
||||
const nsPoint& aOffsetToUserSpace,
|
||||
Matrix& aOutMaskTransform,
|
||||
RefPtr<SourceSurface>& aOutMaskSurface,
|
||||
bool& aOpacityApplied)
|
||||
PaintMaskSurface(const PaintFramesParams& aParams,
|
||||
DrawTarget* aMaskDT, float aOpacity, nsStyleContext* aSC,
|
||||
const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
|
||||
const gfxMatrix& aMaskSurfaceMatrix,
|
||||
const nsPoint& aOffsetToUserSpace)
|
||||
{
|
||||
const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
|
||||
MOZ_ASSERT(aMaskFrames.Length() > 0);
|
||||
MOZ_ASSERT(aMaskDT->GetFormat() == SurfaceFormat::A8);
|
||||
|
||||
const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
|
||||
gfxMatrix cssPxToDevPxMatrix =
|
||||
nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);
|
||||
|
||||
gfxContext& ctx = aParams.ctx;
|
||||
|
||||
// There is only one SVG mask.
|
||||
if (((aMaskFrames.Length() == 1) && aMaskFrames[0])) {
|
||||
aOpacityApplied = true;
|
||||
aOutMaskSurface =
|
||||
aMaskFrames[0]->GetMaskForMaskedFrame(&ctx, aParams.frame,
|
||||
cssPxToDevPxMatrix, aOpacity,
|
||||
&aOutMaskTransform,
|
||||
svgReset->mMask.mLayers[0].mMaskMode);
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
const IntRect& maskSurfaceRect = aParams.maskRect;
|
||||
if (maskSurfaceRect.IsEmpty()) {
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> maskDT =
|
||||
ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
|
||||
SurfaceFormat::A8);
|
||||
if (!maskDT || !maskDT->IsValid()) {
|
||||
return DrawResult::TEMPORARY_ERROR;
|
||||
}
|
||||
|
||||
RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(maskDT);
|
||||
MOZ_ASSERT(maskContext);
|
||||
|
||||
nsPresContext* presContext = aParams.frame->PresContext();
|
||||
gfxPoint devPixelOffsetToUserSpace =
|
||||
nsLayoutUtils::PointToGfxPoint(aOffsetToUserSpace,
|
||||
presContext->AppUnitsPerDevPixel());
|
||||
|
||||
// Set ctx'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(-maskSurfaceRect.TopLeft());
|
||||
maskContext->SetMatrix(maskSurfaceMatrix);
|
||||
|
||||
// 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.
|
||||
aOpacityApplied = !HasNonSVGMask(aMaskFrames);
|
||||
RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(aMaskDT);
|
||||
MOZ_ASSERT(maskContext);
|
||||
maskContext->SetMatrix(aMaskSurfaceMatrix);
|
||||
|
||||
// Multiple SVG masks interleave with image mask. Paint each layer onto
|
||||
// maskDT one at a time.
|
||||
// aMaskDT one at a time.
|
||||
for (int i = aMaskFrames.Length() - 1; i >= 0 ; i--) {
|
||||
nsSVGMaskFrame *maskFrame = aMaskFrames[i];
|
||||
|
||||
|
@ -504,7 +471,7 @@ GenerateMaskSurface(const PaintFramesParams& aParams,
|
|||
RefPtr<SourceSurface> svgMask =
|
||||
maskFrame->GetMaskForMaskedFrame(maskContext, aParams.frame,
|
||||
cssPxToDevPxMatrix,
|
||||
aOpacityApplied ? aOpacity : 1.0,
|
||||
aOpacity,
|
||||
&svgMaskMatrix,
|
||||
svgReset->mMask.mLayers[i].mMaskMode);
|
||||
if (svgMask) {
|
||||
|
@ -512,7 +479,7 @@ GenerateMaskSurface(const PaintFramesParams& aParams,
|
|||
|
||||
maskContext->Multiply(ThebesMatrix(svgMaskMatrix));
|
||||
Rect drawRect = IntRectToRect(IntRect(IntPoint(0, 0), svgMask->GetSize()));
|
||||
maskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask,
|
||||
aMaskDT->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)), svgMask,
|
||||
drawRect.TopLeft(),
|
||||
DrawOptions(1.0, compositionOp));
|
||||
}
|
||||
|
@ -539,6 +506,67 @@ GenerateMaskSurface(const PaintFramesParams& aParams,
|
|||
}
|
||||
}
|
||||
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
static DrawResult
|
||||
CreateAndPaintMaskSurface(const PaintFramesParams& aParams,
|
||||
float aOpacity, nsStyleContext* aSC,
|
||||
const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
|
||||
const nsPoint& aOffsetToUserSpace,
|
||||
Matrix& aOutMaskTransform,
|
||||
RefPtr<SourceSurface>& aOutMaskSurface,
|
||||
bool& aOpacityApplied)
|
||||
{
|
||||
const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
|
||||
MOZ_ASSERT(aMaskFrames.Length() > 0);
|
||||
|
||||
gfxContext& ctx = aParams.ctx;
|
||||
|
||||
// There is only one SVG mask.
|
||||
if (((aMaskFrames.Length() == 1) && aMaskFrames[0])) {
|
||||
gfxMatrix cssPxToDevPxMatrix =
|
||||
nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);
|
||||
|
||||
aOpacityApplied = true;
|
||||
aOutMaskSurface =
|
||||
aMaskFrames[0]->GetMaskForMaskedFrame(&ctx, aParams.frame,
|
||||
cssPxToDevPxMatrix, aOpacity,
|
||||
&aOutMaskTransform,
|
||||
svgReset->mMask.mLayers[0].mMaskMode);
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
const IntRect& maskSurfaceRect = aParams.maskRect;
|
||||
if (maskSurfaceRect.IsEmpty()) {
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> maskDT =
|
||||
ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
|
||||
SurfaceFormat::A8);
|
||||
if (!maskDT || !maskDT->IsValid()) {
|
||||
return DrawResult::TEMPORARY_ERROR;
|
||||
}
|
||||
|
||||
// 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.
|
||||
aOpacityApplied = !HasNonSVGMask(aMaskFrames);
|
||||
|
||||
// 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());
|
||||
|
||||
DrawResult result = PaintMaskSurface(aParams, maskDT,
|
||||
aOpacityApplied ? aOpacity : 1.0,
|
||||
aSC, aMaskFrames, maskSurfaceMatrix,
|
||||
aOffsetToUserSpace);
|
||||
if (result != DrawResult::SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
aOutMaskTransform = ToMatrix(maskSurfaceMatrix);
|
||||
if (!aOutMaskTransform.Invert()) {
|
||||
return DrawResult::SUCCESS;
|
||||
|
@ -757,9 +785,8 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
|||
MOZ_ASSERT(maskUsage.shouldGenerateMaskLayer);
|
||||
|
||||
nsIFrame* frame = aParams.frame;
|
||||
DrawResult result = DrawResult::SUCCESS;
|
||||
if (!ValidateSVGFrame(frame)) {
|
||||
return result;
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
if (maskUsage.opacity == 0.0f) {
|
||||
|
@ -768,9 +795,6 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
|||
|
||||
gfxContext& ctx = aParams.ctx;
|
||||
|
||||
Matrix maskTransform;
|
||||
RefPtr<SourceSurface> maskSurface;
|
||||
|
||||
gfxContextMatrixAutoSaveRestore matSR(&ctx);
|
||||
|
||||
nsIFrame* firstFrame =
|
||||
|
@ -778,29 +802,17 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
|
|||
nsSVGEffects::EffectProperties effectProperties =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame);
|
||||
nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
|
||||
bool opacityApplied = false;
|
||||
bool opacityApplied = !HasNonSVGMask(maskFrames);
|
||||
|
||||
nsPoint offsetToBoundingBox;
|
||||
nsPoint offsetToUserSpace;
|
||||
SetupContextMatrix(frame, aParams, offsetToBoundingBox,
|
||||
offsetToUserSpace, false);
|
||||
result = GenerateMaskSurface(aParams, maskUsage.opacity,
|
||||
firstFrame->StyleContext(),
|
||||
maskFrames, offsetToUserSpace,
|
||||
maskTransform, maskSurface, opacityApplied);
|
||||
if (!maskSurface) {
|
||||
// Entire surface is clipped out.
|
||||
return result;
|
||||
}
|
||||
|
||||
ctx.Multiply(ThebesMatrix(maskTransform));
|
||||
|
||||
DrawTarget* target = ctx.GetDrawTarget();
|
||||
MOZ_ASSERT(target->GetFormat() == SurfaceFormat::A8);
|
||||
Rect drawingRect(Point(0, 0), Size(target->GetSize()));
|
||||
target->DrawSurface(maskSurface, drawingRect, drawingRect);
|
||||
|
||||
return result;
|
||||
return PaintMaskSurface(aParams, ctx.GetDrawTarget(),
|
||||
opacityApplied ? maskUsage.opacity : 1.0,
|
||||
firstFrame->StyleContext(), maskFrames,
|
||||
ctx.CurrentMatrix(), offsetToUserSpace);
|
||||
}
|
||||
|
||||
DrawResult
|
||||
|
@ -876,10 +888,11 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
|
|||
// instead of the first continuation frame.
|
||||
SetupContextMatrix(frame, aParams, offsetToBoundingBox,
|
||||
offsetToUserSpace, false);
|
||||
result = GenerateMaskSurface(aParams, maskUsage.opacity,
|
||||
firstFrame->StyleContext(),
|
||||
maskFrames, offsetToUserSpace,
|
||||
maskTransform, maskSurface, opacityApplied);
|
||||
result = CreateAndPaintMaskSurface(aParams, maskUsage.opacity,
|
||||
firstFrame->StyleContext(),
|
||||
maskFrames, offsetToUserSpace,
|
||||
maskTransform, maskSurface,
|
||||
opacityApplied);
|
||||
if (!maskSurface) {
|
||||
// Entire surface is clipped out.
|
||||
return result;
|
||||
|
|
Загрузка…
Ссылка в новой задаче