Bug 1495034. Separate out the SVGObserverUtils clip path handling from EffectProperties. r=longsonr

Differential Revision: https://phabricator.services.mozilla.com/D7194

--HG--
extra : rebase_source : d8137eb0f1b91fe926d04bfb3d7197c11d6402e7
extra : amend_source : c0faf32401c08471c6acb52b5eb36571ceaeb951
This commit is contained in:
Jonathan Watt 2018-09-05 18:12:44 +01:00
Родитель c506a0013f
Коммит 85d30e0f2c
6 изменённых файлов: 163 добавлений и 175 удалений

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

@ -9718,7 +9718,8 @@ nsDisplayMasksAndClipPaths::IsValidMask() {
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(firstFrame);
if (effectProperties.HasInvalidClipPath() ||
if (SVGObserverUtils::GetAndObserveClipPath(firstFrame, nullptr) ==
SVGObserverUtils::eHasRefsSomeInvalid ||
effectProperties.HasInvalidMask()) {
return false;
}
@ -10036,13 +10037,15 @@ nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo)
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(firstFrame);
nsSVGClipPathFrame* clipPathFrame = effectProperties.GetClipPathFrame();
bool first = true;
aTo += " effects=(";
if (mFrame->StyleEffects()->mOpacity != 1.0f && mHandleOpacity) {
first = false;
aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
}
nsSVGClipPathFrame* clipPathFrame;
// XXX Check return value?
SVGObserverUtils::GetAndObserveClipPath(firstFrame, &clipPathFrame);
if (clipPathFrame) {
if (!first) {
aTo += ", ";
@ -10050,9 +10053,7 @@ nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo)
aTo += nsPrintfCString(
"clip(%s)", clipPathFrame->IsTrivial() ? "trivial" : "non-trivial");
first = false;
}
const nsStyleSVGReset* style = mFrame->StyleSVGReset();
if (style->HasClipPath() && !clipPathFrame) {
} else if (mFrame->StyleSVGReset()->HasClipPath()) {
if (!first) {
aTo += ", ";
}

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

@ -580,6 +580,43 @@ GetOrCreateMaskProperty(nsIFrame* aFrame)
return prop;
}
static already_AddRefed<URLAndReferrerInfo>
ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL)
{
MOZ_ASSERT(aFrame);
if (!aURL) {
return nullptr;
}
nsCOMPtr<nsIURI> uri = aURL->GetURI();
RefPtr<URLAndReferrerInfo> result;
// Non-local-reference URL.
if (!aURL->IsLocalRef()) {
if (!uri) {
return nullptr;
}
result = new URLAndReferrerInfo(uri,
aURL->mExtraData->GetReferrer(),
aURL->mExtraData->GetReferrerPolicy());
return result.forget();
}
nsCOMPtr<nsIURI> baseURI =
SVGObserverUtils::GetBaseURLForLocalRef(aFrame->GetContent(), uri);
nsCOMPtr<nsIURI> resolvedURI = aURL->ResolveLocalRef(baseURI);
if (!resolvedURI) {
return nullptr;
}
result = new URLAndReferrerInfo(resolvedURI,
aURL->mExtraData->GetReferrer(),
aURL->mExtraData->GetReferrerPolicy());
return result.forget();
}
template<class T>
static T*
GetEffectProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame,
@ -716,6 +753,46 @@ SVGObserverUtils::DetachFromCanvasContext(nsISupports* aAutoObserver)
DetachFromContext();
}
static nsSVGPaintingProperty*
GetOrCreateClipPathObserver(nsIFrame* aClippedFrame)
{
const nsStyleSVGReset* svgStyleReset = aClippedFrame->StyleSVGReset();
if (svgStyleReset->mClipPath.GetType() != StyleShapeSourceType::URL) {
return nullptr;
}
css::URLValue* url = svgStyleReset->mClipPath.GetURL();
RefPtr<URLAndReferrerInfo> pathURI = ResolveURLUsingLocalRef(aClippedFrame, url);
return SVGObserverUtils::GetPaintingProperty(pathURI, aClippedFrame,
SVGObserverUtils::ClipPathProperty());
}
SVGObserverUtils::ReferenceState
SVGObserverUtils::GetAndObserveClipPath(nsIFrame* aClippedFrame,
nsSVGClipPathFrame** aClipPathFrame)
{
if (aClipPathFrame) {
*aClipPathFrame = nullptr;
}
nsSVGPaintingProperty* observers = GetOrCreateClipPathObserver(aClippedFrame);
if (!observers) {
return eHasNoRefs;
}
bool frameTypeOK = true;
nsSVGClipPathFrame* frame = static_cast<nsSVGClipPathFrame*>(
observers->GetAndObserveReferencedFrame(LayoutFrameType::SVGClipPath,
&frameTypeOK));
// Note that, unlike for filters, a reference to an ID that doesn't exist
// is not invalid for clip-path or mask.
if (!frameTypeOK || (frame && !frame->IsValid())) {
return eHasRefsSomeInvalid;
}
if (aClipPathFrame) {
*aClipPathFrame = frame;
}
return frame ? eHasRefsAllValid : eHasNoRefs;
}
SVGGeometryElement*
SVGObserverUtils::GetTextPathsReferencedPath(nsIFrame* aTextPathFrame)
{
@ -760,6 +837,7 @@ SVGObserverUtils::InitiateResourceDocLoads(nsIFrame* aFrame)
// We create observer objects and attach them to aFrame, but we do not
// make aFrame start observing the referenced frames.
Unused << GetOrCreateFilterObserverListForCSS(aFrame);
Unused << GetOrCreateClipPathObserver(aFrame);
Unused << GetEffectProperties(aFrame);
}
@ -849,14 +927,6 @@ SVGObserverUtils::GetEffectProperties(nsIFrame* aFrame)
EffectProperties result;
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
if (style->mClipPath.GetType() == StyleShapeSourceType::URL) {
RefPtr<URLAndReferrerInfo> pathURI = SVGObserverUtils::GetClipPathURI(aFrame);
result.mClipPath =
GetPaintingProperty(pathURI, aFrame, ClipPathProperty());
} else {
result.mClipPath = nullptr;
}
MOZ_ASSERT(style->mMask.mImageCount > 0);
result.mMaskObservers = style->HasMask()
? GetOrCreateMaskProperty(aFrame) : nullptr;
@ -908,19 +978,6 @@ SVGObserverUtils::GetPaintServer(nsIFrame* aTargetFrame,
return static_cast<nsSVGPaintServerFrame*>(result);
}
nsSVGClipPathFrame *
SVGObserverUtils::EffectProperties::GetClipPathFrame()
{
if (!mClipPath)
return nullptr;
nsSVGClipPathFrame* frame = static_cast<nsSVGClipPathFrame*>(
mClipPath->GetAndObserveReferencedFrame(LayoutFrameType::SVGClipPath,
nullptr));
return frame;
}
nsTArray<nsSVGMaskFrame *>
SVGObserverUtils::EffectProperties::GetMaskFrames()
{
@ -954,22 +1011,7 @@ SVGObserverUtils::EffectProperties::GetMaskFrames()
bool
SVGObserverUtils::EffectProperties::HasNoOrValidEffects()
{
return HasNoOrValidClipPath() && HasNoOrValidMask();
}
bool
SVGObserverUtils::EffectProperties::HasNoOrValidClipPath()
{
if (mClipPath) {
bool ok = true;
nsSVGClipPathFrame* frame = static_cast<nsSVGClipPathFrame*>(
mClipPath->GetAndObserveReferencedFrame(LayoutFrameType::SVGClipPath, &ok));
if (!ok || (frame && !frame->IsValid())) {
return false;
}
}
return true;
return HasNoOrValidMask();
}
bool
@ -1241,43 +1283,6 @@ SVGObserverUtils::GetBaseURLForLocalRef(nsIContent* content, nsIURI* aDocURI)
return baseURI.forget();
}
static already_AddRefed<URLAndReferrerInfo>
ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL)
{
MOZ_ASSERT(aFrame);
if (!aURL) {
return nullptr;
}
nsCOMPtr<nsIURI> uri = aURL->GetURI();
RefPtr<URLAndReferrerInfo> result;
// Non-local-reference URL.
if (!aURL->IsLocalRef()) {
if (!uri) {
return nullptr;
}
result = new URLAndReferrerInfo(uri,
aURL->mExtraData->GetReferrer(),
aURL->mExtraData->GetReferrerPolicy());
return result.forget();
}
nsCOMPtr<nsIURI> baseURI =
SVGObserverUtils::GetBaseURLForLocalRef(aFrame->GetContent(), uri);
nsCOMPtr<nsIURI> resolvedURI = aURL->ResolveLocalRef(baseURI);
if (!resolvedURI) {
return nullptr;
}
result = new URLAndReferrerInfo(resolvedURI,
aURL->mExtraData->GetReferrer(),
aURL->mExtraData->GetReferrerPolicy());
return result.forget();
}
already_AddRefed<URLAndReferrerInfo>
SVGObserverUtils::GetMarkerURI(nsIFrame* aFrame,
RefPtr<css::URLValue> nsStyleSVG::* aMarker)
@ -1285,16 +1290,6 @@ SVGObserverUtils::GetMarkerURI(nsIFrame* aFrame,
return ResolveURLUsingLocalRef(aFrame, aFrame->StyleSVG()->*aMarker);
}
already_AddRefed<URLAndReferrerInfo>
SVGObserverUtils::GetClipPathURI(nsIFrame* aFrame)
{
const nsStyleSVGReset* svgResetStyle = aFrame->StyleSVGReset();
MOZ_ASSERT(svgResetStyle->mClipPath.GetType() == StyleShapeSourceType::URL);
css::URLValue* url = svgResetStyle->mClipPath.GetURL();
return ResolveURLUsingLocalRef(aFrame, url);
}
already_AddRefed<URLAndReferrerInfo>
SVGObserverUtils::GetFilterURI(nsIFrame* aFrame, uint32_t aIndex)
{

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

@ -583,12 +583,6 @@ public:
struct EffectProperties {
SVGMaskObserverList* mMaskObservers;
nsSVGPaintingProperty* mClipPath;
/**
* @return the clip-path frame, or null if there is no clip-path frame
*/
nsSVGClipPathFrame* GetClipPathFrame();
/**
* @return an array which contains all SVG mask frames.
@ -608,19 +602,6 @@ public:
return !HasNoOrValidEffects();
}
/*
* @return true if we either do not have clip-path or have a valid
* clip-path.
*/
bool HasNoOrValidClipPath();
/*
* @return true if we have an invalid clip-path.
*/
bool HasInvalidClipPath() {
return !HasNoOrValidClipPath();
}
/*
* @return true if we either do not have mask or all masks we have
* are valid.
@ -793,6 +774,27 @@ public:
static void
DetachFromCanvasContext(nsISupports* aAutoObserver);
/**
* Get the frame of the SVG clipPath applied to aClippedFrame, if any, and
* set up aClippedFrame as a rendering observer of the clipPath's frame, to
* be invalidated if it changes.
*
* Currently we only have support for 'clip-path' with a single item, but the
* spec. now says 'clip-path' can be set to an arbitrary number of items.
* Once we support that, aClipPathFrame will need to be an nsTArray as it
* is for 'filter' and 'mask'. Currently a return value of eHasNoRefs means
* that there is no clipping at all, but once we support more than one item
* then - as for filter and mask - we could still have basic shape clipping
* to apply even if there are no references to SVG clipPath elements.
*
* Note that, unlike for filters, a reference to an ID that doesn't exist
* is not invalid for clip-path or mask. We will return eHasNoRefs in that
* case.
*/
static ReferenceState
GetAndObserveClipPath(nsIFrame* aClippedFrame,
nsSVGClipPathFrame** aClipPathFrame);
/**
* Get the SVGGeometryElement that is referenced by aTextPathFrame, and make
* aTextPathFrame start observing rendering changes to that element.
@ -849,12 +851,6 @@ public:
GetMarkerURI(nsIFrame* aFrame,
RefPtr<mozilla::css::URLValue> nsStyleSVG::* aMarker);
/**
* A helper function to resolve clip-path URL.
*/
static already_AddRefed<URLAndReferrerInfo>
GetClipPathURI(nsIFrame* aFrame);
/**
* A helper function to resolve filter URL.
*/

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

@ -146,8 +146,9 @@ nsSVGClipPathFrame::PaintClipMask(gfxContext& aMaskContext,
mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;
// Check if this clipPath is itself clipped by another clipPath:
nsSVGClipPathFrame* clipPathThatClipsClipPath =
SVGObserverUtils::GetEffectProperties(this).GetClipPathFrame();
nsSVGClipPathFrame* clipPathThatClipsClipPath;
// XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(this, &clipPathThatClipsClipPath);
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(this, true, maskUsage);
@ -203,13 +204,12 @@ nsSVGClipPathFrame::PaintFrameIntoMask(nsIFrame *aFrame,
frame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
// Children of this clipPath may themselves be clipped.
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(aFrame);
if (effectProperties.HasInvalidClipPath()) {
nsSVGClipPathFrame* clipPathThatClipsChild;
// XXX check return value?
if (SVGObserverUtils::GetAndObserveClipPath(aFrame, &clipPathThatClipsChild) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
return;
}
nsSVGClipPathFrame *clipPathThatClipsChild =
effectProperties.GetClipPathFrame();
nsSVGUtils::MaskUsage maskUsage;
nsSVGUtils::DetermineMaskUsage(aFrame, true, maskUsage);
@ -306,8 +306,9 @@ nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,
// clipped by the original clipPath. If this clipPath is being clipped by a
// different clip path we need to check if it prevents the original element
// from receiving events at aPoint:
nsSVGClipPathFrame *clipPathFrame =
SVGObserverUtils::GetEffectProperties(this).GetClipPathFrame();
nsSVGClipPathFrame* clipPathFrame;
// XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(this, &clipPathFrame);
if (clipPathFrame &&
!clipPathFrame->PointIsInsideClipPath(aClippedFrame, aPoint)) {
return false;
@ -339,8 +340,10 @@ bool
nsSVGClipPathFrame::IsTrivial(nsSVGDisplayableFrame **aSingleChild)
{
// If the clip path is clipped then it's non-trivial
if (SVGObserverUtils::GetEffectProperties(this).GetClipPathFrame())
if (SVGObserverUtils::GetAndObserveClipPath(this, nullptr) ==
SVGObserverUtils::eHasRefsAllValid) {
return false;
}
if (aSingleChild) {
*aSingleChild = nullptr;
@ -358,8 +361,10 @@ nsSVGClipPathFrame::IsTrivial(nsSVGDisplayableFrame **aSingleChild)
return false;
// or where the child is itself clipped
if (SVGObserverUtils::GetEffectProperties(kid).GetClipPathFrame())
if (SVGObserverUtils::GetAndObserveClipPath(kid, nullptr) ==
SVGObserverUtils::eHasRefsAllValid) {
return false;
}
foundChild = svgChild;
}
@ -384,7 +389,8 @@ nsSVGClipPathFrame::IsValid()
return false; // Break reference chain
}
if (SVGObserverUtils::GetEffectProperties(this).HasInvalidClipPath()) {
if (SVGObserverUtils::GetAndObserveClipPath(this, nullptr) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
return false;
}
@ -478,6 +484,12 @@ nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox &aBBox,
const gfxMatrix &aMatrix,
uint32_t aFlags)
{
nsSVGClipPathFrame* clipPathThatClipsClipPath;
if (SVGObserverUtils::GetAndObserveClipPath(this, &clipPathThatClipsClipPath) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
return SVGBBox();
}
nsIContent* node = GetContent()->GetFirstChild();
SVGBBox unionBBox, tmpBBox;
for (; node; node = node->GetNextSibling()) {
@ -489,14 +501,11 @@ nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox &aBBox,
gfxMatrix matrix = svgNode->PrependLocalTransformsTo(aMatrix, eUserSpaceToParent);
tmpBBox = svg->GetBBoxContribution(mozilla::gfx::ToMatrix(matrix),
nsSVGUtils::eBBoxIncludeFill);
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(frame);
if (effectProperties.HasNoOrValidClipPath()) {
nsSVGClipPathFrame *clipPathFrame =
effectProperties.GetClipPathFrame();
if (clipPathFrame) {
tmpBBox = clipPathFrame->GetBBoxForClipPathFrame(tmpBBox, aMatrix, aFlags);
}
nsSVGClipPathFrame* clipPathFrame;
if (SVGObserverUtils::GetAndObserveClipPath(frame, &clipPathFrame) !=
SVGObserverUtils::eHasRefsSomeInvalid &&
clipPathFrame) {
tmpBBox = clipPathFrame->GetBBoxForClipPathFrame(tmpBBox, aMatrix, aFlags);
}
if (!(aFlags & nsSVGUtils::eDoNotClipToBBoxOfContentInsideClipPath)) {
tmpBBox.Intersect(aBBox);
@ -506,18 +515,10 @@ nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox &aBBox,
}
}
SVGObserverUtils::EffectProperties props =
SVGObserverUtils::GetEffectProperties(this);
if (props.mClipPath) {
if (props.HasInvalidClipPath()) {
unionBBox = SVGBBox();
} else {
nsSVGClipPathFrame *clipPathFrame = props.GetClipPathFrame();
if (clipPathFrame) {
tmpBBox = clipPathFrame->GetBBoxForClipPathFrame(aBBox, aMatrix, aFlags);
unionBBox.Intersect(tmpBBox);
}
}
if (clipPathThatClipsClipPath) {
tmpBBox =
clipPathThatClipsClipPath->GetBBoxForClipPathFrame(aBBox, aMatrix, aFlags);
unionBBox.Intersect(tmpBBox);
}
return unionBBox;
}

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

@ -875,7 +875,9 @@ nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams)
Matrix clipMaskTransform;
gfxMatrix cssPxToDevPxMatrix = nsSVGUtils::GetCSSPxToDevPxMatrix(frame);
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
nsSVGClipPathFrame* clipPathFrame;
// XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(firstFrame, &clipPathFrame);
RefPtr<SourceSurface> maskSurface =
maskUsage.shouldGenerateMaskLayer ? maskTarget->Snapshot() : nullptr;
clipPathFrame->PaintClipMask(ctx, frame, cssPxToDevPxMatrix,
@ -929,7 +931,9 @@ void PaintMaskAndClipPathInternal(const PaintFramesParams& aParams, const T& aPa
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(firstFrame);
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
nsSVGClipPathFrame* clipPathFrame;
// XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(firstFrame, &clipPathFrame);
gfxMatrix cssPxToDevPxMatrix = nsSVGUtils::GetCSSPxToDevPxMatrix(frame);
nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();

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

@ -495,7 +495,9 @@ nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
aUsage.shouldGenerateMaskLayer = (maskFrames.Length() > 0);
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
nsSVGClipPathFrame* clipPathFrame;
// XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(firstFrame, &clipPathFrame);
MOZ_ASSERT(!clipPathFrame ||
svgReset->mClipPath.GetType() == StyleShapeSourceType::URL);
@ -711,6 +713,7 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
/* Properties are added lazily and may have been removed by a restyle,
so make sure all applicable ones are set again. */
nsSVGClipPathFrame* clipPathFrame;
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(aFrame);
// TODO: We currently pass nullptr instead of an nsTArray* here, but we
@ -718,12 +721,13 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
// PaintFilteredFrame below! See bug 1494263.
if (effectProperties.HasInvalidEffects() ||
SVGObserverUtils::GetAndObserveFilters(aFrame, nullptr) ==
SVGObserverUtils::eHasRefsSomeInvalid ||
SVGObserverUtils::GetAndObserveClipPath(aFrame, &clipPathFrame) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
// Some resource is invalid. We shouldn't paint anything.
return;
}
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
nsTArray<nsSVGMaskFrame*> masks = effectProperties.GetMaskFrames();
nsSVGMaskFrame *maskFrame = masks.IsEmpty() ? nullptr : masks[0];
@ -872,29 +876,18 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
bool
nsSVGUtils::HitTestClip(nsIFrame *aFrame, const gfxPoint &aPoint)
{
SVGObserverUtils::EffectProperties props =
SVGObserverUtils::GetEffectProperties(aFrame);
if (!props.mClipPath) {
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
if (style->HasClipPath()) {
return nsCSSClipPathInstance::HitTestBasicShapeOrPathClip(aFrame, aPoint);
}
return true;
nsSVGClipPathFrame* clipPathFrame;
if (SVGObserverUtils::GetAndObserveClipPath(aFrame, &clipPathFrame) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
return false; // everything clipped away if clip path is invalid
}
if (props.HasInvalidClipPath()) {
// clipPath is not a valid resource, so nothing gets painted, so
// hit-testing must fail.
return false;
if (clipPathFrame) {
return clipPathFrame->PointIsInsideClipPath(aFrame, aPoint);
}
nsSVGClipPathFrame *clipPathFrame = props.GetClipPathFrame();
if (!clipPathFrame) {
// clipPath doesn't exist, ignore it.
return true;
if (aFrame->StyleSVGReset()->HasClipPath()) {
return nsCSSClipPathInstance::HitTestBasicShapeOrPathClip(aFrame, aPoint);
}
return clipPathFrame->PointIsInsideClipPath(aFrame, aPoint);
return true;
}
nsIFrame *
@ -1162,13 +1155,11 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, uint32_t aFlags,
clipRect = matrix.TransformBounds(clipRect);
}
}
SVGObserverUtils::EffectProperties effectProperties =
SVGObserverUtils::GetEffectProperties(aFrame);
if (effectProperties.HasInvalidClipPath()) {
nsSVGClipPathFrame* clipPathFrame;
if (SVGObserverUtils::GetAndObserveClipPath(aFrame, &clipPathFrame) ==
SVGObserverUtils::eHasRefsSomeInvalid) {
bbox = gfxRect(0, 0, 0, 0);
} else {
nsSVGClipPathFrame *clipPathFrame =
effectProperties.GetClipPathFrame();
if (clipPathFrame) {
SVGClipPathElement *clipContent =
static_cast<SVGClipPathElement*>(clipPathFrame->GetContent());