Bug 324183 - masking and other surface operations inside a filter incorrect.
r=scooter git-svn-id: svn://10.0.0.236/trunk@188470 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
39d0ee60a3
commit
cbc768243c
@ -133,7 +133,8 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
@ -155,7 +156,8 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
@ -167,7 +169,8 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
@ -190,7 +193,8 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
|
||||
@ -374,7 +374,8 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
@ -397,7 +398,8 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
@ -409,7 +411,8 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
@ -522,7 +525,8 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
|
||||
@ -439,7 +439,8 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
clip->IsTrivial(&trivialClip);
|
||||
|
||||
if (!trivialClip) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
@ -461,7 +462,8 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
@ -473,7 +475,8 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
@ -496,7 +499,8 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
|
||||
@ -284,7 +284,8 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
@ -307,7 +308,8 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix;
|
||||
@ -319,7 +321,8 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
@ -369,7 +372,8 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
|
||||
@ -594,7 +594,8 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
if (trivialClip) {
|
||||
canvas->PushClip();
|
||||
} else {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipMaskSurface));
|
||||
if (!clipMaskSurface)
|
||||
clip = nsnull;
|
||||
}
|
||||
@ -616,7 +617,8 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
@ -628,7 +630,8 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
}
|
||||
|
||||
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(maskedSurface));
|
||||
if (maskedSurface) {
|
||||
canvas->PushSurface(maskedSurface);
|
||||
} else
|
||||
@ -652,7 +655,8 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
maskSurface = clipMaskSurface;
|
||||
} else {
|
||||
nsCOMPtr<nsISVGRendererSurface> clipped;
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped));
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
|
||||
getter_AddRefs(clipped));
|
||||
|
||||
canvas->PushSurface(clipped);
|
||||
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
|
||||
|
||||
@ -66,6 +66,7 @@
|
||||
#include "nsSVGPoint.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsISVGOuterSVGFrame.h"
|
||||
#include "nsISVGRendererCanvas.h"
|
||||
|
||||
#if defined(MOZ_SVG_RENDERER_GDIPLUS)
|
||||
#include <windows.h>
|
||||
@ -397,21 +398,11 @@ nsSVGUtils::TransformPoint(nsIDOMSVGMatrix *matrix,
|
||||
|
||||
nsresult
|
||||
nsSVGUtils::GetSurface(nsISVGOuterSVGFrame *aOuterSVGFrame,
|
||||
nsISVGRendererCanvas *aCanvas,
|
||||
nsISVGRendererSurface **aSurface)
|
||||
{
|
||||
if (!aOuterSVGFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIFrame *frame = nsnull;
|
||||
CallQueryInterface(aOuterSVGFrame, &frame);
|
||||
|
||||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsSize size = frame->GetSize();
|
||||
float p2t = frame->GetPresContext()->ScaledPixelsToTwips();
|
||||
PRUint32 width = (PRUint32)ceil(size.width/p2t);
|
||||
PRUint32 height = (PRUint32)ceil(size.height/p2t);
|
||||
PRUint32 width, height;
|
||||
aCanvas->GetSurfaceSize(&width, &height);
|
||||
|
||||
nsCOMPtr<nsISVGRenderer> renderer;
|
||||
aOuterSVGFrame->GetRenderer(getter_AddRefs(renderer));
|
||||
|
||||
@ -59,6 +59,7 @@ class nsIURI;
|
||||
class nsISVGOuterSVGFrame;
|
||||
class nsISVGRendererSurface;
|
||||
class nsIPresShell;
|
||||
class nsISVGRendererCanvas;
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
@ -142,8 +143,9 @@ public:
|
||||
static float
|
||||
AngleBisect(float a1, float a2);
|
||||
|
||||
/* Generate a new rendering surface the size of the outer svg frame */
|
||||
/* Generate a new rendering surface the size of the current surface */
|
||||
static nsresult GetSurface(nsISVGOuterSVGFrame *aOuterSVGFrame,
|
||||
nsISVGRendererCanvas *aCanvas,
|
||||
nsISVGRendererSurface **aSurface);
|
||||
|
||||
private:
|
||||
|
||||
@ -69,7 +69,7 @@ interface nsISVGRendererSurface;
|
||||
* Mozilla-native rendering object with a call to
|
||||
* nsISVGRenderer::createCanvas().
|
||||
*/
|
||||
[scriptable, uuid(9cdf3f86-a511-4948-83f8-e25460f03b83)]
|
||||
[scriptable, uuid(a1ea0d56-765f-43be-88dc-e54576e5735b)]
|
||||
interface nsISVGRendererCanvas : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -133,6 +133,11 @@ interface nsISVGRendererCanvas : nsISupports
|
||||
void pushSurface(in nsISVGRendererSurface surface);
|
||||
void popSurface();
|
||||
|
||||
/**
|
||||
* Get the current drawing surface dimensions.
|
||||
*/
|
||||
void getSurfaceSize(out unsigned long width, out unsigned long height);
|
||||
|
||||
/**
|
||||
* Surface composition.
|
||||
*/
|
||||
|
||||
@ -701,6 +701,12 @@ nsSVGCairoCanvas::SetClipRect(nsIDOMSVGMatrix *aCTM, float aX, float aY,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct ctxEntry {
|
||||
cairo_t *mCR;
|
||||
PRUint32 mWidth;
|
||||
PRUint32 mHeight;
|
||||
};
|
||||
|
||||
/** Implements pushSurface(in nsISVGRendererSurface surface); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
|
||||
@ -709,11 +715,19 @@ nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
|
||||
if (!cairoSurface)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
cairo_t* oldCR = mCR;
|
||||
mContextStack.AppendElement(NS_STATIC_CAST(void*, oldCR));
|
||||
ctxEntry *ctx = new ctxEntry;
|
||||
if (!ctx)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
ctx->mCR = mCR;
|
||||
ctx->mWidth = mWidth;
|
||||
ctx->mHeight = mHeight;
|
||||
|
||||
mContextStack.AppendElement(NS_STATIC_CAST(void*, ctx));
|
||||
|
||||
mCR = cairo_create(cairoSurface->GetSurface());
|
||||
// XXX Copy state over from oldCR?
|
||||
aSurface->GetWidth(&mWidth);
|
||||
aSurface->GetHeight(&mHeight);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -725,13 +739,25 @@ nsSVGCairoCanvas::PopSurface()
|
||||
PRUint32 count = mContextStack.Count();
|
||||
if (count != 0) {
|
||||
cairo_destroy(mCR);
|
||||
mCR = NS_STATIC_CAST(cairo_t*, mContextStack[count - 1]);
|
||||
ctxEntry *ctx = NS_STATIC_CAST(ctxEntry*, mContextStack[count - 1]);
|
||||
mCR = ctx->mCR;
|
||||
mWidth = ctx->mWidth;
|
||||
mHeight = ctx->mHeight;
|
||||
delete ctx;
|
||||
mContextStack.RemoveElementAt(count - 1);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGCairoCanvas::GetSurfaceSize(PRUint32 *aWidth, PRUint32 *aHeight)
|
||||
{
|
||||
*aWidth = mWidth;
|
||||
*aHeight = mHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** Implements void compositeSurface(in nsISVGRendererSurface surface,
|
||||
in unsigned long x, in unsigned long y,
|
||||
in float opacity); */
|
||||
|
||||
@ -455,6 +455,13 @@ nsSVGGDIPlusCanvas::PopSurface()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGDIPlusCanvas::GetSurfaceSize(PRUint32 *aWidth, PRUint32 *aHeight)
|
||||
{
|
||||
// XXX
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/** Implements void compositeSurface(in nsISVGRendererSurface surface,
|
||||
in unsigned long x, in unsigned long y,
|
||||
in float opacity); */
|
||||
|
||||
@ -410,6 +410,13 @@ nsSVGLibartCanvas::PopSurface()
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartCanvas::GetSurfaceSize(PRUint32 *aWidth, PRUint32 *aHeight)
|
||||
{
|
||||
// XXX
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/** Implements void compositeSurface(in nsISVGRendererSurface surface,
|
||||
in unsigned long x, in unsigned long y,
|
||||
in float opacity); */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user