LCOV - code coverage report
Current view: top level - dom/svg - SVGTransformableElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 19 114 16.7 %
Date: 2017-07-14 16:53:18 Functions: 5 15 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "gfx2DGlue.h"
       8             : #include "mozilla/dom/SVGAnimatedTransformList.h"
       9             : #include "mozilla/dom/SVGGraphicsElementBinding.h"
      10             : #include "mozilla/dom/SVGTransformableElement.h"
      11             : #include "mozilla/dom/SVGMatrix.h"
      12             : #include "mozilla/dom/SVGSVGElement.h"
      13             : #include "nsContentUtils.h"
      14             : #include "nsIDOMMutationEvent.h"
      15             : #include "nsIFrame.h"
      16             : #include "nsSVGDisplayableFrame.h"
      17             : #include "mozilla/dom/SVGRect.h"
      18             : #include "nsSVGUtils.h"
      19             : #include "SVGContentUtils.h"
      20             : 
      21             : using namespace mozilla::gfx;
      22             : 
      23             : namespace mozilla {
      24             : namespace dom {
      25             : 
      26             : already_AddRefed<SVGAnimatedTransformList>
      27           0 : SVGTransformableElement::Transform()
      28             : {
      29             :   // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
      30             :   // to allocate the SVGAnimatedTransformList if it hasn't already done so:
      31             :   return SVGAnimatedTransformList::GetDOMWrapper(
      32           0 :            GetAnimatedTransformList(DO_ALLOCATE), this);
      33             : 
      34             : }
      35             : 
      36             : //----------------------------------------------------------------------
      37             : // nsIContent methods
      38             : 
      39             : NS_IMETHODIMP_(bool)
      40         987 : SVGTransformableElement::IsAttributeMapped(const nsIAtom* name) const
      41             : {
      42             :   static const MappedAttributeEntry* const map[] = {
      43             :     sColorMap,
      44             :     sFillStrokeMap,
      45             :     sGraphicsMap
      46             :   };
      47             : 
      48        1811 :   return FindAttributeDependence(name, map) ||
      49        1811 :     nsSVGElement::IsAttributeMapped(name);
      50             : }
      51             : 
      52             : nsChangeHint
      53           0 : SVGTransformableElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
      54             :                                                 int32_t aModType) const
      55             : {
      56             :   nsChangeHint retval =
      57           0 :     nsSVGElement::GetAttributeChangeHint(aAttribute, aModType);
      58           0 :   if (aAttribute == nsGkAtoms::transform ||
      59           0 :       aAttribute == nsGkAtoms::mozAnimateMotionDummyAttr) {
      60             :     nsIFrame* frame =
      61           0 :       const_cast<SVGTransformableElement*>(this)->GetPrimaryFrame();
      62           0 :     retval |= nsChangeHint_InvalidateRenderingObservers;
      63           0 :     if (!frame || (frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
      64           0 :       return retval;
      65             :     }
      66             : 
      67           0 :     bool isAdditionOrRemoval = false;
      68           0 :     if (aModType == nsIDOMMutationEvent::ADDITION ||
      69             :         aModType == nsIDOMMutationEvent::REMOVAL) {
      70           0 :       isAdditionOrRemoval = true;
      71             :     } else {
      72           0 :       MOZ_ASSERT(aModType == nsIDOMMutationEvent::MODIFICATION,
      73             :                  "Unknown modification type.");
      74           0 :       if (!mTransforms ||
      75           0 :           !mTransforms->HasTransform() ||
      76           0 :           !mTransforms->HadTransformBeforeLastBaseValChange()) {
      77             :         // New or old value is empty; this is effectively addition or removal.
      78           0 :         isAdditionOrRemoval = true;
      79             :       }
      80             :     }
      81             : 
      82           0 :     if (isAdditionOrRemoval) {
      83             :       // Reconstruct the frame tree to handle stacking context changes:
      84           0 :       retval |= nsChangeHint_ReconstructFrame;
      85             :     } else {
      86             :       // We just assume the old and new transforms are different.
      87             :       retval |= nsChangeHint_UpdatePostTransformOverflow |
      88           0 :                 nsChangeHint_UpdateTransformLayer;
      89             :     }
      90             :   }
      91           0 :   return retval;
      92             : }
      93             : 
      94             : bool
      95           0 : SVGTransformableElement::IsEventAttributeNameInternal(nsIAtom* aName)
      96             : {
      97           0 :   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
      98             : }
      99             : 
     100             : //----------------------------------------------------------------------
     101             : // nsSVGElement overrides
     102             : 
     103             : gfxMatrix
     104          38 : SVGTransformableElement::PrependLocalTransformsTo(const gfxMatrix& aMatrix,
     105             :                                                   SVGTransformTypes aWhich) const
     106             : {
     107          38 :   if (aWhich == eChildToUserSpace) {
     108             :     // We don't have any eUserSpaceToParent transforms. (Sub-classes that do
     109             :     // must override this function and handle that themselves.)
     110           4 :     return aMatrix;
     111             :   }
     112          34 :   return GetUserToParentTransform(mAnimateMotionTransform, mTransforms) * aMatrix;
     113             : }
     114             : 
     115             : const gfx::Matrix*
     116         387 : SVGTransformableElement::GetAnimateMotionTransform() const
     117             : {
     118         387 :   return mAnimateMotionTransform.get();
     119             : }
     120             : 
     121             : void
     122           0 : SVGTransformableElement::SetAnimateMotionTransform(const gfx::Matrix* aMatrix)
     123             : {
     124           0 :   if ((!aMatrix && !mAnimateMotionTransform) ||
     125           0 :       (aMatrix && mAnimateMotionTransform && *aMatrix == *mAnimateMotionTransform)) {
     126           0 :     return;
     127             :   }
     128           0 :   bool transformSet = mTransforms && mTransforms->IsExplicitlySet();
     129           0 :   bool prevSet = mAnimateMotionTransform || transformSet;
     130           0 :   mAnimateMotionTransform = aMatrix ? new gfx::Matrix(*aMatrix) : nullptr;
     131           0 :   bool nowSet = mAnimateMotionTransform || transformSet;
     132             :   int32_t modType;
     133           0 :   if (prevSet && !nowSet) {
     134           0 :     modType = nsIDOMMutationEvent::REMOVAL;
     135           0 :   } else if(!prevSet && nowSet) {
     136           0 :     modType = nsIDOMMutationEvent::ADDITION;
     137             :   } else {
     138           0 :     modType = nsIDOMMutationEvent::MODIFICATION;
     139             :   }
     140           0 :   DidAnimateTransformList(modType);
     141           0 :   nsIFrame* frame = GetPrimaryFrame();
     142           0 :   if (frame) {
     143             :     // If the result of this transform and any other transforms on this frame
     144             :     // is the identity matrix, then DoApplyRenderingChangeToTree won't handle
     145             :     // our nsChangeHint_UpdateTransformLayer hint since aFrame->IsTransformed()
     146             :     // will return false. That's fine, but we still need to schedule a repaint,
     147             :     // and that won't otherwise happen. Since it's cheap to call SchedulePaint,
     148             :     // we don't bother to check IsTransformed().
     149           0 :     frame->SchedulePaint();
     150             :   }
     151             : }
     152             : 
     153             : nsSVGAnimatedTransformList*
     154         724 : SVGTransformableElement::GetAnimatedTransformList(uint32_t aFlags)
     155             : {
     156         724 :   if (!mTransforms && (aFlags & DO_ALLOCATE)) {
     157           7 :     mTransforms = new nsSVGAnimatedTransformList();
     158             :   }
     159         724 :   return mTransforms;
     160             : }
     161             : 
     162             : nsSVGElement*
     163           0 : SVGTransformableElement::GetNearestViewportElement()
     164             : {
     165           0 :   return SVGContentUtils::GetNearestViewportElement(this);
     166             : }
     167             : 
     168             : nsSVGElement*
     169           0 : SVGTransformableElement::GetFarthestViewportElement()
     170             : {
     171           0 :   return SVGContentUtils::GetOuterSVGElement(this);
     172             : }
     173             : 
     174             : already_AddRefed<SVGIRect>
     175           0 : SVGTransformableElement::GetBBox(const SVGBoundingBoxOptions& aOptions,
     176             :                                  ErrorResult& rv)
     177             : {
     178           0 :   nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
     179             : 
     180           0 :   if (!frame || (frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
     181           0 :     rv.Throw(NS_ERROR_FAILURE);
     182           0 :     return nullptr;
     183             :   }
     184           0 :   nsSVGDisplayableFrame* svgframe = do_QueryFrame(frame);
     185           0 :   if (!svgframe) {
     186           0 :     rv.Throw(NS_ERROR_NOT_IMPLEMENTED); // XXX: outer svg
     187           0 :     return nullptr;
     188             :   }
     189             : 
     190           0 :   if (!NS_SVGNewGetBBoxEnabled()) {
     191           0 :     return NS_NewSVGRect(this, ToRect(nsSVGUtils::GetBBox(frame)));
     192             :   } else {
     193           0 :     uint32_t flags = 0;
     194           0 :     if (aOptions.mFill) {
     195           0 :       flags |= nsSVGUtils::eBBoxIncludeFill;
     196             :     }
     197           0 :     if (aOptions.mStroke) {
     198           0 :       flags |= nsSVGUtils::eBBoxIncludeStroke;
     199             :     }
     200           0 :     if (aOptions.mMarkers) {
     201           0 :       flags |= nsSVGUtils::eBBoxIncludeMarkers;
     202             :     }
     203           0 :     if (aOptions.mClipped) {
     204           0 :       flags |= nsSVGUtils::eBBoxIncludeClipped;
     205             :     }
     206           0 :     if (flags == 0) {
     207           0 :       return NS_NewSVGRect(this,0,0,0,0);
     208             :     }
     209           0 :     if (flags == nsSVGUtils::eBBoxIncludeMarkers ||
     210             :         flags == nsSVGUtils::eBBoxIncludeClipped) {
     211           0 :       flags |= nsSVGUtils::eBBoxIncludeFill;
     212             :     }
     213           0 :     return NS_NewSVGRect(this, ToRect(nsSVGUtils::GetBBox(frame, flags)));
     214             :   }
     215             : }
     216             : 
     217             : already_AddRefed<SVGMatrix>
     218           0 : SVGTransformableElement::GetCTM()
     219             : {
     220           0 :   nsIDocument* currentDoc = GetComposedDoc();
     221           0 :   if (currentDoc) {
     222             :     // Flush all pending notifications so that our frames are up to date
     223           0 :     currentDoc->FlushPendingNotifications(FlushType::Layout);
     224             :   }
     225           0 :   gfx::Matrix m = SVGContentUtils::GetCTM(this, false);
     226           0 :   RefPtr<SVGMatrix> mat = m.IsSingular() ? nullptr : new SVGMatrix(ThebesMatrix(m));
     227           0 :   return mat.forget();
     228             : }
     229             : 
     230             : already_AddRefed<SVGMatrix>
     231           0 : SVGTransformableElement::GetScreenCTM()
     232             : {
     233           0 :   nsIDocument* currentDoc = GetComposedDoc();
     234           0 :   if (currentDoc) {
     235             :     // Flush all pending notifications so that our frames are up to date
     236           0 :     currentDoc->FlushPendingNotifications(FlushType::Layout);
     237             :   }
     238           0 :   gfx::Matrix m = SVGContentUtils::GetCTM(this, true);
     239           0 :   RefPtr<SVGMatrix> mat = m.IsSingular() ? nullptr : new SVGMatrix(ThebesMatrix(m));
     240           0 :   return mat.forget();
     241             : }
     242             : 
     243             : already_AddRefed<SVGMatrix>
     244           0 : SVGTransformableElement::GetTransformToElement(SVGGraphicsElement& aElement,
     245             :                                                ErrorResult& rv)
     246             : {
     247             :   // the easiest way to do this (if likely to increase rounding error):
     248           0 :   RefPtr<SVGMatrix> ourScreenCTM = GetScreenCTM();
     249           0 :   RefPtr<SVGMatrix> targetScreenCTM = aElement.GetScreenCTM();
     250           0 :   if (!ourScreenCTM || !targetScreenCTM) {
     251           0 :     rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     252           0 :     return nullptr;
     253             :   }
     254           0 :   RefPtr<SVGMatrix> tmp = targetScreenCTM->Inverse(rv);
     255           0 :   if (rv.Failed()) return nullptr;
     256             : 
     257           0 :   RefPtr<SVGMatrix> mat = tmp->Multiply(*ourScreenCTM);
     258           0 :   return mat.forget();
     259             : }
     260             : 
     261             : /* static */ gfxMatrix
     262          46 : SVGTransformableElement::GetUserToParentTransform(
     263             :                            const gfx::Matrix* aAnimateMotionTransform,
     264             :                            const nsSVGAnimatedTransformList* aTransforms)
     265             : {
     266          46 :   gfxMatrix result;
     267             : 
     268          46 :   if (aAnimateMotionTransform) {
     269           0 :     result.PreMultiply(ThebesMatrix(*aAnimateMotionTransform));
     270             :   }
     271             : 
     272          46 :   if (aTransforms) {
     273          42 :     result.PreMultiply(aTransforms->GetAnimValue().GetConsolidationMatrix());
     274             :   }
     275             : 
     276          46 :   return result;
     277             : }
     278             : 
     279             : } // namespace dom
     280             : } // namespace mozilla
     281             : 

Generated by: LCOV version 1.13