mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 377015 - Simplify nsSVGClipPathFrame API and make clip reference loop detection more robust. r=jwatt,sr=tor
This commit is contained in:
parent
adf8e096fb
commit
09edc1c88b
@ -101,10 +101,10 @@ nsSVGClipPathFrame::InitSVG()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult
|
||||||
nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
|
nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
|
||||||
nsISVGChildFrame* aParent,
|
nsISVGChildFrame* aParent,
|
||||||
nsCOMPtr<nsIDOMSVGMatrix> aMatrix)
|
nsIDOMSVGMatrix *aMatrix)
|
||||||
{
|
{
|
||||||
// If the flag is set when we get here, it means this clipPath frame
|
// If the flag is set when we get here, it means this clipPath frame
|
||||||
// has already been used painting the current clip, and the document
|
// has already been used painting the current clip, and the document
|
||||||
@ -113,13 +113,12 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
|
|||||||
NS_WARNING("Clip loop detected!");
|
NS_WARNING("Clip loop detected!");
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
mInUse = PR_TRUE;
|
AutoClipPathReferencer clipRef(this);
|
||||||
|
|
||||||
mClipParent = aParent,
|
mClipParent = aParent,
|
||||||
mClipParentMatrix = aMatrix;
|
mClipParentMatrix = aMatrix;
|
||||||
|
|
||||||
PRBool isTrivial;
|
PRBool isTrivial = IsTrivial();
|
||||||
IsTrivial(&isTrivial);
|
|
||||||
|
|
||||||
nsAutoSVGRenderMode mode(aContext,
|
nsAutoSVGRenderMode mode(aContext,
|
||||||
isTrivial ? nsSVGRenderState::CLIP
|
isTrivial ? nsSVGRenderState::CLIP
|
||||||
@ -140,26 +139,22 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
|
|||||||
aContext->GetGfxContext()->NewPath();
|
aContext->GetGfxContext()->NewPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
mInUse = PR_FALSE;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
PRBool
|
||||||
nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent,
|
nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent,
|
||||||
nsCOMPtr<nsIDOMSVGMatrix> aMatrix,
|
nsIDOMSVGMatrix *aMatrix,
|
||||||
float aX, float aY, PRBool *aHit)
|
float aX, float aY)
|
||||||
{
|
{
|
||||||
*aHit = PR_FALSE;
|
|
||||||
|
|
||||||
// If the flag is set when we get here, it means this clipPath frame
|
// If the flag is set when we get here, it means this clipPath frame
|
||||||
// has already been used in hit testing against the current clip,
|
// has already been used in hit testing against the current clip,
|
||||||
// and the document has a clip reference loop.
|
// and the document has a clip reference loop.
|
||||||
if (mInUse) {
|
if (mInUse) {
|
||||||
NS_WARNING("Clip loop detected!");
|
NS_WARNING("Clip loop detected!");
|
||||||
return NS_OK;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
mInUse = PR_TRUE;
|
AutoClipPathReferencer clipRef(this);
|
||||||
|
|
||||||
nsRect dirty;
|
nsRect dirty;
|
||||||
mClipParent = aParent,
|
mClipParent = aParent,
|
||||||
@ -177,23 +172,16 @@ nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent,
|
|||||||
|
|
||||||
nsIFrame *temp = nsnull;
|
nsIFrame *temp = nsnull;
|
||||||
nsresult rv = SVGFrame->GetFrameForPointSVG(aX, aY, &temp);
|
nsresult rv = SVGFrame->GetFrameForPointSVG(aX, aY, &temp);
|
||||||
if (NS_SUCCEEDED(rv) && temp) {
|
if (NS_SUCCEEDED(rv) && temp)
|
||||||
*aHit = PR_TRUE;
|
return PR_TRUE;
|
||||||
mInUse = PR_FALSE;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return PR_FALSE;
|
||||||
mInUse = PR_FALSE;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
PRBool
|
||||||
nsSVGClipPathFrame::IsTrivial(PRBool *aTrivial)
|
nsSVGClipPathFrame::IsTrivial()
|
||||||
{
|
{
|
||||||
*aTrivial = PR_TRUE;
|
|
||||||
PRBool foundChild = PR_FALSE;
|
PRBool foundChild = PR_FALSE;
|
||||||
|
|
||||||
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
for (nsIFrame* kid = mFrames.FirstChild(); kid;
|
||||||
@ -204,15 +192,12 @@ nsSVGClipPathFrame::IsTrivial(PRBool *aTrivial)
|
|||||||
if (svgChild) {
|
if (svgChild) {
|
||||||
// We consider a non-trivial clipPath to be one containing
|
// We consider a non-trivial clipPath to be one containing
|
||||||
// either more than one svg child and/or a svg container
|
// either more than one svg child and/or a svg container
|
||||||
if (foundChild || svgChild->IsDisplayContainer()) {
|
if (foundChild || svgChild->IsDisplayContainer())
|
||||||
*aTrivial = PR_FALSE;
|
return PR_FALSE;
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
foundChild = PR_TRUE;
|
foundChild = PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return PR_TRUE;
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIAtom *
|
nsIAtom *
|
||||||
|
@ -48,22 +48,22 @@ class nsSVGClipPathFrame : public nsSVGClipPathFrameBase
|
|||||||
|
|
||||||
NS_IMETHOD InitSVG();
|
NS_IMETHOD InitSVG();
|
||||||
|
|
||||||
public:
|
|
||||||
nsSVGClipPathFrame(nsStyleContext* aContext) : nsSVGClipPathFrameBase(aContext) {}
|
nsSVGClipPathFrame(nsStyleContext* aContext) : nsSVGClipPathFrameBase(aContext) {}
|
||||||
|
|
||||||
|
public:
|
||||||
// nsSVGClipPathFrame methods:
|
// nsSVGClipPathFrame methods:
|
||||||
NS_IMETHOD ClipPaint(nsSVGRenderState* aContext,
|
nsresult ClipPaint(nsSVGRenderState* aContext,
|
||||||
nsISVGChildFrame* aParent,
|
nsISVGChildFrame* aParent,
|
||||||
nsCOMPtr<nsIDOMSVGMatrix> aMatrix);
|
nsIDOMSVGMatrix *aMatrix);
|
||||||
|
|
||||||
NS_IMETHOD ClipHitTest(nsISVGChildFrame* aParent,
|
PRBool ClipHitTest(nsISVGChildFrame* aParent,
|
||||||
nsCOMPtr<nsIDOMSVGMatrix> aMatrix,
|
nsIDOMSVGMatrix *aMatrix,
|
||||||
float aX, float aY, PRBool *aHit);
|
float aX, float aY);
|
||||||
|
|
||||||
// Check if this clipPath is made up of more than one geometry object.
|
// Check if this clipPath is made up of more than one geometry object.
|
||||||
// If so, the clipping API in cairo isn't enough and we need to use
|
// If so, the clipping API in cairo isn't enough and we need to use
|
||||||
// mask based clipping.
|
// mask based clipping.
|
||||||
NS_IMETHOD IsTrivial(PRBool *aTrivial);
|
PRBool IsTrivial();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "type" of the frame
|
* Get the "type" of the frame
|
||||||
@ -80,6 +80,24 @@ class nsSVGClipPathFrame : public nsSVGClipPathFrameBase
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// A helper class to allow us to paint clip paths safely. The helper
|
||||||
|
// automatically sets and clears the mInUse flag on the clip path frame
|
||||||
|
// (to prevent nasty reference loops). It's easy to mess this up
|
||||||
|
// and break things, so this helper makes the code far more robust.
|
||||||
|
class AutoClipPathReferencer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutoClipPathReferencer(nsSVGClipPathFrame *aFrame) {
|
||||||
|
NS_ASSERTION(mFrame->mInUse == PR_FALSE, "reference loop!");
|
||||||
|
mFrame->mInUse = PR_TRUE;
|
||||||
|
}
|
||||||
|
~AutoClipPathReferencer() {
|
||||||
|
mFrame->mInUse = PR_FALSE;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
nsSVGClipPathFrame *mFrame;
|
||||||
|
};
|
||||||
|
|
||||||
nsISVGChildFrame *mClipParent;
|
nsISVGChildFrame *mClipParent;
|
||||||
nsCOMPtr<nsIDOMSVGMatrix> mClipParentMatrix;
|
nsCOMPtr<nsIDOMSVGMatrix> mClipParentMatrix;
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
#include "nsSVGGFrame.h"
|
#include "nsSVGGFrame.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsSVGMatrix.h"
|
#include "nsSVGMatrix.h"
|
||||||
#include "nsSVGClipPathFrame.h"
|
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsSVGUtils.h"
|
#include "nsSVGUtils.h"
|
||||||
#include "nsISVGValueUtils.h"
|
#include "nsISVGValueUtils.h"
|
||||||
|
@ -811,13 +811,9 @@ AddEffectProperties(nsIFrame *aFrame)
|
|||||||
aFrame->GetContent());
|
aFrame->GetContent());
|
||||||
if (clip) {
|
if (clip) {
|
||||||
aFrame->SetProperty(nsGkAtoms::clipPath, clip);
|
aFrame->SetProperty(nsGkAtoms::clipPath, clip);
|
||||||
|
aFrame->AddStateBits(clip->IsTrivial() ?
|
||||||
PRBool trivialClip;
|
NS_STATE_SVG_CLIPPED_TRIVIAL :
|
||||||
clip->IsTrivial(&trivialClip);
|
NS_STATE_SVG_CLIPPED_COMPLEX);
|
||||||
if (trivialClip)
|
|
||||||
aFrame->AddStateBits(NS_STATE_SVG_CLIPPED_TRIVIAL);
|
|
||||||
else
|
|
||||||
aFrame->AddStateBits(NS_STATE_SVG_CLIPPED_COMPLEX);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,8 +1034,6 @@ nsSVGUtils::StyleEffects(nsIFrame *aFrame)
|
|||||||
PRBool
|
PRBool
|
||||||
nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
|
nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
|
||||||
{
|
{
|
||||||
PRBool clipHit = PR_TRUE;
|
|
||||||
|
|
||||||
nsISVGChildFrame* SVGFrame;
|
nsISVGChildFrame* SVGFrame;
|
||||||
CallQueryInterface(aFrame, &SVGFrame);
|
CallQueryInterface(aFrame, &SVGFrame);
|
||||||
|
|
||||||
@ -1048,10 +1042,10 @@ nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
|
|||||||
clip = NS_STATIC_CAST(nsSVGClipPathFrame *,
|
clip = NS_STATIC_CAST(nsSVGClipPathFrame *,
|
||||||
aFrame->GetProperty(nsGkAtoms::clipPath));
|
aFrame->GetProperty(nsGkAtoms::clipPath));
|
||||||
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
|
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
|
||||||
clip->ClipHitTest(SVGFrame, matrix, x, y, &clipHit);
|
return clip->ClipHitTest(SVGFrame, matrix, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clipHit;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user