Bug 1054838, part 2 - Remove callers of DrawTarget::Mask. r=Bas,jwatt

This commit is contained in:
Matt Woodrow 2014-09-12 08:20:12 +01:00
parent 810fbe5243
commit 5056e93044
7 changed files with 73 additions and 60 deletions

View File

@ -926,37 +926,15 @@ gfxContext::GetPattern()
// masking
void
gfxContext::Mask(gfxPattern *pattern)
gfxContext::Mask(SourceSurface* aSurface, const Matrix& aTransform)
{
if (pattern->Extend() == gfxPattern::EXTEND_NONE) {
// In this situation the mask will be fully transparent (i.e. nothing
// will be drawn) outside of the bounds of the surface. We can support
// that by clipping out drawing to that area.
Point offset;
if (pattern->IsAzure()) {
// This is an Azure pattern. i.e. this was the result of a PopGroup and
// then the extend mode was changed to EXTEND_NONE.
// XXX - We may need some additional magic here in theory to support
// device offsets in these patterns, but no problems have been observed
// yet because of this. And it would complicate things a little further.
offset = Point(0.f, 0.f);
}
Matrix old = mTransform;
Matrix mat = aTransform * mTransform;
if (pattern->IsAzure()) {
RefPtr<SourceSurface> mask = pattern->GetAzureSurface();
Matrix mat = ToMatrix(pattern->GetInverseMatrix());
Matrix old = mTransform;
// add in the inverse of the pattern transform so that when we
// MaskSurface we are transformed to the place matching the pattern transform
mat = mat * mTransform;
ChangeTransform(mat);
mDT->MaskSurface(GeneralPattern(this), mask, offset, DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
ChangeTransform(old);
return;
}
}
mDT->Mask(GeneralPattern(this), *pattern->GetPattern(mDT), DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
ChangeTransform(mat);
mDT->MaskSurface(GeneralPattern(this), aSurface, Point(),
DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
ChangeTransform(old);
}
void
@ -1120,6 +1098,24 @@ gfxContext::PopGroup()
return pat.forget();
}
TemporaryRef<SourceSurface>
gfxContext::PopGroupToSurface(Matrix* aTransform)
{
RefPtr<SourceSurface> src = mDT->Snapshot();
Point deviceOffset = CurrentState().deviceOffset;
Restore();
Matrix mat = mTransform;
mat.Invert();
Matrix deviceOffsetTranslation;
deviceOffsetTranslation.PreTranslate(deviceOffset.x, deviceOffset.y);
*aTransform = deviceOffsetTranslation * mat;
return src;
}
void
gfxContext::PopGroupToSource()
{

View File

@ -388,7 +388,7 @@ public:
* Like Paint, except that it only draws the source where pattern is
* non-transparent.
*/
void Mask(gfxPattern *pattern);
void Mask(mozilla::gfx::SourceSurface *aSurface, const mozilla::gfx::Matrix& aTransform);
/**
* Shorthand for creating a pattern and calling the pattern-taking
@ -601,6 +601,9 @@ public:
already_AddRefed<gfxPattern> PopGroup();
void PopGroupToSource();
mozilla::TemporaryRef<mozilla::gfx::SourceSurface>
PopGroupToSurface(mozilla::gfx::Matrix* aMatrix);
/**
** Hit Testing - check if given point is in the current path
**/

View File

@ -8,13 +8,15 @@
// Keep others in (case-insensitive) order:
#include "gfxContext.h"
#include "mozilla/dom/SVGClipPathElement.h"
#include "nsGkAtoms.h"
#include "nsRenderingContext.h"
#include "mozilla/dom/SVGClipPathElement.h"
#include "nsSVGEffects.h"
#include "nsSVGUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
//----------------------------------------------------------------------
// Implementation
@ -136,14 +138,14 @@ nsSVGClipPathFrame::ApplyClipOrPaintClipMask(nsRenderingContext* aContext,
if (!isTrivial) {
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> clipMaskSurface;
gfx->PushGroup(gfxContentType::ALPHA);
clipPathFrame->ApplyClipOrPaintClipMask(aContext, aClippedFrame, aMatrix);
clipMaskSurface = gfx->PopGroup();
Matrix maskTransform;
RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&maskTransform);
if (clipMaskSurface) {
gfx->Mask(clipMaskSurface);
gfx->Mask(clipMaskSurface, maskTransform);
}
}
gfx->Restore();
@ -155,14 +157,14 @@ nsSVGClipPathFrame::ApplyClipOrPaintClipMask(nsRenderingContext* aContext,
if (!referencedClipIsTrivial) {
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> clipMaskSurface;
gfx->PushGroup(gfxContentType::ALPHA);
clipPathFrame->ApplyClipOrPaintClipMask(aContext, aClippedFrame, aMatrix);
clipMaskSurface = gfx->PopGroup();
Matrix maskTransform;
RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&maskTransform);
if (clipMaskSurface) {
gfx->Mask(clipMaskSurface);
gfx->Mask(clipMaskSurface, maskTransform);
}
}
gfx->Restore();

View File

@ -26,6 +26,7 @@
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::gfx;
// ----------------------------------------------------------------------
@ -555,33 +556,34 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> maskSurface =
Matrix maskTransform;
RefPtr<SourceSurface> maskSurface =
maskFrame ? maskFrame->GetMaskForMaskedFrame(aCtx->ThebesContext(),
aFrame, cssPxToDevPxMatrix,
opacity)
opacity, &maskTransform)
: nullptr;
nsRefPtr<gfxPattern> clipMaskSurface;
if (clipPathFrame && !isTrivialClip) {
gfx->PushGroup(gfxContentType::COLOR_ALPHA);
nsresult rv = clipPathFrame->ApplyClipOrPaintClipMask(aCtx, aFrame, cssPxToDevPxMatrix);
clipMaskSurface = gfx->PopGroup();
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&clippedMaskTransform);
if (NS_SUCCEEDED(rv) && clipMaskSurface) {
// Still more set after clipping, so clip to another surface
if (maskSurface || opacity != 1.0f) {
gfx->PushGroup(gfxContentType::COLOR_ALPHA);
gfx->Mask(clipMaskSurface);
gfx->Mask(clipMaskSurface, clippedMaskTransform);
gfx->PopGroupToSource();
} else {
gfx->Mask(clipMaskSurface);
gfx->Mask(clipMaskSurface, clippedMaskTransform);
}
}
}
if (maskSurface) {
gfx->Mask(maskSurface);
gfx->Mask(maskSurface, maskTransform);
} else if (opacity != 1.0f) {
gfx->Paint(opacity);
}

View File

@ -166,11 +166,12 @@ NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame)
already_AddRefed<gfxPattern>
TemporaryRef<SourceSurface>
nsSVGMaskFrame::GetMaskForMaskedFrame(gfxContext* aContext,
nsIFrame* aMaskedFrame,
const gfxMatrix &aMatrix,
float aOpacity)
float aOpacity,
Matrix* aMaskTransform)
{
// If the flag is set when we get here, it means this mask frame
// has already been used painting the current mask, and the document
@ -273,9 +274,9 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(gfxContext* aContext,
if (!maskSurfaceMatrix.Invert()) {
return nullptr;
}
nsRefPtr<gfxPattern> retval =
new gfxPattern(maskSurface, ToMatrix(maskSurfaceMatrix));
return retval.forget();
*aMaskTransform = ToMatrix(maskSurfaceMatrix);
return maskSurface;
}
nsresult

View File

@ -7,6 +7,8 @@
#define __NS_SVGMASKFRAME_H__
#include "mozilla/Attributes.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "gfxPattern.h"
#include "gfxMatrix.h"
#include "nsSVGContainerFrame.h"
@ -21,6 +23,10 @@ class nsSVGMaskFrame MOZ_FINAL : public nsSVGMaskFrameBase
{
friend nsIFrame*
NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
typedef mozilla::gfx::Matrix Matrix;
typedef mozilla::gfx::SourceSurface SourceSurface;
protected:
explicit nsSVGMaskFrame(nsStyleContext* aContext)
: nsSVGMaskFrameBase(aContext)
@ -33,10 +39,12 @@ public:
NS_DECL_FRAMEARENA_HELPERS
// nsSVGMaskFrame method:
already_AddRefed<gfxPattern> GetMaskForMaskedFrame(gfxContext* aContext,
nsIFrame* aMaskedFrame,
const gfxMatrix &aMatrix,
float aOpacity);
mozilla::TemporaryRef<SourceSurface>
GetMaskForMaskedFrame(gfxContext* aContext,
nsIFrame* aMaskedFrame,
const gfxMatrix &aMatrix,
float aOpacity,
Matrix* aMaskTransform);
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,

View File

@ -634,32 +634,33 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> maskSurface =
Matrix maskTransform;
RefPtr<SourceSurface> maskSurface =
maskFrame ? maskFrame->GetMaskForMaskedFrame(aContext->ThebesContext(),
aFrame, aTransform, opacity)
aFrame, aTransform, opacity, &maskTransform)
: nullptr;
nsRefPtr<gfxPattern> clipMaskSurface;
if (clipPathFrame && !isTrivialClip) {
gfx->PushGroup(gfxContentType::COLOR_ALPHA);
nsresult rv = clipPathFrame->ApplyClipOrPaintClipMask(aContext, aFrame, aTransform);
clipMaskSurface = gfx->PopGroup();
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface = gfx->PopGroupToSurface(&clippedMaskTransform);
if (NS_SUCCEEDED(rv) && clipMaskSurface) {
// Still more set after clipping, so clip to another surface
if (maskSurface || opacity != 1.0f) {
gfx->PushGroup(gfxContentType::COLOR_ALPHA);
gfx->Mask(clipMaskSurface);
gfx->Mask(clipMaskSurface, clippedMaskTransform);
gfx->PopGroupToSource();
} else {
gfx->Mask(clipMaskSurface);
gfx->Mask(clipMaskSurface, clippedMaskTransform);
}
}
}
if (maskSurface) {
gfx->Mask(maskSurface);
gfx->Mask(maskSurface, maskTransform);
} else if (opacity != 1.0f) {
gfx->Paint(opacity);
}