Bug 330498 - unify SVG effects (filter, clip, mask, opacity) logic. r+sr=roc

This commit is contained in:
tor%cs.brown.edu 2006-03-21 15:49:20 +00:00
Родитель 81b6cec562
Коммит 6d663c38d3
29 изменённых файлов: 602 добавлений и 1136 удалений

Просмотреть файл

@ -67,7 +67,11 @@ nsSVGValue::NotifyObservers(SVGObserverNotifyFunction f,
modificationType aModType)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; ++i) {
// Since notification might cause the listeners to remove themselves
// from the observer list (mod_die), walk backwards through the list
// to catch everyone.
for (PRInt32 i = count - 1; i >= 0; i--) {
nsIWeakReference* wr = NS_STATIC_CAST(nsIWeakReference*,mObservers.ElementAt(i));
nsCOMPtr<nsISVGValueObserver> observer = do_QueryReferent(wr);
if (observer)

Просмотреть файл

@ -51,22 +51,14 @@ class nsIDOMSVGMatrix;
struct nsRect;
#define NS_ISVGCHILDFRAME_IID \
{ 0xe3280ee5, 0x0980, 0x45f4, { 0xb4, 0x84, 0xc4, 0x11, 0xbc, 0x36, 0xcd, 0xda } }
{ 0x2a5b5908, 0x8b2a, 0x4991, { 0x97, 0x2e, 0xe4, 0x5f, 0x0a, 0xb2, 0x14, 0x9a } }
class nsISVGChildFrame : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGCHILDFRAME_IID)
// XXX Ideally we don't want to pass the dirtyRect along but extract
// it from nsIRenderingContext where needed (only in foreign
// objects) dirtyRectTwips is the unmodified region passed to the
// outer svg frame's ::Paint. ignoreFilter tells the frame if it
// should ignore any filter attribute set, as filters need to call
// back to the frame to render source image(s).
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)=0;
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas)=0;
// Check if this frame or children contain the given point,
// specified in device pixels relative to the origin of the outer
@ -96,10 +88,6 @@ public:
// XXX move this function into interface nsISVGLocatableMetrics
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval)=0; // bbox in local coords
// Get the filtered invalidation area for this frame. Null return
// if frame is not directly filtered.
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval)=0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGChildFrame, NS_ISVGCHILDFRAME_IID)

Просмотреть файл

@ -197,7 +197,7 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas,
else {
rv = canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP_MASK);
canvas->PushSurface(aClipSurface);
canvas->PushSurface(aClipSurface, PR_TRUE);
}
if (NS_FAILED(rv))
@ -208,7 +208,7 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas,
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
SVGFrame->PaintSVG(canvas, dirty, PR_TRUE);
SVGFrame->PaintSVG(canvas);
}
}

Просмотреть файл

@ -194,9 +194,7 @@ nsSVGDefsFrame::AttributeChanged(PRInt32 aNameSpaceID,
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGDefsFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGDefsFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
// defs don't paint

Просмотреть файл

@ -94,9 +94,7 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -106,10 +104,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM) { return NS_ERROR_FAILURE; }
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = nsnull;
return NS_OK;
}
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();

Просмотреть файл

@ -269,8 +269,7 @@ nsSVGFilterFrame::FilterFailCleanup(nsISVGRendererCanvas *aCanvas,
aTarget->SetOverrideCTM(nsnull);
aTarget->SetMatrixPropagation(PR_TRUE);
aTarget->NotifyCanvasTMChanged(PR_TRUE);
nsRect dummyRect;
aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE);
aTarget->PaintSVG(aCanvas);
}
NS_IMETHODIMP
@ -308,8 +307,7 @@ nsSVGFilterFrame::FilterPaint(nsISVGRendererCanvas *aCanvas,
if (unimplementedFilter)
fprintf(stderr, "FilterFrame: unimplemented filter element\n");
#endif
nsRect dummyRect;
aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE);
aTarget->PaintSVG(aCanvas);
return NS_OK;
}
@ -401,9 +399,8 @@ nsSVGFilterFrame::FilterPaint(nsISVGRendererCanvas *aCanvas,
return NS_OK;
}
aCanvas->PushSurface(surface);
nsRect dummyRect;
aTarget->PaintSVG(aCanvas, dummyRect, PR_TRUE);
aCanvas->PushSurface(surface, PR_FALSE);
aTarget->PaintSVG(aCanvas);
aCanvas->PopSurface();
mPrimitiveUnits->GetAnimVal(&type);

Просмотреть файл

