Bug 301234 - implement subset of SVG filters. r=scooter

git-svn-id: svn://10.0.0.236/trunk@179732 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
tor%cs.brown.edu
2005-09-06 22:30:40 +00:00
parent cd2f15379f
commit 4a3e054bee
53 changed files with 4972 additions and 132 deletions

View File

@@ -66,6 +66,8 @@
#include "nsLayoutAtoms.h"
#include "nsISVGPathFlatten.h"
#include "nsSVGUtils.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGUtils.h"
typedef nsContainerFrame nsSVGTextFrameBase;
@@ -144,15 +146,23 @@ public:
// implementation inherited from nsSupportsWeakReference
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips);
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
NS_IMETHOD NotifyCanvasTMChanged();
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
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:
nsISVGOuterSVGFrame *GetOuterSVGFrame();
@@ -195,7 +205,11 @@ protected:
PRBool mPositioningDirty;
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
PRBool mPropagateTransform;
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
};
//----------------------------------------------------------------------
@@ -228,7 +242,7 @@ NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent,
nsSVGTextFrame::nsSVGTextFrame()
: mFragmentTreeState(suspended), mMetricsState(suspended),
mFragmentTreeDirty(PR_FALSE), mPositioningDirty(PR_FALSE),
mPropagateTransform(PR_TRUE)
mPropagateTransform(PR_TRUE), mFilter(nsnull)
{
}
@@ -262,6 +276,10 @@ nsSVGTextFrame::~nsSVGTextFrame()
transformable->GetTransform(getter_AddRefs(transforms));
NS_REMOVE_SVGVALUE_OBSERVER(transforms);
}
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
}
nsresult nsSVGTextFrame::Init()
@@ -453,6 +471,20 @@ NS_IMETHODIMP
nsSVGTextFrame::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 = GetOuterSVGFrame();
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
return NS_OK;
}
@@ -461,8 +493,29 @@ NS_IMETHODIMP
nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
nsCOMPtr<nsIDOMSVGAnimatedTransformList> transforms = GetTransform();
if (SameCOMIdentity(observable, transforms)) {
if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
nsISVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame();
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 (SameCOMIdentity(observable, transforms)) {
// transform has changed
// make sure our cached transform matrix gets (lazily) updated
@@ -473,7 +526,7 @@ nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable,
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->NotifyCanvasTMChanged();
SVGFrame->NotifyCanvasTMChanged(PR_FALSE);
kid = kid->GetNextSibling();
}
}
@@ -522,18 +575,39 @@ nsSVGTextFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter)
{
#ifdef DEBUG
// printf("nsSVGTextFrame(%p)::Paint\n", this);
#endif
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
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;
}
}
nsIFrame* kid = mFrames.FirstChild();
while (kid) {
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame)
SVGFrame->PaintSVG(canvas, dirtyRectTwips);
SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE);
kid = kid->GetNextSibling();
}
@@ -624,7 +698,7 @@ nsSVGTextFrame::InitialUpdate()
}
NS_IMETHODIMP
nsSVGTextFrame::NotifyCanvasTMChanged()
nsSVGTextFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation)
{
// make sure our cached transform matrix gets (lazily) updated
mCanvasTM = nsnull;
@@ -634,7 +708,7 @@ nsSVGTextFrame::NotifyCanvasTMChanged()
nsISVGChildFrame* SVGFrame=0;
kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame);
if (SVGFrame) {
SVGFrame->NotifyCanvasTMChanged();
SVGFrame->NotifyCanvasTMChanged(suppressInvalidation);
}
kid = kid->GetNextSibling();
}
@@ -720,6 +794,13 @@ nsSVGTextFrame::SetMatrixPropagation(PRBool aPropagate)
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM)
{
mOverrideCTM = aCTM;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::GetBBox(nsIDOMSVGRect **_retval)
{
@@ -748,13 +829,18 @@ nsSVGTextFrame::GetOuterSVGFrame()
already_AddRefed<nsIDOMSVGMatrix>
nsSVGTextFrame::GetCanvasTM()
{
if (!mCanvasTM) {
if (!mPropagateTransform) {
nsIDOMSVGMatrix *retval;
if (!mPropagateTransform) {
nsIDOMSVGMatrix *retval;
if (mOverrideCTM) {
retval = mOverrideCTM;
NS_ADDREF(retval);
} else {
NS_NewSVGMatrix(&retval);
return retval;
}
return retval;
}
if (!mCanvasTM) {
// get our parent's tm and append local transforms (if any):
NS_ASSERTION(mParent, "null parent");
nsISVGContainerFrame *containerFrame;