From f3d5be38992c72bc2b6f119b42e25f6377696f69 Mon Sep 17 00:00:00 2001 From: "tor%cs.brown.edu" Date: Mon, 22 Jan 2007 23:19:54 +0000 Subject: [PATCH] Bug 367557 - correct filter/pattern surface refcount. r=vlad, sr=roc --- layout/svg/base/src/nsSVGFilterFrame.cpp | 42 +++++++++++----------- layout/svg/base/src/nsSVGPatternFrame.cpp | 43 ++++++++++------------- layout/svg/base/src/nsSVGPatternFrame.h | 1 - 3 files changed, 39 insertions(+), 47 deletions(-) diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp index faca3dcad28c..5729dc2e8427 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.cpp +++ b/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -49,6 +49,7 @@ #include "nsSVGContainerFrame.h" #include "gfxASurface.h" #include "gfxContext.h" +#include "gfxImageSurface.h" typedef nsSVGContainerFrame nsSVGFilterFrameBase; @@ -359,26 +360,18 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, aTarget->NotifyCanvasTMChanged(PR_TRUE); // paint the target geometry - cairo_surface_t *surface = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - filterResX, filterResY); - if (!surface) { + nsRefPtr tmpSurface = + new gfxImageSurface(gfxASurface::ImageFormatARGB32, + filterResX, filterResY); + if (!tmpSurface) { FilterFailCleanup(aContext, aTarget); return NS_OK; } - gfxUnknownSurface tmpSurface(surface); - gfxContext tmpContext(&tmpSurface); - - // thebes types don't like being stack allocated - addref the surface - // so that gfxContext doesn't try destroying it (scope will delete it) - tmpSurface.AddRef(); - - // tmpSurface now owns the cairo surface - cairo_surface_destroy(surface); - + gfxContext tmpContext(tmpSurface); nsSVGRenderState tmpState(&tmpContext); + memset(tmpSurface->Data(), 0, tmpSurface->Height() * tmpSurface->Stride()); aTarget->PaintSVG(&tmpState, nsnull); mPrimitiveUnits->GetAnimVal(&type); @@ -397,9 +390,9 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, return NS_OK; } - PRUint8 *data = cairo_image_surface_get_data(surface); + PRUint8 *data = tmpSurface->Data(); PRUint8 *alphaData = cairo_image_surface_get_data(alpha); - PRUint32 stride = cairo_image_surface_get_stride(surface); + PRUint32 stride = tmpSurface->Stride(); for (PRUint32 yy=0; yyCairoSurface(), nsRect(0, 0, filterResX, filterResY)); for (PRUint32 k=0; k resultSurface; instance.LookupImage(NS_LITERAL_STRING(""), &filterResult, &filterRect); + if (filterResult) + resultSurface = gfxASurface::Wrap(filterResult); + if (!resultSurface) { + FilterFailCleanup(aContext, aTarget); + return NS_OK; + } + nsCOMPtr scale, fini; NS_NewSVGMatrix(getter_AddRefs(scale), width/filterResX, 0.0f, @@ -441,10 +443,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, ctm->Multiply(scale, getter_AddRefs(fini)); - gfxUnknownSurface resultSurface(filterResult); - nsSVGUtils::CompositeSurfaceMatrix(aContext->GetGfxContext(), - &resultSurface, fini, 1.0); + resultSurface, fini, 1.0); aTarget->SetOverrideCTM(nsnull); aTarget->SetMatrixPropagation(PR_TRUE); diff --git a/layout/svg/base/src/nsSVGPatternFrame.cpp b/layout/svg/base/src/nsSVGPatternFrame.cpp index b13683ac3719..1749dfcb4d47 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.cpp +++ b/layout/svg/base/src/nsSVGPatternFrame.cpp @@ -53,8 +53,8 @@ #include "nsSVGPatternElement.h" #include "nsSVGGeometryFrame.h" #include "nsSVGPatternFrame.h" -#include "gfxASurface.h" #include "gfxContext.h" +#include "gfxImageSurface.h" #ifdef DEBUG_scooter static void printCTM(char *msg, nsIDOMSVGMatrix *aCTM); @@ -281,17 +281,22 @@ nsSVGPatternFrame::PaintPattern(cairo_surface_t** surface, // Now that we have all of the necessary geometries, we can // create our surface. - cairo_surface_t *patternSurface = CreateSurface(bbox); - if (!patternSurface) + float surfaceWidth, surfaceHeight; + bbox->GetWidth(&surfaceWidth); + bbox->GetHeight(&surfaceHeight); + +#ifdef DEBUG_scooter + printf("Creating %dX%d surface\n",(int)(surfaceWidth),(int)(surfaceHeight)); +#endif + + nsRefPtr tmpSurface = + new gfxImageSurface(gfxASurface::ImageFormatARGB32, + (int)surfaceWidth, (int)surfaceHeight); + if (!tmpSurface) return NS_ERROR_FAILURE; - gfxUnknownSurface tmpSurface(patternSurface); - gfxContext tmpContext(&tmpSurface); - - // thebes types don't like being stack allocated - addref the surface - // so that gfxContext doesn't try destroying it (scope will delete it) - tmpSurface.AddRef(); - + memset(tmpSurface->Data(), 0, tmpSurface->Height() * tmpSurface->Stride()); + gfxContext tmpContext(tmpSurface); nsSVGRenderState tmpState(&tmpContext); // OK, now render -- note that we use "firstKid", which @@ -308,7 +313,9 @@ nsSVGPatternFrame::PaintPattern(cairo_surface_t** surface, } mSource = nsnull; - *surface = patternSurface; + // caller now owns the cairo surface + cairo_surface_reference(tmpSurface->CairoSurface()); + *surface = tmpSurface->CairoSurface(); return NS_OK; } @@ -773,20 +780,6 @@ nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM, return NS_OK; } -cairo_surface_t * -nsSVGPatternFrame::CreateSurface(nsIDOMSVGRect *bbox) -{ - float width, height; - bbox->GetWidth(&width); - bbox->GetHeight(&height); - -#ifdef DEBUG_scooter - printf("Creating %dX%d surface\n",(int)(width),(int)(height)); -#endif - return cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - (int)(width), (int)(height)); -} - //---------------------------------------------------------------------- // nsSVGPaintServerFrame methods: diff --git a/layout/svg/base/src/nsSVGPatternFrame.h b/layout/svg/base/src/nsSVGPatternFrame.h index bb38f7e14e3f..fa3793f1e016 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.h +++ b/layout/svg/base/src/nsSVGPatternFrame.h @@ -140,7 +140,6 @@ protected: nsIDOMSVGRect *bbox, nsIDOMSVGMatrix *callerCTM); nsresult ConstructCTM(nsIDOMSVGMatrix **ctm, nsIDOMSVGRect *callerBBox); - cairo_surface_t *CreateSurface(nsIDOMSVGRect *bbox); nsresult GetCallerGeometry(nsIDOMSVGMatrix **aCTM, nsIDOMSVGRect **aBBox, nsSVGElement **aContent,