@ -60,12 +60,12 @@
#include "nsLayoutUtils.h"
#include "nsSVGUtils.h"
#include "nsIURI.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGPoint.h"
#include "nsSVGRect.h"
#include "nsSVGMatrix.h"
#include "nsINameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsISVGRendererSurface.h"
//----------------------------------------------------------------------
// Implementation
@ -85,19 +85,12 @@ NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent)
}
nsSVGForeignObjectFrame::nsSVGForeignObjectFrame()
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE), mFilter(nsnull)
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE)
{
AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT |
NS_FRAME_REFLOW_ROOT);
}
nsSVGForeignObjectFrame::~nsSVGForeignObjectFrame()
{
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
}
nsresult nsSVGForeignObjectFrame::Init()
{
nsCOMPtr<nsIDOMSVGForeignObjectElement> foreignObject = do_QueryInterface(mContent);
@ -271,6 +264,13 @@ nsSVGForeignObjectFrame::AttributeChanged(PRInt32 aNameSpaceID,
return NS_OK;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}
//----------------------------------------------------------------------
// nsISVGValueObserver methods:
@ -278,20 +278,8 @@ NS_IMETHODIMP
nsSVGForeignObjectFrame::WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
// need to handle filters because we might be the topmost filtered frame and
// the filter region could be changing.
if (filter && mFilterRegion) {
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::WillModifyEffects(this, observable, aModType);
return NS_OK;
}
@ -301,29 +289,7 @@ nsSVGForeignObjectFrame::DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
Update();
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
if (mFilter)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
if (region)
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::DidModifyEffects(this, observable, aModType);
return NS_OK;
}
@ -377,33 +343,14 @@ TransformRect(float* aX, float *aY, float* aWidth, float *aHeight,
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
nsresult rv = NS_OK;
if (mIsDirty) {
nsCOMPtr<nsISVGRendererRegion> region = DoReflow();
}
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
nsCOMPtr<nsIURI> aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
nsRect dirtyRect = nsRect(nsPoint(0, 0), GetSize());
nsCOMPtr<nsIDOMSVGMatrix> tm = GetTMIncludingOffset();
nsCOMPtr<nsIDOMSVGMatrix> inverse;

Просмотреть файл

@ -62,7 +62,6 @@ class nsSVGForeignObjectFrame : public nsSVGForeignObjectFrameBase,
NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent);
protected:
nsSVGForeignObjectFrame();
virtual ~nsSVGForeignObjectFrame();
nsresult Init();
// nsISupports interface:
@ -96,6 +95,8 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType);
NS_IMETHOD DidSetStyleContext();
/**
* Get the "type" of the frame
*
@ -124,9 +125,7 @@ public:
// implementation inherited from nsSupportsWeakReference
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -136,11 +135,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = mFilterRegion;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
// nsISVGContainerFrame interface:
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
@ -171,9 +165,6 @@ protected:
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
PRPackedBool mPropagateTransform;
PRPackedBool mIsDirty;
};

Просмотреть файл

@ -48,9 +48,7 @@
#include "nsISVGRendererCanvas.h"
#include "nsLayoutAtoms.h"
#include "nsSVGUtils.h"
#include "nsSVGFilterFrame.h"
#include "nsISVGValueUtils.h"
#include "nsSVGMaskFrame.h"
NS_INTERFACE_MAP_BEGIN(nsSVGGFrame)
NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
@ -80,183 +78,30 @@ nsSVGGFrame::GetType() const
return nsLayoutAtoms::svgGFrame;
}
nsSVGGFrame::~nsSVGGFrame()
{
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
}
//----------------------------------------------------------------------
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
if (display->mOpacity == 0.0)
return NS_OK;
nsIURI *aURI;
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
/* check for a clip path */
PRBool trivialClip = PR_TRUE;
nsISVGClipPathFrame *clip = NULL;
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI) {
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
clip->IsTrivial(&trivialClip);
if (trivialClip) {
canvas->PushClip();
} else {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipMaskSurface));
if (!clipMaskSurface)
clip = nsnull;
}
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
}
}
}
/* check for mask */
nsISVGMaskFrame *mask = nsnull;
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
aURI = GetStyleSVGReset()->mMask;
if (aURI) {
NS_GetSVGMaskFrame(&mask, aURI, mContent);
if (mask) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskSurface));
if (maskSurface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix,
display->mOpacity)))
maskSurface = nsnull;
}
}
}
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskedSurface));
if (maskedSurface) {
canvas->PushSurface(maskedSurface);
} else
maskSurface = nsnull;
}
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
nsSVGUtils::PaintChildWithEffects(canvas, kid);
}
if (maskedSurface)
canvas->PopSurface();
if (clipMaskSurface) {
if (!maskSurface && display->mOpacity == 1.0) {
maskSurface = clipMaskSurface;
} else {
nsCOMPtr<nsISVGRendererSurface> clipped;
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipped));
canvas->PushSurface(clipped);
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
canvas->PopSurface();
maskedSurface = clipped;
}
}
if (maskSurface)
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
else if (display->mOpacity != 1.0)
canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity);
if (clip && trivialClip)
canvas->PopClip();
return NS_OK;
}
NS_IMETHODIMP
nsSVGGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
*hit = nsnull;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
nsIFrame* temp=nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
if (NS_SUCCEEDED(rv) && temp) {
*hit = temp;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
}
nsSVGUtils::HitTestChildren(this, x, y, hit);
if (*hit) {
PRBool clipHit = PR_TRUE;;
nsIURI *aURI;
nsISVGClipPathFrame *clip = NULL;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI)
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
clip->ClipHitTest(this, matrix, x, y, &clipHit);
}
if (!clipHit)
*hit = nsnull;
}
return *hit ? NS_OK : NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
@ -328,21 +173,7 @@ NS_IMETHODIMP
nsSVGGFrame::WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
// need to handle filters because we might be the topmost filtered frame and
// the filter region could be changing.
if (filter && mFilterRegion) {
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::WillModifyEffects(this, observable, aModType);
return NS_OK;
}
@ -350,28 +181,13 @@ NS_IMETHODIMP
nsSVGGFrame::DidModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
if (mFilter)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
if (region)
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::DidModifyEffects(this, observable, aModType);
return NS_OK;
}
NS_IMETHODIMP
nsSVGGFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}

Просмотреть файл

@ -52,9 +52,7 @@ class nsSVGGFrame : public nsSVGGFrameBase,
public nsSupportsWeakReference
{
public:
nsSVGGFrame() : mFilter(nsnull), mPropagateTransform(PR_TRUE) {}
virtual ~nsSVGGFrame();
nsSVGGFrame() : mPropagateTransform(PR_TRUE) {}
/**
* Get the "type" of the frame
@ -79,20 +77,16 @@ protected:
friend nsIFrame*
NS_NewSVGGFrame(nsIPresShell* aPresShell, nsIContent* aContent);
// nsIFrame interface:
NS_IMETHOD DidSetStyleContext();
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = mFilterRegion;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
@ -105,9 +99,6 @@ protected:
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
PRPackedBool mPropagateTransform;
};

Просмотреть файл

@ -186,9 +186,7 @@ nsSVGGenericContainerFrame::IsFrameOfType(PRUint32 aFlags) const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
#ifdef DEBUG
// printf("nsSVGGenericContainer(%p)::Paint\n", this);
@ -198,7 +196,7 @@ nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas,
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
SVGFrame->PaintSVG(canvas);
}
return NS_OK;
@ -207,26 +205,9 @@ nsSVGGenericContainerFrame::PaintSVG(nsISVGRendererCanvas* canvas,
NS_IMETHODIMP
nsSVGGenericContainerFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
#ifdef DEBUG
// printf("nsSVGGenericContainerFrame(%p)::GetFrameForPoint\n", this);
#endif
*hit = nsnull;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
nsIFrame* temp=nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
if (NS_SUCCEEDED(rv) && temp) {
*hit = temp;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
}
return *hit ? NS_OK : NS_ERROR_FAILURE;
nsSVGUtils::HitTestChildren(this, x, y, hit);
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)

Просмотреть файл

@ -100,9 +100,7 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -112,10 +110,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM) { return NS_ERROR_FAILURE; }
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = nsnull;
return NS_OK;
}
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();

Просмотреть файл

@ -132,9 +132,7 @@ public:
nsISVGValue::modificationType aModType);
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -144,10 +142,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_OK; }
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM) { return NS_ERROR_FAILURE; }
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = nsnull;
return NS_OK;
}
// nsISVGGeometrySource interface:
NS_DECL_NSISVGGEOMETRYSOURCE
@ -482,9 +476,7 @@ nsSVGGlyphFrame::DidModifySVGObservable (nsISVGValue* observable,
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
#ifdef DEBUG
//printf("nsSVGGlyphFrame(%p)::Paint\n", this);

Просмотреть файл

@ -135,9 +135,7 @@ public:
// nsISVGChildFrame interface:
// Override PaintSVG (our frames don't directly render)
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter) {return NS_OK;}
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas) {return NS_OK;}
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const

Просмотреть файл

@ -53,12 +53,9 @@
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "imgIRequest.h"
#include "nsSVGClipPathFrame.h"
#include "nsLayoutAtoms.h"
#include "nsISVGValueUtils.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGUtils.h"
#include "nsSVGMaskFrame.h"
#include "nsINameSpaceManager.h"
#include "nsGkAtoms.h"
@ -102,9 +99,7 @@ public:
NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder);
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
// nsISVGGeometrySource interface:
NS_IMETHOD GetStrokePaintType(PRUint16 *aStrokePaintType);
@ -286,33 +281,11 @@ NS_IMETHODIMP nsSVGImageFrame::ConstructPath(nsISVGRendererPathBuilder* pathBuil
//----------------------------------------------------------------------
// nsISVGChildFrame methods:
NS_IMETHODIMP
nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
nsIURI *aURI;
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
if (mSurfaceInvalid) {
nsCOMPtr<imgIRequest> currentRequest;
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
@ -336,71 +309,6 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
}
}
canvas->PushClip();
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
/* check for a clip path */
PRBool trivialClip = PR_TRUE;
nsISVGClipPathFrame *clip = NULL;
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI) {
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
clip->IsTrivial(&trivialClip);
if (trivialClip) {
canvas->PushClip();
} else {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipMaskSurface));
if (!clipMaskSurface)
clip = nsnull;
}
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix;
GetCanvasTM(getter_AddRefs(matrix));
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
}
}
}
/* check for mask */
nsISVGMaskFrame *mask = nsnull;
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
aURI = GetStyleSVGReset()->mMask;
if (aURI) {
NS_GetSVGMaskFrame(&mask, aURI, mContent);
if (mask) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskSurface));
if (maskSurface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix;
GetCanvasTM(getter_AddRefs(matrix));
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix)))
maskSurface = nsnull;
}
}
}
if (maskSurface || clipMaskSurface) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskedSurface));
if (maskedSurface) {
canvas->PushSurface(maskedSurface);
} else
maskSurface = nsnull;
}
if (mSurface) {
nsCOMPtr<nsIDOMSVGMatrix> ctm;
GetCanvasTM(getter_AddRefs(ctm));
@ -435,29 +343,6 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas,
mStyleContext->GetStyleDisplay()->mOpacity);
}
if (maskedSurface)
canvas->PopSurface();
if (clipMaskSurface) {
if (!maskSurface) {
maskSurface = clipMaskSurface;
} else {
nsCOMPtr<nsISVGRendererSurface> clipped;
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipped));
canvas->PushSurface(clipped);
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
canvas->PopSurface();
maskedSurface = clipped;
}
}
if (maskSurface)
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
canvas->PopClip();
return NS_OK;
}

