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:
tor%cs.brown.edu 2006-01-30 17:53:26 +00:00
parent 39d0ee60a3
commit cbc768243c
11 changed files with 97 additions and 39 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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:

View File

@ -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.
*/

View File

@ -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); */

View File

@ -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); */

View File

@ -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); */