--- a/gfx/thebes/gfxContext.h
+++ b/gfx/thebes/gfxContext.h
@@ -614,16 +614,17 @@ public:
mContext = aContext;
mMatrix = aContext->CurrentMatrix();
}
void Restore()
{
if (mContext) {
mContext->SetMatrix(mMatrix);
+ mContext = nullptr;
}
}
const gfxMatrix& Matrix()
{
MOZ_ASSERT(mContext, "mMatrix doesn't contain a useful matrix");
return mMatrix;
}
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -860,47 +860,67 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
}
bool shouldGenerateMask = (opacity != 1.0f || shouldGenerateClipMaskLayer ||
shouldGenerateMaskLayer);
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
if (shouldGenerateMask) {
- gfxContextMatrixAutoSaveRestore save(&context);
- SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
- offsetToUserSpace, true);
+ gfxContextMatrixAutoSaveRestore matSR;
+
Matrix maskTransform;
RefPtr<SourceSurface> maskSurface;
+
if (shouldGenerateMaskLayer) {
+ matSR.SetContext(&context);
+
+ // For css-mask, we want to generate a mask for each continuation frame,
+ // so we setup context matrix by the position of the current frame,
+ // instead of the first continuation frame.
+ SetupContextMatrix(frame, aParams, offsetToBoundingBox,
+ offsetToUserSpace, true);
result = GenerateMaskSurface(aParams, opacity,
firstFrame->StyleContext(),
maskFrames, offsetToUserSpace,
maskTransform, maskSurface);
- }
-
- if (shouldGenerateMaskLayer && !maskSurface) {
- // Entire surface is clipped out.
- return result;
+ context.PopClip();
+ if (!maskSurface) {
+ // Entire surface is clipped out.
+ return result;
+ }
}
if (shouldGenerateClipMaskLayer) {
+ matSR.Restore();
+ matSR.SetContext(&context);
+
+ SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
+ offsetToUserSpace, true);
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface =
clipPathFrame->GetClipMask(context, frame, cssPxToDevPxMatrix,
&clippedMaskTransform, maskSurface,
maskTransform, &result);
+ context.PopClip();
if (clipMaskSurface) {
maskSurface = clipMaskSurface;
maskTransform = clippedMaskTransform;
}
}
- // Pop the clip pushed in SetupContextMatrix.
- context.PopClip();
+
+ // opacity != 1.0f.
+ if (!shouldGenerateClipMaskLayer && !shouldGenerateMaskLayer) {
+ MOZ_ASSERT(opacity != 1.0f);
+
+ matSR.SetContext(&context);
+ SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
+ offsetToUserSpace, true);
+ }
target->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity, maskSurface, maskTransform);
}
/* If this frame has only a trivial clipPath, set up cairo's clipping now so
* we can just do normal painting and get it clipped appropriately.
*/
if (shouldApplyClipPath || shouldApplyBasicShape) {
@@ -926,16 +946,22 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
basic->SetTarget(oldCtx);
if (shouldApplyClipPath || shouldApplyBasicShape) {
context.Restore();
}
if (shouldGenerateMask) {
target->PopGroupAndBlend();
+
+ if (!shouldGenerateClipMaskLayer && !shouldGenerateMaskLayer) {
+ MOZ_ASSERT(opacity != 1.0f);
+ // Pop the clip push by SetupContextMatrix
+ context.PopClip();
+ }
}
if (aParams.frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
MOZ_ASSERT(target != &aParams.ctx);
BlendToTarget(aParams, target, targetOffset);
}
return result;
@@ -975,17 +1001,17 @@ nsSVGIntegrationUtils::PaintFilter(const
gfxContext& context = aParams.ctx;
nsPoint offsetToBoundingBox;
nsPoint offsetToUserSpace;
// These are used if we require a temporary surface for a custom blend mode.
// Clip the source context first, so that we can generate a smaller temporary
// surface. (Since we will clip this context in SetupContextMatrix, a pair
// of save/restore is needed.)
- context.Save();
+ gfxContextAutoSaveRestore autoSR(&context);
SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
offsetToUserSpace, true);
IntPoint targetOffset;
RefPtr<gfxContext> target =
(aParams.frame->StyleEffects()->mMixBlendMode == NS_STYLE_BLEND_NORMAL)
? RefPtr<gfxContext>(&aParams.ctx).forget()
: CreateBlendTarget(aParams, targetOffset);
if (!target) {
@@ -1010,17 +1036,16 @@ nsSVGIntegrationUtils::PaintFilter(const
target->PopGroupAndBlend();
}
if (aParams.frame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
MOZ_ASSERT(target != &aParams.ctx);
BlendToTarget(aParams, target, targetOffset);
}
- context.Restore();
return result;
}
gfxMatrix
nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(nsIFrame* aNonSVGFrame)
{
int32_t appUnitsPerDevPixel = aNonSVGFrame->PresContext()->AppUnitsPerDevPixel();
float devPxPerCSSPx =