Просмотреть файл

@ -58,7 +58,6 @@
#include "nsISVGValueUtils.h"
#include "nsSVGUtils.h"
#include "nsSVGClipPathFrame.h"
#include "nsSVGMaskFrame.h"
#include "nsISVGRendererSurface.h"
#include "nsGkAtoms.h"
@ -75,7 +74,6 @@ class nsSVGInnerSVGFrame : public nsSVGInnerSVGFrameBase,
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent);
protected:
nsSVGInnerSVGFrame();
virtual ~nsSVGInnerSVGFrame();
nsresult Init();
// nsISupports interface:
@ -97,6 +95,7 @@ public:
nsIFrame* aParent,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD DidSetStyleContext();
// We don't define an AttributeChanged method since changes to the
// 'x', 'y', 'width' and 'height' attributes of our content object
@ -118,9 +117,7 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -130,11 +127,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = mFilterRegion;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
@ -162,9 +154,6 @@ protected:
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
PRPackedBool mPropagateTransform;
};
@ -177,24 +166,13 @@ NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent)
return new (aPresShell) nsSVGInnerSVGFrame;
}
nsSVGInnerSVGFrame::nsSVGInnerSVGFrame() : mFilter(nsnull),
mPropagateTransform(PR_TRUE)
nsSVGInnerSVGFrame::nsSVGInnerSVGFrame() : mPropagateTransform(PR_TRUE)
{
#ifdef DEBUG
// printf("nsSVGInnerSVGFrame CTOR\n");
#endif
}
nsSVGInnerSVGFrame::~nsSVGInnerSVGFrame()
{
#ifdef DEBUG
// printf("~nsSVGInnerSVGFrame\n");
#endif
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
}
nsresult nsSVGInnerSVGFrame::Init()
{
NS_ASSERTION(mParent, "no parent");
@ -338,37 +316,12 @@ nsSVGInnerSVGFrame::IsFrameOfType(PRUint32 aFlags) const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
#ifdef DEBUG
// printf("nsSVGInnerSVG(%p)::Paint\n", this);
#endif
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
nsIURI *aURI;
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
canvas->PushClip();
if (GetStyleDisplay()->IsScrollableOverflow()) {
@ -400,97 +353,11 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
canvas->SetClipRect(clipTransform, x, y, width, height);
}
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
/* check for a clip path */
PRBool trivialClip = PR_TRUE;
nsISVGClipPathFrame *clip = NULL;
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI) {
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
clip->IsTrivial(&trivialClip);
if (!trivialClip) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipMaskSurface));
if (!clipMaskSurface)
clip = nsnull;
}
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
}
}
}
/* check for mask */
nsISVGMaskFrame *mask = nsnull;
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
aURI = GetStyleSVGReset()->mMask;
if (aURI) {
NS_GetSVGMaskFrame(&mask, aURI, mContent);
if (mask) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskSurface));
if (maskSurface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix,
display->mOpacity)))
maskSurface = nsnull;
}
}
}
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskedSurface));
if (maskedSurface) {
canvas->PushSurface(maskedSurface);
} else
maskSurface = nsnull;
}
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
nsSVGUtils::PaintChildWithEffects(canvas, kid);
}
if (maskedSurface)
canvas->PopSurface();
if (clipMaskSurface) {
if (!maskSurface && display->mOpacity == 1.0) {
maskSurface = clipMaskSurface;
} else {
nsCOMPtr<nsISVGRendererSurface> clipped;
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipped));
canvas->PushSurface(clipped);
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
canvas->PopSurface();
maskedSurface = clipped;
}
}
if (maskSurface)
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
else if (display->mOpacity != 1.0)
canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity);
canvas->PopClip();
return NS_OK;
@ -499,26 +366,9 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
NS_IMETHODIMP
nsSVGInnerSVGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
#ifdef DEBUG
// printf("nsSVGInnerSVGFrame(%p)::GetFrameForPoint\n", this);
#endif
*hit = nsnull;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
nsIFrame* temp=nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
if (NS_SUCCEEDED(rv) && temp) {
*hit = temp;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
}
return *hit ? NS_OK : NS_ERROR_FAILURE;
nsSVGUtils::HitTestChildren(this, x, y, hit);
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
@ -791,21 +641,7 @@ NS_IMETHODIMP
nsSVGInnerSVGFrame::WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
// need to handle filters because we might be the topmost filtered frame and
// the filter region could be changing.
if (filter && mFilterRegion) {
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::WillModifyEffects(this, observable, aModType);
return NS_OK;
}
@ -816,27 +652,18 @@ nsSVGInnerSVGFrame::DidModifySVGObservable (nsISVGValue* observable,
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
nsSVGUtils::DidModifyEffects(this, observable, aModType);
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
if (mFilter)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
if (region)
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
} else {
if (!filter) {
NotifyViewportChange();
}
return NS_OK;
}
NS_IMETHODIMP
nsSVGInnerSVGFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}

Просмотреть файл

@ -377,14 +377,13 @@ nsSVGMarkerFrame::PaintMark(nsISVGRendererCanvas *aCanvas,
}
}
nsRect dirtyRectTwips;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
SVGFrame->NotifyCanvasTMChanged(PR_TRUE);
SVGFrame->PaintSVG(aCanvas, dirtyRectTwips, PR_FALSE);
nsSVGUtils::PaintChildWithEffects(aCanvas, kid);
}
}

Просмотреть файл

