LCOV - code coverage report
Current view: directory - layout/svg/base/src - nsSVGClipPathFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 131 0 0.0 %
Date: 2012-06-02 Functions: 11 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Mozilla SVG project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is IBM Corporation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2004
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "nsIDOMDocument.h"
      38                 : #include "nsIDocument.h"
      39                 : #include "nsIDOMSVGClipPathElement.h"
      40                 : #include "nsSVGClipPathFrame.h"
      41                 : #include "nsGkAtoms.h"
      42                 : #include "nsSVGUtils.h"
      43                 : #include "nsSVGEffects.h"
      44                 : #include "nsSVGClipPathElement.h"
      45                 : #include "gfxContext.h"
      46                 : 
      47                 : //----------------------------------------------------------------------
      48                 : // Implementation
      49                 : 
      50                 : nsIFrame*
      51               0 : NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      52                 : {
      53               0 :   return new (aPresShell) nsSVGClipPathFrame(aContext);
      54                 : }
      55                 : 
      56               0 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGClipPathFrame)
      57                 : 
      58                 : nsresult
      59               0 : nsSVGClipPathFrame::ClipPaint(nsRenderingContext* aContext,
      60                 :                               nsIFrame* aParent,
      61                 :                               const gfxMatrix &aMatrix)
      62                 : {
      63                 :   // If the flag is set when we get here, it means this clipPath frame
      64                 :   // has already been used painting the current clip, and the document
      65                 :   // has a clip reference loop.
      66               0 :   if (mInUse) {
      67               0 :     NS_WARNING("Clip loop detected!");
      68               0 :     return NS_OK;
      69                 :   }
      70               0 :   AutoClipPathReferencer clipRef(this);
      71                 : 
      72               0 :   mClipParent = aParent;
      73               0 :   if (mClipParentMatrix) {
      74               0 :     *mClipParentMatrix = aMatrix;
      75                 :   } else {
      76               0 :     mClipParentMatrix = new gfxMatrix(aMatrix);
      77                 :   }
      78                 : 
      79               0 :   bool isTrivial = IsTrivial();
      80                 : 
      81                 :   SVGAutoRenderState mode(aContext,
      82                 :                           isTrivial ? SVGAutoRenderState::CLIP
      83               0 :                                     : SVGAutoRenderState::CLIP_MASK);
      84                 : 
      85               0 :   gfxContext *gfx = aContext->ThebesContext();
      86                 : 
      87                 :   nsSVGClipPathFrame *clipPathFrame =
      88               0 :     nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nsnull);
      89                 :   bool referencedClipIsTrivial;
      90               0 :   if (clipPathFrame) {
      91               0 :     referencedClipIsTrivial = clipPathFrame->IsTrivial();
      92               0 :     gfx->Save();
      93               0 :     if (referencedClipIsTrivial) {
      94               0 :       clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
      95                 :     } else {
      96               0 :       gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
      97                 :     }
      98                 :   }
      99                 : 
     100               0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     101                 :        kid = kid->GetNextSibling()) {
     102               0 :     nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
     103               0 :     if (SVGFrame) {
     104                 :       // The CTM of each frame referencing us can be different.
     105                 :       SVGFrame->NotifySVGChanged(
     106                 :                           nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS | 
     107               0 :                           nsISVGChildFrame::TRANSFORM_CHANGED);
     108                 : 
     109               0 :       bool isOK = true;
     110                 :       nsSVGClipPathFrame *clipPathFrame =
     111               0 :         nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame(&isOK);
     112               0 :       if (!isOK) {
     113               0 :         continue;
     114                 :       }
     115                 : 
     116                 :       bool isTrivial;
     117                 : 
     118               0 :       if (clipPathFrame) {
     119               0 :         isTrivial = clipPathFrame->IsTrivial();
     120               0 :         gfx->Save();
     121               0 :         if (isTrivial) {
     122               0 :           clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
     123                 :         } else {
     124               0 :           gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
     125                 :         }
     126                 :       }
     127                 : 
     128               0 :       SVGFrame->PaintSVG(aContext, nsnull);
     129                 : 
     130               0 :       if (clipPathFrame) {
     131               0 :         if (!isTrivial) {
     132               0 :           gfx->PopGroupToSource();
     133                 : 
     134               0 :           nsRefPtr<gfxPattern> clipMaskSurface;
     135               0 :           gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
     136                 : 
     137               0 :           clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
     138               0 :           clipMaskSurface = gfx->PopGroup();
     139                 : 
     140               0 :           if (clipMaskSurface) {
     141               0 :             gfx->Mask(clipMaskSurface);
     142                 :           }
     143                 :         }
     144               0 :         gfx->Restore();
     145                 :       }
     146                 :     }
     147                 :   }
     148                 : 
     149               0 :   if (clipPathFrame) {
     150               0 :     if (!referencedClipIsTrivial) {
     151               0 :       gfx->PopGroupToSource();
     152                 : 
     153               0 :       nsRefPtr<gfxPattern> clipMaskSurface;
     154               0 :       gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
     155                 : 
     156               0 :       clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
     157               0 :       clipMaskSurface = gfx->PopGroup();
     158                 : 
     159               0 :       if (clipMaskSurface) {
     160               0 :         gfx->Mask(clipMaskSurface);
     161                 :       }
     162                 :     }
     163               0 :     gfx->Restore();
     164                 :   }
     165                 : 
     166               0 :   if (isTrivial) {
     167               0 :     gfx->Clip();
     168               0 :     gfx->NewPath();
     169                 :   }
     170                 : 
     171               0 :   return NS_OK;
     172                 : }
     173                 : 
     174                 : bool
     175               0 : nsSVGClipPathFrame::ClipHitTest(nsIFrame* aParent,
     176                 :                                 const gfxMatrix &aMatrix,
     177                 :                                 const nsPoint &aPoint)
     178                 : {
     179                 :   // If the flag is set when we get here, it means this clipPath frame
     180                 :   // has already been used in hit testing against the current clip,
     181                 :   // and the document has a clip reference loop.
     182               0 :   if (mInUse) {
     183               0 :     NS_WARNING("Clip loop detected!");
     184               0 :     return false;
     185                 :   }
     186               0 :   AutoClipPathReferencer clipRef(this);
     187                 : 
     188               0 :   mClipParent = aParent;
     189               0 :   if (mClipParentMatrix) {
     190               0 :     *mClipParentMatrix = aMatrix;
     191                 :   } else {
     192               0 :     mClipParentMatrix = new gfxMatrix(aMatrix);
     193                 :   }
     194                 : 
     195                 :   nsSVGClipPathFrame *clipPathFrame =
     196               0 :     nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nsnull);
     197               0 :   if (clipPathFrame && !clipPathFrame->ClipHitTest(aParent, aMatrix, aPoint))
     198               0 :     return false;
     199                 : 
     200               0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     201                 :        kid = kid->GetNextSibling()) {
     202               0 :     nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
     203               0 :     if (SVGFrame) {
     204                 :       // Notify the child frame that we may be working with a
     205                 :       // different transform, so it can update its covered region
     206                 :       // (used to shortcut hit testing).
     207               0 :       SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
     208                 : 
     209               0 :       if (SVGFrame->GetFrameForPoint(aPoint))
     210               0 :         return true;
     211                 :     }
     212                 :   }
     213               0 :   return false;
     214                 : }
     215                 : 
     216                 : bool
     217               0 : nsSVGClipPathFrame::IsTrivial()
     218                 : {
     219                 :   // If the clip path is clipped then it's non-trivial
     220               0 :   if (nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nsnull))
     221               0 :     return false;
     222                 : 
     223               0 :   bool foundChild = false;
     224                 : 
     225               0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     226                 :        kid = kid->GetNextSibling()) {
     227               0 :     nsISVGChildFrame *svgChild = do_QueryFrame(kid);
     228               0 :     if (svgChild) {
     229                 :       // We consider a non-trivial clipPath to be one containing
     230                 :       // either more than one svg child and/or a svg container
     231               0 :       if (foundChild || svgChild->IsDisplayContainer())
     232               0 :         return false;
     233                 : 
     234                 :       // or where the child is itself clipped
     235               0 :       if (nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame(nsnull))
     236               0 :         return false;
     237                 : 
     238               0 :       foundChild = true;
     239                 :     }
     240                 :   }
     241               0 :   return true;
     242                 : }
     243                 : 
     244                 : bool
     245               0 : nsSVGClipPathFrame::IsValid()
     246                 : {
     247               0 :   if (mInUse) {
     248               0 :     NS_WARNING("Clip loop detected!");
     249               0 :     return false;
     250                 :   }
     251               0 :   AutoClipPathReferencer clipRef(this);
     252                 : 
     253               0 :   bool isOK = true;
     254               0 :   nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(&isOK);
     255               0 :   if (!isOK) {
     256               0 :     return false;
     257                 :   }
     258                 : 
     259               0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     260                 :        kid = kid->GetNextSibling()) {
     261                 : 
     262               0 :     nsIAtom *type = kid->GetType();
     263                 : 
     264               0 :     if (type == nsGkAtoms::svgUseFrame) {
     265               0 :       for (nsIFrame* grandKid = kid->GetFirstPrincipalChild(); grandKid;
     266                 :            grandKid = grandKid->GetNextSibling()) {
     267                 : 
     268               0 :         nsIAtom *type = grandKid->GetType();
     269                 : 
     270               0 :         if (type != nsGkAtoms::svgPathGeometryFrame &&
     271                 :             type != nsGkAtoms::svgTextFrame) {
     272               0 :           return false;
     273                 :         }
     274                 :       }
     275               0 :       continue;
     276                 :     }
     277               0 :     if (type != nsGkAtoms::svgPathGeometryFrame &&
     278                 :         type != nsGkAtoms::svgTextFrame) {
     279               0 :       return false;
     280                 :     }
     281                 :   }
     282               0 :   return true;
     283                 : }
     284                 : 
     285                 : NS_IMETHODIMP
     286               0 : nsSVGClipPathFrame::AttributeChanged(PRInt32         aNameSpaceID,
     287                 :                                      nsIAtom*        aAttribute,
     288                 :                                      PRInt32         aModType)
     289                 : {
     290               0 :   if (aNameSpaceID == kNameSpaceID_None) {
     291               0 :     if (aAttribute == nsGkAtoms::transform) {
     292                 :       nsSVGUtils::NotifyChildrenOfSVGChange(this,
     293               0 :                                             nsISVGChildFrame::TRANSFORM_CHANGED);
     294                 :     }
     295               0 :     if (aAttribute == nsGkAtoms::clipPathUnits) {
     296               0 :       nsSVGEffects::InvalidateRenderingObservers(this);
     297                 :     }
     298                 :   }
     299                 : 
     300                 :   return nsSVGClipPathFrameBase::AttributeChanged(aNameSpaceID,
     301               0 :                                                   aAttribute, aModType);
     302                 : }
     303                 : 
     304                 : NS_IMETHODIMP
     305               0 : nsSVGClipPathFrame::Init(nsIContent* aContent,
     306                 :                          nsIFrame* aParent,
     307                 :                          nsIFrame* aPrevInFlow)
     308                 : {
     309                 : #ifdef DEBUG
     310               0 :   nsCOMPtr<nsIDOMSVGClipPathElement> clipPath = do_QueryInterface(aContent);
     311               0 :   NS_ASSERTION(clipPath, "Content is not an SVG clipPath!");
     312                 : #endif
     313                 : 
     314               0 :   AddStateBits(NS_STATE_SVG_CLIPPATH_CHILD);
     315               0 :   return nsSVGClipPathFrameBase::Init(aContent, aParent, aPrevInFlow);
     316                 : }
     317                 : 
     318                 : nsIAtom *
     319               0 : nsSVGClipPathFrame::GetType() const
     320                 : {
     321               0 :   return nsGkAtoms::svgClipPathFrame;
     322                 : }
     323                 : 
     324                 : gfxMatrix
     325               0 : nsSVGClipPathFrame::GetCanvasTM()
     326                 : {
     327               0 :   nsSVGClipPathElement *content = static_cast<nsSVGClipPathElement*>(mContent);
     328                 : 
     329                 :   gfxMatrix tm =
     330                 :     content->PrependLocalTransformsTo(mClipParentMatrix ?
     331               0 :                                       *mClipParentMatrix : gfxMatrix());
     332                 : 
     333                 :   return nsSVGUtils::AdjustMatrixForUnits(tm,
     334                 :                                           &content->mEnumAttributes[nsSVGClipPathElement::CLIPPATHUNITS],
     335               0 :                                           mClipParent);
     336                 : }

Generated by: LCOV version 1.7