LCOV - code coverage report
Current view: top level - layout/svg - nsSVGClipPathFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 57 225 25.3 %
Date: 2017-07-14 16:53:18 Functions: 7 16 43.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : // Main header first:
       7             : #include "nsSVGClipPathFrame.h"
       8             : 
       9             : // Keep others in (case-insensitive) order:
      10             : #include "AutoReferenceChainGuard.h"
      11             : #include "DrawResult.h"
      12             : #include "gfxContext.h"
      13             : #include "mozilla/dom/SVGClipPathElement.h"
      14             : #include "nsGkAtoms.h"
      15             : #include "nsSVGEffects.h"
      16             : #include "SVGGeometryElement.h"
      17             : #include "SVGGeometryFrame.h"
      18             : #include "nsSVGUtils.h"
      19             : 
      20             : using namespace mozilla;
      21             : using namespace mozilla::dom;
      22             : using namespace mozilla::gfx;
      23             : using namespace mozilla::image;
      24             : 
      25             : //----------------------------------------------------------------------
      26             : // Implementation
      27             : 
      28             : nsIFrame*
      29           6 : NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      30             : {
      31           6 :   return new (aPresShell) nsSVGClipPathFrame(aContext);
      32             : }
      33             : 
      34           6 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGClipPathFrame)
      35             : 
      36             : void
      37           2 : nsSVGClipPathFrame::ApplyClipPath(gfxContext& aContext,
      38             :                                   nsIFrame* aClippedFrame,
      39             :                                   const gfxMatrix& aMatrix)
      40             : {
      41           2 :   MOZ_ASSERT(IsTrivial(), "Caller needs to use GetClipMask");
      42             : 
      43           2 :   DrawTarget& aDrawTarget = *aContext.GetDrawTarget();
      44             : 
      45             :   // No need for AutoReferenceChainGuard since simple clip paths by definition
      46             :   // don't reference another clip path.
      47             : 
      48             :   // Restore current transform after applying clip path:
      49           4 :   gfxContextMatrixAutoSaveRestore autoRestore(&aContext);
      50             : 
      51           4 :   RefPtr<Path> clipPath;
      52             : 
      53           2 :   nsSVGDisplayableFrame* singleClipPathChild = nullptr;
      54           2 :   IsTrivial(&singleClipPathChild);
      55             : 
      56           2 :   if (singleClipPathChild) {
      57           2 :     SVGGeometryFrame* pathFrame = do_QueryFrame(singleClipPathChild);
      58           2 :     if (pathFrame) {
      59             :       SVGGeometryElement* pathElement =
      60           2 :         static_cast<SVGGeometryElement*>(pathFrame->GetContent());
      61             :       gfxMatrix toChildsUserSpace = pathElement->
      62           4 :         PrependLocalTransformsTo(GetClipPathTransform(aClippedFrame) * aMatrix,
      63           4 :                                  eUserSpaceToParent);
      64             :       gfxMatrix newMatrix =
      65           2 :         aContext.CurrentMatrix().PreMultiply(toChildsUserSpace).NudgeToIntegers();
      66           2 :       if (!newMatrix.IsSingular()) {
      67           2 :         aContext.SetMatrix(newMatrix);
      68             :         FillRule clipRule =
      69           2 :           nsSVGUtils::ToFillRule(pathFrame->StyleSVG()->mClipRule);
      70           2 :         clipPath = pathElement->GetOrBuildPath(aDrawTarget, clipRule);
      71             :       }
      72             :     }
      73             :   }
      74             : 
      75           2 :   if (clipPath) {
      76           2 :     aContext.Clip(clipPath);
      77             :   } else {
      78             :     // The spec says clip away everything if we have no children or the
      79             :     // clipping path otherwise can't be resolved:
      80           0 :     aContext.Clip(Rect());
      81             :   }
      82           2 : }
      83             : 
      84             : already_AddRefed<DrawTarget>
      85           0 : nsSVGClipPathFrame::CreateClipMask(gfxContext& aReferenceContext,
      86             :                                    IntPoint& aOffset)
      87             : {
      88           0 :   gfxContextMatrixAutoSaveRestore autoRestoreMatrix(&aReferenceContext);
      89             : 
      90           0 :   aReferenceContext.SetMatrix(gfxMatrix());
      91           0 :   gfxRect rect = aReferenceContext.GetClipExtents();
      92           0 :   IntRect bounds = RoundedOut(ToRect(rect));
      93           0 :   if (bounds.IsEmpty()) {
      94             :     // We don't need to create a mask surface, all drawing is clipped anyway.
      95           0 :     return nullptr;
      96             :   }
      97             : 
      98           0 :   DrawTarget* referenceDT = aReferenceContext.GetDrawTarget();
      99             :   RefPtr<DrawTarget> maskDT =
     100           0 :     referenceDT->CreateSimilarDrawTarget(bounds.Size(), SurfaceFormat::A8);
     101             : 
     102           0 :   aOffset = bounds.TopLeft();
     103             : 
     104           0 :   return maskDT.forget();
     105             : }
     106             : 
     107             : static void
     108           0 : ComposeExtraMask(DrawTarget* aTarget, const gfxMatrix& aMaskTransfrom,
     109             :                  SourceSurface* aExtraMask, const Matrix& aExtraMasksTransform)
     110             : {
     111           0 :   MOZ_ASSERT(aExtraMask);
     112             : 
     113           0 :   Matrix origin = aTarget->GetTransform();
     114           0 :   aTarget->SetTransform(aExtraMasksTransform * aTarget->GetTransform());
     115           0 :   aTarget->MaskSurface(ColorPattern(Color(0.0, 0.0, 0.0, 1.0)),
     116             :                        aExtraMask,
     117             :                        Point(0, 0),
     118           0 :                        DrawOptions(1.0, CompositionOp::OP_IN));
     119           0 :   aTarget->SetTransform(origin);
     120           0 : }
     121             : 
     122             : void
     123           0 : nsSVGClipPathFrame::PaintClipMask(gfxContext& aMaskContext,
     124             :                                   nsIFrame* aClippedFrame,
     125             :                                   const gfxMatrix& aMatrix,
     126             :                                   Matrix* aMaskTransform,
     127             :                                   SourceSurface* aExtraMask,
     128             :                                   const Matrix& aExtraMasksTransform)
     129             : {
     130             :   static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
     131             : 
     132             :   // A clipPath can reference another clipPath, creating a chain of clipPaths
     133             :   // that must all be applied.  We re-enter this method for each clipPath in a
     134             :   // chain, so we need to protect against reference chain related crashes etc.:
     135             :   AutoReferenceChainGuard refChainGuard(this, &mIsBeingProcessed,
     136           0 :                                         &sRefChainLengthCounter);
     137           0 :   if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
     138           0 :     return; // Break reference chain
     139             :   }
     140             : 
     141           0 :   DrawTarget* maskDT = aMaskContext.GetDrawTarget();
     142           0 :   MOZ_ASSERT(maskDT->GetFormat() == SurfaceFormat::A8);
     143             : 
     144             :   // Paint this clipPath's contents into aMaskDT:
     145             :   // We need to set mMatrixForChildren here so that under the PaintSVG calls
     146             :   // on our children (below) our GetCanvasTM() method will return the correct
     147             :   // transform.
     148           0 :   mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;
     149             : 
     150             :   // Check if this clipPath is itself clipped by another clipPath:
     151             :   nsSVGClipPathFrame* clipPathThatClipsClipPath =
     152           0 :     nsSVGEffects::GetEffectProperties(this).GetClipPathFrame();
     153           0 :   nsSVGUtils::MaskUsage maskUsage;
     154           0 :   nsSVGUtils::DetermineMaskUsage(this, true, maskUsage);
     155             : 
     156           0 :   if (maskUsage.shouldApplyClipPath) {
     157             :     clipPathThatClipsClipPath->ApplyClipPath(aMaskContext, aClippedFrame,
     158           0 :                                              aMatrix);
     159           0 :   } else if (maskUsage.shouldGenerateClipMaskLayer) {
     160           0 :     Matrix maskTransform;
     161             :     RefPtr<SourceSurface> maskSurface =
     162           0 :       clipPathThatClipsClipPath->GetClipMask(aMaskContext, aClippedFrame,
     163           0 :                                              aMatrix, &maskTransform);
     164           0 :     aMaskContext.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
     165           0 :                                        maskSurface, maskTransform);
     166             :     // The corresponding PopGroupAndBlend call below will mask the
     167             :     // blend using |maskSurface|.
     168             :   }
     169             : 
     170             :   // Paint our children into the mask:
     171           0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     172             :        kid = kid->GetNextSibling()) {
     173           0 :     PaintFrameIntoMask(kid, aClippedFrame, aMaskContext, aMatrix);
     174             :   }
     175             : 
     176           0 :   if (maskUsage.shouldGenerateClipMaskLayer) {
     177           0 :     aMaskContext.PopGroupAndBlend();
     178           0 :   } else if (maskUsage.shouldApplyClipPath) {
     179           0 :     aMaskContext.PopClip();
     180             :   }
     181             : 
     182             :   // Moz2D transforms in the opposite direction to Thebes
     183           0 :   gfxMatrix maskTransfrom = aMaskContext.CurrentMatrix();
     184           0 :   maskTransfrom.Invert();
     185             : 
     186           0 :   if (aExtraMask) {
     187           0 :     ComposeExtraMask(maskDT, maskTransfrom, aExtraMask, aExtraMasksTransform);
     188             :   }
     189             : 
     190           0 :   *aMaskTransform = ToMatrix(maskTransfrom);
     191             : }
     192             : 
     193             : void
     194           0 : nsSVGClipPathFrame::PaintFrameIntoMask(nsIFrame *aFrame,
     195             :                                        nsIFrame* aClippedFrame,
     196             :                                        gfxContext& aTarget,
     197             :                                        const gfxMatrix& aMatrix)
     198             : {
     199           0 :   nsSVGDisplayableFrame* frame = do_QueryFrame(aFrame);
     200           0 :   if (!frame) {
     201           0 :     return;
     202             :   }
     203             : 
     204             :   // The CTM of each frame referencing us can be different.
     205           0 :   frame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
     206             : 
     207             :   // Children of this clipPath may themselves be clipped.
     208             :   nsSVGEffects::EffectProperties effectProperties =
     209           0 :     nsSVGEffects::GetEffectProperties(aFrame);
     210           0 :   if (effectProperties.HasInvalidClipPath()) {
     211           0 :     return;
     212             :   }
     213             :   nsSVGClipPathFrame *clipPathThatClipsChild =
     214           0 :     effectProperties.GetClipPathFrame();
     215             : 
     216           0 :   nsSVGUtils::MaskUsage maskUsage;
     217           0 :   nsSVGUtils::DetermineMaskUsage(aFrame, true, maskUsage);
     218           0 :   if (maskUsage.shouldApplyClipPath) {
     219           0 :     clipPathThatClipsChild->ApplyClipPath(aTarget, aClippedFrame, aMatrix);
     220           0 :   } else if (maskUsage.shouldGenerateClipMaskLayer) {
     221           0 :     Matrix maskTransform;
     222             :     RefPtr<SourceSurface> maskSurface =
     223           0 :       clipPathThatClipsChild->GetClipMask(aTarget, aClippedFrame,
     224           0 :                                           aMatrix, &maskTransform);
     225           0 :     aTarget.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0,
     226           0 :                                   maskSurface, maskTransform);
     227             :     // The corresponding PopGroupAndBlend call below will mask the
     228             :     // blend using |maskSurface|.
     229             :   }
     230             : 
     231           0 :   gfxMatrix toChildsUserSpace = mMatrixForChildren;
     232           0 :   nsIFrame* child = do_QueryFrame(frame);
     233           0 :   nsIContent* childContent = child->GetContent();
     234           0 :   if (childContent->IsSVGElement()) {
     235             :     toChildsUserSpace =
     236             :       static_cast<const nsSVGElement*>(childContent)->
     237           0 :         PrependLocalTransformsTo(mMatrixForChildren, eUserSpaceToParent);
     238             :   }
     239             : 
     240             :   // clipPath does not result in any image rendering, so we just use a dummy
     241             :   // imgDrawingParams instead of requiring our caller to pass one.
     242           0 :   image::imgDrawingParams imgParams;
     243             : 
     244             :   // Our children have NS_STATE_SVG_CLIPPATH_CHILD set on them, and
     245             :   // SVGGeometryFrame::Render checks for that state bit and paints
     246             :   // only the geometry (opaque black) if set.
     247           0 :   frame->PaintSVG(aTarget, toChildsUserSpace, imgParams);
     248             : 
     249           0 :   if (maskUsage.shouldGenerateClipMaskLayer) {
     250           0 :     aTarget.PopGroupAndBlend();
     251           0 :   } else if (maskUsage.shouldApplyClipPath) {
     252           0 :     aTarget.PopClip();
     253             :   }
     254             : }
     255             : 
     256             : already_AddRefed<SourceSurface>
     257           0 : nsSVGClipPathFrame::GetClipMask(gfxContext& aReferenceContext,
     258             :                                 nsIFrame* aClippedFrame,
     259             :                                 const gfxMatrix& aMatrix,
     260             :                                 Matrix* aMaskTransform,
     261             :                                 SourceSurface* aExtraMask,
     262             :                                 const Matrix& aExtraMasksTransform)
     263             : {
     264           0 :   IntPoint offset;
     265           0 :   RefPtr<DrawTarget> maskDT = CreateClipMask(aReferenceContext, offset);
     266           0 :   if (!maskDT) {
     267           0 :     return nullptr;
     268             :   }
     269             : 
     270           0 :   RefPtr<gfxContext> maskContext = gfxContext::CreateOrNull(maskDT);
     271           0 :   if (!maskContext) {
     272           0 :     gfxCriticalError() << "SVGClipPath context problem " << gfx::hexa(maskDT);
     273           0 :     return nullptr;
     274             :   }
     275           0 :   maskContext->SetMatrix(aReferenceContext.CurrentMatrix() *
     276           0 :                          gfxMatrix::Translation(-offset));
     277             : 
     278           0 :   PaintClipMask(*maskContext, aClippedFrame, aMatrix, aMaskTransform,
     279           0 :                 aExtraMask, aExtraMasksTransform);
     280             : 
     281           0 :   RefPtr<SourceSurface> surface = maskDT->Snapshot();
     282           0 :   return surface.forget();
     283             : }
     284             : 
     285             : bool
     286           0 : nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,
     287             :                                           const gfxPoint &aPoint)
     288             : {
     289             :   static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
     290             : 
     291             :   // A clipPath can reference another clipPath, creating a chain of clipPaths
     292             :   // that must all be applied.  We re-enter this method for each clipPath in a
     293             :   // chain, so we need to protect against reference chain related crashes etc.:
     294             :   AutoReferenceChainGuard refChainGuard(this, &mIsBeingProcessed,
     295           0 :                                         &sRefChainLengthCounter);
     296           0 :   if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
     297           0 :     return false; // Break reference chain
     298             :   }
     299             : 
     300           0 :   gfxMatrix matrix = GetClipPathTransform(aClippedFrame);
     301           0 :   if (!matrix.Invert()) {
     302           0 :     return false;
     303             :   }
     304           0 :   gfxPoint point = matrix.TransformPoint(aPoint);
     305             : 
     306             :   // clipPath elements can themselves be clipped by a different clip path. In
     307             :   // that case the other clip path further clips away the element that is being
     308             :   // clipped by the original clipPath. If this clipPath is being clipped by a
     309             :   // different clip path we need to check if it prevents the original element
     310             :   // from recieving events at aPoint:
     311             :   nsSVGClipPathFrame *clipPathFrame =
     312           0 :     nsSVGEffects::GetEffectProperties(this).GetClipPathFrame();
     313           0 :   if (clipPathFrame &&
     314           0 :       !clipPathFrame->PointIsInsideClipPath(aClippedFrame, aPoint)) {
     315           0 :     return false;
     316             :   }
     317             : 
     318           0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     319             :        kid = kid->GetNextSibling()) {
     320           0 :     nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
     321           0 :     if (SVGFrame) {
     322           0 :       gfxPoint pointForChild = point;
     323           0 :       gfxMatrix m = static_cast<nsSVGElement*>(kid->GetContent())->
     324           0 :         PrependLocalTransformsTo(gfxMatrix(), eUserSpaceToParent);
     325           0 :       if (!m.IsIdentity()) {
     326           0 :         if (!m.Invert()) {
     327           0 :           return false;
     328             :         }
     329           0 :         pointForChild = m.TransformPoint(point);
     330             :       }
     331           0 :       if (SVGFrame->GetFrameForPoint(pointForChild)) {
     332           0 :         return true;
     333             :       }
     334             :     }
     335             :   }
     336             : 
     337           0 :   return false;
     338             : }
     339             : 
     340             : bool
     341           6 : nsSVGClipPathFrame::IsTrivial(nsSVGDisplayableFrame **aSingleChild)
     342             : {
     343             :   // If the clip path is clipped then it's non-trivial
     344           6 :   if (nsSVGEffects::GetEffectProperties(this).GetClipPathFrame())
     345           0 :     return false;
     346             : 
     347           6 :   if (aSingleChild) {
     348           2 :     *aSingleChild = nullptr;
     349             :   }
     350             : 
     351           6 :   nsSVGDisplayableFrame* foundChild = nullptr;
     352             : 
     353          12 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     354             :        kid = kid->GetNextSibling()) {
     355           6 :     nsSVGDisplayableFrame* svgChild = do_QueryFrame(kid);
     356           6 :     if (svgChild) {
     357             :       // We consider a non-trivial clipPath to be one containing
     358             :       // either more than one svg child and/or a svg container
     359           6 :       if (foundChild || svgChild->IsDisplayContainer())
     360           0 :         return false;
     361             : 
     362             :       // or where the child is itself clipped
     363           6 :       if (nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame())
     364           0 :         return false;
     365             : 
     366           6 :       foundChild = svgChild;
     367             :     }
     368             :   }
     369           6 :   if (aSingleChild) {
     370           2 :     *aSingleChild = foundChild;
     371             :   }
     372           6 :   return true;
     373             : }
     374             : 
     375             : bool
     376           2 : nsSVGClipPathFrame::IsValid()
     377             : {
     378             :   static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
     379             : 
     380             :   // A clipPath can reference another clipPath, creating a chain of clipPaths
     381             :   // that must all be applied.  We re-enter this method for each clipPath in a
     382             :   // chain, so we need to protect against reference chain related crashes etc.:
     383             :   AutoReferenceChainGuard refChainGuard(this, &mIsBeingProcessed,
     384           4 :                                         &sRefChainLengthCounter);
     385           2 :   if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
     386           0 :     return false; // Break reference chain
     387             :   }
     388             : 
     389           2 :   if (nsSVGEffects::GetEffectProperties(this).HasInvalidClipPath()) {
     390           0 :     return false;
     391             :   }
     392             : 
     393           4 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     394             :        kid = kid->GetNextSibling()) {
     395             : 
     396           2 :     LayoutFrameType kidType = kid->Type();
     397             : 
     398           2 :     if (kidType == LayoutFrameType::SVGUse) {
     399           0 :       for (nsIFrame* grandKid : kid->PrincipalChildList()) {
     400             : 
     401           0 :         LayoutFrameType grandKidType = grandKid->Type();
     402             : 
     403           0 :         if (grandKidType != LayoutFrameType::SVGGeometry &&
     404             :             grandKidType != LayoutFrameType::SVGText) {
     405           0 :           return false;
     406             :         }
     407             :       }
     408           0 :       continue;
     409             :     }
     410             : 
     411           2 :     if (kidType != LayoutFrameType::SVGGeometry &&
     412             :         kidType != LayoutFrameType::SVGText) {
     413           0 :       return false;
     414             :     }
     415             :   }
     416             : 
     417           2 :   return true;
     418             : }
     419             : 
     420             : nsresult
     421           0 : nsSVGClipPathFrame::AttributeChanged(int32_t         aNameSpaceID,
     422             :                                      nsIAtom*        aAttribute,
     423             :                                      int32_t         aModType)
     424             : {
     425           0 :   if (aNameSpaceID == kNameSpaceID_None) {
     426           0 :     if (aAttribute == nsGkAtoms::transform) {
     427           0 :       nsSVGEffects::InvalidateDirectRenderingObservers(this);
     428           0 :       nsSVGUtils::NotifyChildrenOfSVGChange(this,
     429           0 :                                             nsSVGDisplayableFrame::TRANSFORM_CHANGED);
     430             :     }
     431           0 :     if (aAttribute == nsGkAtoms::clipPathUnits) {
     432           0 :       nsSVGEffects::InvalidateDirectRenderingObservers(this);
     433             :     }
     434             :   }
     435             : 
     436           0 :   return nsSVGContainerFrame::AttributeChanged(aNameSpaceID,
     437           0 :                                                aAttribute, aModType);
     438             : }
     439             : 
     440             : void
     441           6 : nsSVGClipPathFrame::Init(nsIContent*       aContent,
     442             :                          nsContainerFrame* aParent,
     443             :                          nsIFrame*         aPrevInFlow)
     444             : {
     445           6 :   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::clipPath),
     446             :                "Content is not an SVG clipPath!");
     447             : 
     448           6 :   AddStateBits(NS_STATE_SVG_CLIPPATH_CHILD);
     449           6 :   nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
     450           6 : }
     451             : 
     452             : gfxMatrix
     453           0 : nsSVGClipPathFrame::GetCanvasTM()
     454             : {
     455           0 :   return mMatrixForChildren;
     456             : }
     457             : 
     458             : gfxMatrix
     459           2 : nsSVGClipPathFrame::GetClipPathTransform(nsIFrame* aClippedFrame)
     460             : {
     461           2 :   SVGClipPathElement *content = static_cast<SVGClipPathElement*>(mContent);
     462             : 
     463           2 :   gfxMatrix tm = content->PrependLocalTransformsTo(gfxMatrix());
     464             : 
     465             :   nsSVGEnum* clipPathUnits =
     466           2 :     &content->mEnumAttributes[SVGClipPathElement::CLIPPATHUNITS];
     467             : 
     468           2 :   return nsSVGUtils::AdjustMatrixForUnits(tm, clipPathUnits, aClippedFrame);
     469             : }
     470             : 
     471             : SVGBBox
     472           0 : nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox &aBBox,
     473             :                                             const gfxMatrix &aMatrix)
     474             : {
     475           0 :   nsIContent* node = GetContent()->GetFirstChild();
     476           0 :   SVGBBox unionBBox, tmpBBox;
     477           0 :   for (; node; node = node->GetNextSibling()) {
     478             :     nsIFrame *frame =
     479           0 :       static_cast<nsSVGElement*>(node)->GetPrimaryFrame();
     480           0 :     if (frame) {
     481           0 :       nsSVGDisplayableFrame* svg = do_QueryFrame(frame);
     482           0 :       if (svg) {
     483           0 :         tmpBBox = svg->GetBBoxContribution(mozilla::gfx::ToMatrix(aMatrix),
     484           0 :                                            nsSVGUtils::eBBoxIncludeFill);
     485             :         nsSVGEffects::EffectProperties effectProperties =
     486           0 :                               nsSVGEffects::GetEffectProperties(frame);
     487           0 :         if (effectProperties.HasNoOrValidClipPath()) {
     488             :           nsSVGClipPathFrame *clipPathFrame =
     489           0 :             effectProperties.GetClipPathFrame();
     490           0 :           if (clipPathFrame) {
     491           0 :             tmpBBox = clipPathFrame->GetBBoxForClipPathFrame(tmpBBox, aMatrix);
     492             :           }
     493             :         }
     494           0 :         tmpBBox.Intersect(aBBox);
     495           0 :         unionBBox.UnionEdges(tmpBBox);
     496             :       }
     497             :     }
     498             :   }
     499             : 
     500             :   nsSVGEffects::EffectProperties props =
     501           0 :     nsSVGEffects::GetEffectProperties(this);
     502           0 :   if (props.mClipPath) {
     503           0 :     if (props.HasInvalidClipPath()) {
     504           0 :       unionBBox = SVGBBox();
     505             :     } else  {
     506           0 :       nsSVGClipPathFrame *clipPathFrame = props.GetClipPathFrame();
     507           0 :       if (clipPathFrame) {
     508           0 :         tmpBBox = clipPathFrame->GetBBoxForClipPathFrame(aBBox, aMatrix);
     509           0 :         unionBBox.Intersect(tmpBBox);
     510             :       }
     511             :     }
     512             :   }
     513           0 :   return unionBBox;
     514             : }

Generated by: LCOV version 1.13