@ -237,7 +237,7 @@ nsSVGMaskFrame::MaskPaint(nsISVGRendererCanvas* aCanvas,
{
nsRect dirty;
if (NS_FAILED(aCanvas->PushSurface(aSurface)))
if (NS_FAILED(aCanvas->PushSurface(aSurface, PR_TRUE)))
return NS_ERROR_FAILURE;
{
@ -300,11 +300,7 @@ nsSVGMaskFrame::MaskPaint(nsISVGRendererCanvas* aCanvas,
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
SVGFrame->PaintSVG(aCanvas, dirty, PR_TRUE);
}
nsSVGUtils::PaintChildWithEffects(aCanvas, kid);
}
aCanvas->PopSurface();

Просмотреть файл

@ -635,23 +635,10 @@ nsSVGOuterSVGFrame::GetFrameForPoint(const nsPoint& aPoint)
return nsnull;
}
nsIFrame* frame = this;
nsIFrame* hit = nsnull;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &hit);
if (NS_SUCCEEDED(rv) && hit) {
frame = hit;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
}
nsIFrame* hit;
nsSVGUtils::HitTestChildren(this, x, y, &hit);
return frame;
return hit;
}
//----------------------------------------------------------------------
@ -737,10 +724,7 @@ nsSVGOuterSVGFrame::Paint(nsIRenderingContext& aRenderingContext,
// paint children:
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRect, PR_FALSE);
nsSVGUtils::PaintChildWithEffects(canvas, kid);
}
canvas->Flush();

Просмотреть файл

@ -70,9 +70,7 @@
// nsSVGPathGeometryFrame
nsSVGPathGeometryFrame::nsSVGPathGeometryFrame()
: mFilter(nsnull), mUpdateFlags(0), mPropagateTransform(PR_TRUE),
mFillGradient(nsnull), mStrokeGradient(nsnull),
mFillPattern(nsnull), mStrokePattern(nsnull)
: mUpdateFlags(0), mPropagateTransform(PR_TRUE)
{
#ifdef DEBUG
// printf("nsSVGPathGeometryFrame %p CTOR\n", this);
@ -91,9 +89,6 @@ nsSVGPathGeometryFrame::~nsSVGPathGeometryFrame()
if (mStrokeGradient) {
NS_REMOVE_SVGVALUE_OBSERVER(mStrokeGradient);
}
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
if (mFillPattern) {
NS_REMOVE_SVGVALUE_OBSERVER(mFillPattern);
}
@ -162,10 +157,6 @@ nsSVGPathGeometryFrame::DidSetStyleContext()
NS_REMOVE_SVGVALUE_OBSERVER(mStrokeGradient);
mStrokeGradient = nsnull;
}
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
mFilter = nsnull;
}
if (mFillPattern) {
NS_REMOVE_SVGVALUE_OBSERVER(mFillPattern);
mFillPattern = nsnull;
@ -174,6 +165,7 @@ nsSVGPathGeometryFrame::DidSetStyleContext()
NS_REMOVE_SVGVALUE_OBSERVER(mStrokePattern);
mStrokePattern = nsnull;
}
nsSVGUtils::StyleEffects(this);
// XXX: we'd like to use the style_hint mechanism and the
// ContentStateChanged/AttributeChanged functions for style changes
@ -225,156 +217,46 @@ nsSVGPathGeometryFrame::GetMarkerFrames(nsISVGMarkerFrame **markerStart,
}
NS_IMETHODIMP
nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
nsIURI *aURI;
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
/* check for a clip path */
PRBool trivialClip = PR_TRUE;
nsISVGClipPathFrame *clip = NULL;
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI) {
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
clip->IsTrivial(&trivialClip);
if (trivialClip) {
canvas->PushClip();
} else {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipMaskSurface));
if (!clipMaskSurface)
clip = nsnull;
}
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix;
GetCanvasTM(getter_AddRefs(matrix));
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
}
}
}
/* check for mask */
nsISVGMaskFrame *mask = nsnull;
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
aURI = GetStyleSVGReset()->mMask;
if (aURI) {
NS_GetSVGMaskFrame(&mask, aURI, mContent);
if (mask) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskSurface));
if (maskSurface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix;
GetCanvasTM(getter_AddRefs(matrix));
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix)))
maskSurface = nsnull;
}
}
}
if (maskSurface || clipMaskSurface) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskedSurface));
if (maskedSurface) {
canvas->PushSurface(maskedSurface);
} else
maskSurface = nsnull;
}
/* render */
GetGeometry()->Render(canvas);
nsISVGMarkable *markable;
CallQueryInterface(this, &markable);
if (markable) {
nsISVGMarkerFrame *markerEnd, *markerMid, *markerStart;
GetMarkerFrames(&markerStart, &markerMid, &markerEnd);
if (markerEnd || markerMid || markerStart) {
// need to set this up with the first draw
if (!mMarkerRegion)
mMarkerRegion = GetCoveredRegion();
float strokeWidth;
GetStrokeWidth(&strokeWidth);
nsVoidArray marks;
markable->GetMarkPoints(&marks);
PRUint32 num = marks.Count();
if (num && markerStart)
markerStart->PaintMark(canvas, this, (nsSVGMark *)marks[0], strokeWidth);
if (num && markerMid)
for (PRUint32 i = 1; i < num - 1; i++)
markerMid->PaintMark(canvas, this, (nsSVGMark *)marks[i], strokeWidth);
if (num && markerEnd)
markerEnd->PaintMark(canvas, this, (nsSVGMark *)marks[num-1], strokeWidth);
}
}
if (maskedSurface)
canvas->PopSurface();
if (clipMaskSurface) {
if (!maskSurface) {
maskSurface = clipMaskSurface;
} else {
nsCOMPtr<nsISVGRendererSurface> clipped;
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipped));
canvas->PushSurface(clipped);
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
canvas->PopSurface();
maskedSurface = clipped;
}
}
if (maskSurface)
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
if (clip && trivialClip)
canvas->PopClip();
return NS_OK;
}
@ -390,24 +272,8 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
PRBool isHit;
GetGeometry()->ContainsPoint(x, y, &isHit);
if (isHit) {
PRBool clipHit = PR_TRUE;;
nsIURI *aURI;
nsISVGClipPathFrame *clip = NULL;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI)
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix;
GetCanvasTM(getter_AddRefs(matrix));
clip->ClipHitTest(this, matrix, x, y, &clipHit);
}
if (clipHit)
*hit = this;
}
if (isHit && nsSVGUtils::HitTestClip(this, x, y))
*hit = this;
return NS_OK;
}
@ -536,20 +402,7 @@ NS_IMETHODIMP
nsSVGPathGeometryFrame::WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
// need to handle filters because we might be the topmost filtered frame and
// the filter region could be changing.
if (filter && mFilterRegion) {
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::WillModifyEffects(this, observable, aModType);
return NS_OK;
}
@ -566,6 +419,8 @@ nsSVGPathGeometryFrame::DidModifySVGObservable (nsISVGValue* observable,
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
nsSVGUtils::DidModifyEffects(this, observable, aModType);
if (gradient) {
// Yes, we need to handle this differently
nsCOMPtr<nsISVGGradient>fill = do_QueryInterface(mFillGradient);
@ -582,10 +437,6 @@ nsSVGPathGeometryFrame::DidModifySVGObservable (nsISVGValue* observable,
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_STROKE_PAINT);
}
} else if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
UpdateGraphic(nsISVGGeometrySource::UPDATEMASK_STROKE_PAINT |
nsISVGGeometrySource::UPDATEMASK_FILL_PAINT);
} else if (pval) {
@ -674,8 +525,7 @@ nsSVGPathGeometryFrame::GetCanvasTM(nsIDOMSVGMatrix * *aCTM)
NS_IMETHODIMP
nsSVGPathGeometryFrame::GetStrokeOpacity(float *aStrokeOpacity)
{
*aStrokeOpacity =
GetStyleSVG()->mStrokeOpacity * GetStyleDisplay()->mOpacity;
*aStrokeOpacity = GetStyleSVG()->mStrokeOpacity;
return NS_OK;
}
@ -766,8 +616,7 @@ nsSVGPathGeometryFrame::GetStrokeMiterlimit(float *aStrokeMiterlimit)
NS_IMETHODIMP
nsSVGPathGeometryFrame::GetFillOpacity(float *aFillOpacity)
{
*aFillOpacity =
GetStyleSVG()->mFillOpacity * GetStyleDisplay()->mOpacity;
*aFillOpacity = GetStyleSVG()->mFillOpacity;
return NS_OK;
}

Просмотреть файл

@ -111,9 +111,7 @@ protected:
nsISVGValue::modificationType aModType);
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -123,11 +121,6 @@ protected:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = mFilterRegion;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference
@ -146,9 +139,7 @@ protected:
void UpdateGraphic(PRUint32 flags, PRBool suppressInvalidation = PR_FALSE);
nsISVGRendererPathGeometry *GetGeometry();
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsCOMPtr<nsISVGRendererRegion> mMarkerRegion;
nsISVGFilterFrame *mFilter;
private:
void GetMarkerFrames(nsISVGMarkerFrame **markerStart,

Просмотреть файл

@ -488,7 +488,7 @@ nsSVGPatternFrame::PaintPattern(nsISVGRendererCanvas* canvas,
getter_AddRefs(patternSurface));
// Push the surface
if (NS_FAILED(canvas->PushSurface(patternSurface)))
if (NS_FAILED(canvas->PushSurface(patternSurface, PR_FALSE)))
return NS_ERROR_FAILURE; //?
if (NS_FAILED(GetPatternMatrix(patternMatrix, bbox, viewRect)))
@ -520,11 +520,7 @@ nsSVGPatternFrame::PaintPattern(nsISVGRendererCanvas* canvas,
nsRect dummyRect;
for (nsIFrame* kid = firstKid; kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame=nsnull;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
SVGFrame->PaintSVG(canvas, dummyRect, PR_FALSE);
}
nsSVGUtils::PaintChildWithEffects(canvas, kid);
}
mSource = nsnull;

Просмотреть файл

@ -278,9 +278,7 @@ nsSVGTSpanFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
#ifdef DEBUG
// printf("nsSVGTSpanFrame(%p)::Paint\n", this);
@ -291,7 +289,7 @@ nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas,
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
SVGFrame->PaintSVG(canvas);
kid = kid->GetNextSibling();
}
@ -301,27 +299,9 @@ nsSVGTSpanFrame::PaintSVG(nsISVGRendererCanvas* canvas,
NS_IMETHODIMP
nsSVGTSpanFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
#ifdef DEBUG
// printf("nsSVGTSpanFrame(%p)::GetFrameForPoint\n", this);
#endif
*hit = nsnull;
nsIFrame* kid = mFrames.FirstChild();
while (kid) {
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
nsIFrame* temp=nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
if (NS_SUCCEEDED(rv) && temp) {
*hit = temp;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
kid = kid->GetNextSibling();
}
return *hit ? NS_OK : NS_ERROR_FAILURE;
nsSVGUtils::HitTestChildren(this, x, y, hit);
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)

Просмотреть файл

@ -127,9 +127,7 @@ public:
// implementation inherited from nsSupportsWeakReference
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -139,10 +137,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = nsnull;
return NS_OK;
}
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();

Просмотреть файл

@ -66,10 +66,8 @@
#include "nsLayoutAtoms.h"
#include "nsISVGPathFlatten.h"
#include "nsSVGUtils.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
#include "nsSVGMaskFrame.h"
#include "nsSVGClipPathFrame.h"
#include "nsISVGRendererSurface.h"
#include "nsINameSpaceManager.h"
@ -89,7 +87,6 @@ class nsSVGTextFrame : public nsSVGTextFrameBase,
NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent);
protected:
nsSVGTextFrame();
virtual ~nsSVGTextFrame();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@ -148,9 +145,7 @@ public:
// implementation inherited from nsSupportsWeakReference
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -160,11 +155,6 @@ public:
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = mFilterRegion;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
@ -205,9 +195,6 @@ protected:
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
PRPackedBool mFragmentTreeDirty;
PRPackedBool mPositioningDirty;
@ -235,17 +222,10 @@ NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent)
nsSVGTextFrame::nsSVGTextFrame()
: mFragmentTreeState(suspended), mMetricsState(suspended),
mFragmentTreeDirty(PR_FALSE), mPositioningDirty(PR_FALSE),
mPropagateTransform(PR_TRUE), mFilter(nsnull)
mPropagateTransform(PR_TRUE)
{
}
nsSVGTextFrame::~nsSVGTextFrame()
{
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
}
//----------------------------------------------------------------------
// nsISupports methods
@ -304,6 +284,7 @@ nsSVGTextFrame::DidSetStyleContext()
#ifdef DEBUG
printf("** nsSVGTextFrame::DidSetStyleContext\n");
#endif
nsSVGUtils::StyleEffects(this);
return NS_OK;
}
@ -402,20 +383,8 @@ NS_IMETHODIMP
nsSVGTextFrame::WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
nsSVGUtils::WillModifyEffects(this, observable, aModType);
// need to handle filters because we might be the topmost filtered frame and
// the filter region could be changing.
if (filter && mFilterRegion) {
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
return NS_OK;
}
@ -424,28 +393,7 @@ NS_IMETHODIMP
nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
if (mFilter)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
if (region)
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
nsSVGUtils::DidModifyEffects(this, observable, aModType);
return NS_OK;
}
@ -552,9 +500,7 @@ nsSVGTextFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
#ifdef DEBUG
// printf("nsSVGTextFrame(%p)::Paint\n", this);
@ -563,152 +509,25 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
if (display->mOpacity == 0.0)
return NS_OK;
nsIURI *aURI;
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
/* check for a clip path */
PRBool trivialClip = PR_TRUE;
nsISVGClipPathFrame *clip = NULL;
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface;
aURI = GetStyleSVGReset()->mClipPath;
if (aURI) {
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
if (clip) {
clip->IsTrivial(&trivialClip);
if (trivialClip) {
canvas->PushClip();
} else {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipMaskSurface));
if (!clipMaskSurface)
clip = nsnull;
}
if (clip) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
}
}
}
/* check for mask */
nsISVGMaskFrame *mask = nsnull;
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
aURI = GetStyleSVGReset()->mMask;
if (aURI) {
NS_GetSVGMaskFrame(&mask, aURI, mContent);
if (mask) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskSurface));
if (maskSurface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM();
if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix,
display->mOpacity)))
maskSurface = nsnull;
}
}
}
if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) {
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(maskedSurface));
if (maskedSurface) {
canvas->PushSurface(maskedSurface);
} else
maskSurface = nsnull;
}
nsIFrame* kid = mFrames.FirstChild();
while (kid) {
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
SVGFrame->PaintSVG(canvas);
kid = kid->GetNextSibling();
}
if (maskedSurface)
canvas->PopSurface();
if (clipMaskSurface) {
if (!maskSurface && display->mOpacity == 1.0) {
maskSurface = clipMaskSurface;
} else {
nsCOMPtr<nsISVGRendererSurface> clipped;
nsSVGUtils::GetSurface(outerSVGFrame, canvas,
getter_AddRefs(clipped));
canvas->PushSurface(clipped);
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface);
canvas->PopSurface();
maskedSurface = clipped;
}
}
if (maskSurface)
canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface);
else if (display->mOpacity != 1.0)
canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity);
if (clip && trivialClip)
canvas->PopClip();
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
#ifdef DEBUG
// printf("nsSVGTextFrame(%p)::GetFrameForPoint\n", this);
#endif
*hit = nsnull;
nsIFrame* kid = mFrames.FirstChild();
while (kid) {
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
nsIFrame* temp=nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
if (NS_SUCCEEDED(rv) && temp) {
*hit = temp;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
kid = kid->GetNextSibling();
}
return *hit ? NS_OK : NS_ERROR_FAILURE;
nsSVGUtils::HitTestChildren(this, x, y, hit);
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)

Просмотреть файл

@ -70,6 +70,16 @@
#include "nsIDOMSVGAnimPresAspRatio.h"
#include "nsIDOMSVGPresAspectRatio.h"
#include "nsSVGMatrix.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGClipPathFrame.h"
#include "nsSVGMaskFrame.h"
#include "nsISVGRendererSurface.h"
#include "nsISVGContainerFrame.h"
struct nsSVGFilterProperty {
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
};
static PRBool gSVGEnabled;
static PRBool gSVGRendererAvailable = PR_FALSE;
@ -477,15 +487,19 @@ void
nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame,
nsISVGRendererRegion **aRegion)
{
nsCOMPtr<nsISVGRendererRegion> region, tmp;
*aRegion = nsnull;
nsISVGRendererRegion *region = nsnull;
while (aFrame != nsnull) {
nsISVGChildFrame *svg;
CallQueryInterface(aFrame, &svg);
if (svg)
svg->GetFilterRegion(getter_AddRefs(tmp));
if (tmp)
region = tmp;
while (aFrame) {
if (aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)
break;
if (aFrame->GetStateBits() & NS_STATE_SVG_FILTERED) {
nsSVGFilterProperty *property;
property = NS_STATIC_CAST(nsSVGFilterProperty *,
aFrame->GetProperty(nsGkAtoms::filter));
region = property->mFilterRegion;
}
aFrame = aFrame->GetParent();
}
@ -734,3 +748,387 @@ nsSVGUtils::GetViewBoxTransform(float aViewportWidth, float aViewportHeight,
NS_NewSVGMatrix(&retval, a, 0.0f, 0.0f, d, e, f);
return retval;
}
// This is ugly and roc will want to kill me...
already_AddRefed<nsIDOMSVGMatrix>
nsSVGUtils::GetCanvasTM(nsIFrame *aFrame)
{
nsISVGContainerFrame *containerFrame = nsnull;
CallQueryInterface(aFrame, &containerFrame);
if (containerFrame) {
return containerFrame->GetCanvasTM();
}
nsISVGGeometrySource *geometrySource = nsnull;
CallQueryInterface(aFrame, &geometrySource);
if (geometrySource) {
nsCOMPtr<nsIDOMSVGMatrix> matrix;
nsIDOMSVGMatrix *retval;
geometrySource->GetCanvasTM(getter_AddRefs(matrix));
retval = matrix.get();
NS_IF_ADDREF(retval);
return retval;
}
return nsnull;
}
// ************************************************************
// Effect helper functions
static void
AddObserver(nsISupports *aObserver, nsISupports *aTarget)
{
nsISVGValueObserver *observer = nsnull;
nsISVGValue *v = nsnull;
CallQueryInterface(aObserver, &observer);
CallQueryInterface(aTarget, &v);
if (observer && v)
v->AddObserver(observer);
}
static void
RemoveObserver(nsISupports *aObserver, nsISupports *aTarget)
{
nsISVGValueObserver *observer = nsnull;
nsISVGValue *v = nsnull;
CallQueryInterface(aObserver, &observer);
CallQueryInterface(aTarget, &v);
if (observer && v)
v->RemoveObserver(observer);
}
static void
FilterPropertyDtor(void *aObject, nsIAtom *aPropertyName,
void *aPropertyValue, void *aData)
{
nsSVGFilterProperty *property = (nsSVGFilterProperty *)aPropertyValue;
RemoveObserver((nsIFrame *)aObject, property->mFilter);
delete property;
}
static void
InvalidateFilterRegion(nsIFrame *aFrame)
{
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(aFrame);
if (outerSVGFrame) {
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(aFrame, getter_AddRefs(region));
if (region)
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
}
static void
AddEffectProperties(nsIFrame *aFrame)
{
const nsStyleSVGReset *style = aFrame->GetStyleSVGReset();
if (style->mFilter && !(aFrame->GetStateBits() & NS_STATE_SVG_FILTERED)) {
nsISVGFilterFrame *filter;
NS_GetSVGFilterFrame(&filter, style->mFilter, aFrame->GetContent());
if (filter) {
AddObserver(aFrame, filter);
nsSVGFilterProperty *property = new nsSVGFilterProperty;
property->mFilter = filter;
filter->GetInvalidationRegion(aFrame, getter_AddRefs(property->mFilterRegion));
aFrame->SetProperty(nsGkAtoms::filter, property, FilterPropertyDtor);
aFrame->AddStateBits(NS_STATE_SVG_FILTERED);
}
}
if (style->mClipPath && !(aFrame->GetStateBits() & NS_STATE_SVG_CLIPPED_MASK)) {
nsISVGClipPathFrame *clip;
NS_GetSVGClipPathFrame(&clip, style->mClipPath, aFrame->GetContent());
if (clip) {
aFrame->SetProperty(nsGkAtoms::clipPath, clip);
PRBool trivialClip;
clip->IsTrivial(&trivialClip);
if (trivialClip)
aFrame->AddStateBits(NS_STATE_SVG_CLIPPED_TRIVIAL);
else
aFrame->AddStateBits(NS_STATE_SVG_CLIPPED_COMPLEX);
}
}
if (style->mMask && !(aFrame->GetStateBits() & NS_STATE_SVG_MASKED)) {
nsISVGMaskFrame *mask;
NS_GetSVGMaskFrame(&mask, style->mMask, aFrame->GetContent());
if (mask) {
aFrame->SetProperty(nsGkAtoms::mask, mask);
aFrame->AddStateBits(NS_STATE_SVG_MASKED);
}
}
}
static already_AddRefed<nsISVGRendererSurface>
GetComplexClipSurface(nsISVGRendererCanvas *aCanvas, nsIFrame *aFrame)
{
nsISVGRendererSurface *surface = nsnull;
if (aFrame->GetStateBits() & NS_STATE_SVG_CLIPPED_COMPLEX) {
nsISVGChildFrame *svgChildFrame;
CallQueryInterface(aFrame, &svgChildFrame);
nsISVGClipPathFrame *clip;
clip = NS_STATIC_CAST(nsISVGClipPathFrame *,
aFrame->GetProperty(nsGkAtoms::clipPath));
nsSVGUtils::GetSurface(nsSVGUtils::GetOuterSVGFrame(aFrame),
aCanvas, &surface);
if (surface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = nsSVGUtils::GetCanvasTM(aFrame);
if (NS_FAILED(clip->ClipPaint(aCanvas, surface, svgChildFrame,
matrix))) {
delete surface;
surface = nsnull;
}
}
}
return surface;
}
static already_AddRefed<nsISVGRendererSurface>
GetMaskSurface(nsISVGRendererCanvas *aCanvas, nsIFrame *aFrame, float opacity)
{
nsISVGRendererSurface *surface = nsnull;
if (aFrame->GetStateBits() & NS_STATE_SVG_MASKED) {
nsISVGChildFrame *svgChildFrame;
CallQueryInterface(aFrame, &svgChildFrame);
nsISVGMaskFrame *mask;
mask = NS_STATIC_CAST(nsISVGMaskFrame *,
aFrame->GetProperty(nsGkAtoms::mask));
nsSVGUtils::GetSurface(nsSVGUtils::GetOuterSVGFrame(aFrame),
aCanvas, &surface);
if (surface) {
nsCOMPtr<nsIDOMSVGMatrix> matrix = nsSVGUtils::GetCanvasTM(aFrame);
if (NS_FAILED(mask->MaskPaint(aCanvas, surface, svgChildFrame,
matrix, opacity))) {
delete surface;
surface = nsnull;
}
}
}
return surface;
}
// ************************************************************
void
nsSVGUtils::PaintChildWithEffects(nsISVGRendererCanvas *aCanvas,
nsIFrame *aFrame)
{
nsISVGChildFrame *svgChildFrame;
CallQueryInterface(aFrame, &svgChildFrame);
if (!svgChildFrame)
return;
nsISVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(aFrame);
float opacity = aFrame->GetStyleDisplay()->mOpacity;
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
AddEffectProperties(aFrame);
nsFrameState state = aFrame->GetStateBits();
/* SVG defines the following rendering model:
*
* 1. Render geometry
* 2. Apply filter
* 3. Apply clipping, masking, group opacity
*
* We follow this, but perform a couple optimizations:
*
* + Use cairo's clipPath when representable natively (single object
* clip region).
*
* + Merge opacity and masking if both used together.
*/
nsCOMPtr<nsISVGRendererSurface> offscreenSurface;
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
if (opacity != 1.0 ||
state & (NS_STATE_SVG_CLIPPED_COMPLEX | NS_STATE_SVG_MASKED)) {
nsSVGUtils::GetSurface(outerSVGFrame,
aCanvas, getter_AddRefs(offscreenSurface));
if (offscreenSurface) {
aCanvas->PushSurface(offscreenSurface, PR_TRUE);
} else {
return;
}
}
/* 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 (state & NS_STATE_SVG_CLIPPED_TRIVIAL) {
nsISVGClipPathFrame *clip;
clip = NS_STATIC_CAST(nsISVGClipPathFrame *,
aFrame->GetProperty(nsGkAtoms::clipPath));
aCanvas->PushClip();
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
clip->ClipPaint(aCanvas, nsnull, svgChildFrame, matrix);
}
/* Paint the child */
if (state & NS_STATE_SVG_FILTERED) {
nsSVGFilterProperty *property;
property = NS_STATIC_CAST(nsSVGFilterProperty *,
aFrame->GetProperty(nsGkAtoms::filter));
property->mFilter->FilterPaint(aCanvas, svgChildFrame);
} else {
svgChildFrame->PaintSVG(aCanvas);
}
if (state & NS_STATE_SVG_CLIPPED_TRIVIAL) {
aCanvas->PopClip();
}
/* No more effects, we're done. */
if (!offscreenSurface)
return;
aCanvas->PopSurface();
nsCOMPtr<nsISVGRendererSurface> clipMaskSurface, maskSurface;
clipMaskSurface = GetComplexClipSurface(aCanvas, aFrame);
maskSurface = GetMaskSurface(aCanvas, aFrame, opacity);
nsCOMPtr<nsISVGRendererSurface> clippedSurface;
if (clipMaskSurface) {
// Still more set after clipping, so clip to another surface
if (maskSurface || opacity != 1.0) {
nsSVGUtils::GetSurface(outerSVGFrame, aCanvas,
getter_AddRefs(clippedSurface));
if (clippedSurface) {
aCanvas->PushSurface(clippedSurface, PR_TRUE);
aCanvas->CompositeSurfaceWithMask(offscreenSurface, clipMaskSurface);
aCanvas->PopSurface();
}
} else {
aCanvas->CompositeSurfaceWithMask(offscreenSurface, clipMaskSurface);
}
}
// No clipping or out of memory creating clip dest surface (skip clipping)
if (!clippedSurface) {
clippedSurface = offscreenSurface;
}
if (maskSurface)
aCanvas->CompositeSurfaceWithMask(clippedSurface, maskSurface);
else if (opacity != 1.0)
aCanvas->CompositeSurface(clippedSurface, opacity);
}
void
nsSVGUtils::StyleEffects(nsIFrame *aFrame)
{
nsFrameState state = aFrame->GetStateBits();
/* clear out all effects */
if (state & NS_STATE_SVG_CLIPPED_MASK) {
aFrame->DeleteProperty(nsGkAtoms::clipPath);
}
if (state & NS_STATE_SVG_FILTERED) {
aFrame->DeleteProperty(nsGkAtoms::filter);
}
if (state & NS_STATE_SVG_MASKED) {
aFrame->DeleteProperty(nsGkAtoms::mask);
}
aFrame->RemoveStateBits(NS_STATE_SVG_CLIPPED_MASK |
NS_STATE_SVG_FILTERED |
NS_STATE_SVG_MASKED);
}
void
nsSVGUtils::WillModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter)
InvalidateFilterRegion(aFrame);
}
void
nsSVGUtils::DidModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter) {
InvalidateFilterRegion(aFrame);
if (aModType == nsISVGValue::mod_die) {
aFrame->DeleteProperty(nsGkAtoms::filter);
aFrame->RemoveStateBits(NS_STATE_SVG_FILTERED);
}
}
}
PRBool
nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
{
PRBool clipHit = PR_TRUE;
nsISVGChildFrame* SVGFrame;
CallQueryInterface(aFrame, &SVGFrame);
if (aFrame->GetStateBits() & NS_STATE_SVG_CLIPPED_MASK) {
nsISVGClipPathFrame *clip;
clip = NS_STATIC_CAST(nsISVGClipPathFrame *,
aFrame->GetProperty(nsGkAtoms::clipPath));
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
clip->ClipHitTest(SVGFrame, matrix, x, y, &clipHit);
}
return clipHit;
}
void
nsSVGUtils::HitTestChildren(nsIFrame *aFrame, float x, float y,
nsIFrame **aResult)
{
*aResult = nsnull;
for (nsIFrame* kid = aFrame->GetFirstChild(nsnull); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame;
CallQueryInterface(kid, &SVGFrame);
if (SVGFrame) {
nsIFrame* temp=nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(x, y, &temp);
if (NS_SUCCEEDED(rv) && temp) {
*aResult = temp;
// return NS_OK; can't return. we need reverse order but only
// have a singly linked list...
}
}
}
if (*aResult && !HitTestClip(aFrame, x, y))
*aResult = nsnull;
}

Просмотреть файл

@ -43,6 +43,7 @@
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsISVGValue.h"
class nsPresContext;
class nsIContent;
@ -64,13 +65,22 @@ class nsIPresShell;
class nsISVGRendererCanvas;
class nsISVGOuterSVGFrame;
class nsIDOMSVGAnimatedPreserveAspectRatio;
class nsISVGValueObserver;
class nsIAtom;
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// SVG Frame state bits
#define NS_STATE_IS_OUTER_SVG 0x00100000
#define NS_STATE_IS_OUTER_SVG 0x00100000
#define NS_STATE_SVG_CLIPPED_TRIVIAL 0x00200000
#define NS_STATE_SVG_CLIPPED_COMPLEX 0x00400000
#define NS_STATE_SVG_CLIPPED_MASK 0x00600000
#define NS_STATE_SVG_FILTERED 0x00800000
#define NS_STATE_SVG_MASKED 0x01000000
class nsSVGUtils
{
@ -216,6 +226,43 @@ public:
nsIDOMSVGAnimatedPreserveAspectRatio *aPreserveAspectRatio,
PRBool aIgnoreAlign = PR_FALSE);
/* Paint frame with SVG effects */
static void
PaintChildWithEffects(nsISVGRendererCanvas *aCanvas, nsIFrame *aFrame);
/* Style change for effects (filter/clip/mask/opacity) - call when
* the frame's style has changed to make sure the effects properties
* stay in sync. */
static void
StyleEffects(nsIFrame *aFrame);
/* Modification events for effects (filter/clip/mask/opacity) - call
* when observers on effects get called to make sure properties stay
* in sync. */
static void
WillModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
nsISVGValue::modificationType aModType);
static void
DidModifyEffects(nsIFrame *aFrame, nsISVGValue *observable,
nsISVGValue::modificationType aModType);
/* Hit testing - check if point hits the clipPath of indicated
* frame. Returns true of no clipPath set. */
static PRBool
HitTestClip(nsIFrame *aFrame, float x, float y);
/* Hit testing - check if point hits any children of frame. */
static void
HitTestChildren(nsIFrame *aFrame, float x, float y, nsIFrame **aResult);
/*
* Returns the CanvasTM of the indicated frame, whether it's a
* child or container SVG frame.
*/
static already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM(nsIFrame *aFrame);
private:
/*
* Returns the glyph fragment containing a particular character

Просмотреть файл

@ -129,8 +129,13 @@ interface nsISVGRendererCanvas : nsISupports
/**
* Push/Pop surface as primary drawing surface.
*
* surface: surface to push
* isSubSurface: boolean to tell whether this should be treated like
* the "root" surface in terms of transformation correction
* or as an absolute surface.
*/
void pushSurface(in nsISVGRendererSurface surface);
void pushSurface(in nsISVGRendererSurface surface, in boolean isSubSurface);
void popSurface();
/**
@ -142,11 +147,9 @@ interface nsISVGRendererCanvas : nsISupports
* Surface composition.
*/
void compositeSurface(in nsISVGRendererSurface surface,
in unsigned long x, in unsigned long y,
in float opacity);
void compositeSurfaceWithMask(in nsISVGRendererSurface surface,
in unsigned long x, in unsigned long y,
in nsISVGRendererSurface mask);
void compositeSurfaceMatrix(in nsISVGRendererSurface surface,

Просмотреть файл

@ -150,6 +150,7 @@ private:
nsCOMPtr<imgIContainer> mContainer;
nsCOMPtr<gfxIImageFrame> mBuffer;
PRUint8 *mData;
PRInt32 mSubSurfaceDepth;
PRUint16 mRenderMode;
PRPackedBool mOwnsCR;
@ -162,7 +163,7 @@ private:
//----------------------------------------------------------------------
// implementation:
nsSVGCairoCanvas::nsSVGCairoCanvas() : mData(nsnull)
nsSVGCairoCanvas::nsSVGCairoCanvas() : mData(nsnull), mSubSurfaceDepth(0)
{
mOwnsCR = PR_FALSE;
}
@ -184,7 +185,7 @@ nsSVGCairoCanvas::~nsSVGCairoCanvas()
nsresult
nsSVGCairoCanvas::AdjustMatrixForInitialTransform(cairo_matrix_t* aMatrix)
{
if (mContextStack.Count() == 0)
if (mSubSurfaceDepth == mContextStack.Count())
cairo_matrix_multiply(aMatrix, aMatrix, &mInitialTransform);
return NS_OK;
}
@ -714,7 +715,8 @@ struct ctxEntry {
/** Implements pushSurface(in nsISVGRendererSurface surface); */
NS_IMETHODIMP
nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface,
PRBool isSubSurface)
{
nsCOMPtr<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
if (!cairoSurface)
@ -728,6 +730,10 @@ nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
ctx->mWidth = mWidth;
ctx->mHeight = mHeight;
// Once we go non-subsurface, all further pushes are forced absolute
if (isSubSurface && mSubSurfaceDepth == mContextStack.Count())
mSubSurfaceDepth++;
mContextStack.AppendElement(NS_STATIC_CAST(void*, ctx));
mCR = cairo_create(cairoSurface->GetSurface());
@ -741,7 +747,7 @@ nsSVGCairoCanvas::PushSurface(nsISVGRendererSurface *aSurface)
NS_IMETHODIMP
nsSVGCairoCanvas::PopSurface()
{
PRUint32 count = mContextStack.Count();
PRInt32 count = mContextStack.Count();
if (count != 0) {
cairo_destroy(mCR);
ctxEntry *ctx = NS_STATIC_CAST(ctxEntry*, mContextStack[count - 1]);
@ -750,6 +756,9 @@ nsSVGCairoCanvas::PopSurface()
mHeight = ctx->mHeight;
delete ctx;
mContextStack.RemoveElementAt(count - 1);
if (mSubSurfaceDepth == count)
mSubSurfaceDepth--;
}
return NS_OK;
@ -764,18 +773,18 @@ nsSVGCairoCanvas::GetSurfaceSize(PRUint32 *aWidth, PRUint32 *aHeight)
}
/** Implements void compositeSurface(in nsISVGRendererSurface surface,
in unsigned long x, in unsigned long y,
in float opacity); */
NS_IMETHODIMP
nsSVGCairoCanvas::CompositeSurface(nsISVGRendererSurface *aSurface,
PRUint32 aX, PRUint32 aY, float aOpacity)
float aOpacity)
{
nsCOMPtr<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
if (!cairoSurface)
return NS_ERROR_FAILURE;
cairo_save(mCR);
cairo_translate(mCR, aX, aY);
if (mSubSurfaceDepth == mContextStack.Count())
cairo_translate(mCR, -mInitialTransform.x0, -mInitialTransform.y0);
cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0);
cairo_paint_with_alpha(mCR, aOpacity);
@ -785,12 +794,9 @@ nsSVGCairoCanvas::CompositeSurface(nsISVGRendererSurface *aSurface,
}
/** Implements void compositeSurfaceWithMask(in nsISVGRendererSurface surface,
in unsigned long x,
in unsigned long y,
in nsISVGRendererSurface mask); */
NS_IMETHODIMP
nsSVGCairoCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface,
PRUint32 aX, PRUint32 aY,
nsISVGRendererSurface *aMask)
{
nsCOMPtr<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
@ -799,7 +805,8 @@ nsSVGCairoCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface,
return NS_ERROR_FAILURE;
cairo_save(mCR);
cairo_translate(mCR, aX, aY);
if (mSubSurfaceDepth == mContextStack.Count())
cairo_translate(mCR, -mInitialTransform.x0, -mInitialTransform.y0);
cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0);
cairo_mask_surface(mCR, maskSurface->GetSurface(), 0.0, 0.0);