LCOV - code coverage report
Current view: top level - dom/svg - SVGSVGElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 106 326 32.5 %
Date: 2017-07-14 16:53:18 Functions: 21 77 27.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 "mozilla/ContentEvents.h"
       8             : #include "mozilla/dom/SVGSVGElement.h"
       9             : #include "mozilla/dom/SVGSVGElementBinding.h"
      10             : #include "mozilla/dom/SVGMatrix.h"
      11             : #include "mozilla/dom/SVGViewElement.h"
      12             : #include "mozilla/EventDispatcher.h"
      13             : 
      14             : #include "DOMSVGLength.h"
      15             : #include "DOMSVGNumber.h"
      16             : #include "DOMSVGPoint.h"
      17             : #include "nsLayoutStylesheetCache.h"
      18             : #include "nsSVGAngle.h"
      19             : #include "nsFrameSelection.h"
      20             : #include "nsIFrame.h"
      21             : #include "nsISVGSVGFrame.h"
      22             : #include "nsSMILAnimationController.h"
      23             : #include "nsSMILTimeContainer.h"
      24             : #include "nsSVGDisplayableFrame.h"
      25             : #include "nsSVGUtils.h"
      26             : #include "SVGAngle.h"
      27             : 
      28          44 : NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT_CHECK_PARSER(SVG)
      29             : 
      30             : using namespace mozilla::gfx;
      31             : 
      32             : namespace mozilla {
      33             : namespace dom {
      34             : 
      35             : nsSVGEnumMapping SVGSVGElement::sZoomAndPanMap[] = {
      36             :   {&nsGkAtoms::disable, SVG_ZOOMANDPAN_DISABLE},
      37             :   {&nsGkAtoms::magnify, SVG_ZOOMANDPAN_MAGNIFY},
      38             :   {nullptr, 0}
      39             : };
      40             : 
      41             : nsSVGElement::EnumInfo SVGSVGElement::sEnumInfo[1] =
      42             : {
      43             :   { &nsGkAtoms::zoomAndPan,
      44             :     sZoomAndPanMap,
      45             :     SVG_ZOOMANDPAN_MAGNIFY
      46             :   }
      47             : };
      48             : 
      49           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMSVGTranslatePoint, nsISVGPoint,
      50             :                                    mElement)
      51             : 
      52           0 : NS_IMPL_ADDREF_INHERITED(DOMSVGTranslatePoint, nsISVGPoint)
      53           0 : NS_IMPL_RELEASE_INHERITED(DOMSVGTranslatePoint, nsISVGPoint)
      54             : 
      55           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGTranslatePoint)
      56           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      57             :   // We have to qualify nsISVGPoint because NS_GET_IID looks for a class in the
      58             :   // global namespace
      59           0 :   NS_INTERFACE_MAP_ENTRY(mozilla::nsISVGPoint)
      60           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      61           0 : NS_INTERFACE_MAP_END
      62             : 
      63             : DOMSVGPoint*
      64           0 : DOMSVGTranslatePoint::Copy()
      65             : {
      66           0 :   return new DOMSVGPoint(mPt.GetX(), mPt.GetY());
      67             : }
      68             : 
      69             : nsISupports*
      70           0 : DOMSVGTranslatePoint::GetParentObject()
      71             : {
      72           0 :   return static_cast<nsIDOMSVGElement*>(mElement);
      73             : }
      74             : 
      75             : void
      76           0 : DOMSVGTranslatePoint::SetX(float aValue, ErrorResult& rv)
      77             : {
      78           0 :   mElement->SetCurrentTranslate(aValue, mPt.GetY());
      79           0 : }
      80             : 
      81             : void
      82           0 : DOMSVGTranslatePoint::SetY(float aValue, ErrorResult& rv)
      83             : {
      84           0 :   mElement->SetCurrentTranslate(mPt.GetX(), aValue);
      85           0 : }
      86             : 
      87             : already_AddRefed<nsISVGPoint>
      88           0 : DOMSVGTranslatePoint::MatrixTransform(SVGMatrix& matrix)
      89             : {
      90           0 :   float a = matrix.A(), b = matrix.B(), c = matrix.C();
      91           0 :   float d = matrix.D(), e = matrix.E(), f = matrix.F();
      92           0 :   float x = mPt.GetX();
      93           0 :   float y = mPt.GetY();
      94             : 
      95           0 :   nsCOMPtr<nsISVGPoint> point = new DOMSVGPoint(a*x + c*y + e, b*x + d*y + f);
      96           0 :   return point.forget();
      97             : }
      98             : 
      99             : JSObject*
     100           0 : SVGSVGElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
     101             : {
     102           0 :   return SVGSVGElementBinding::Wrap(aCx, this, aGivenProto);
     103             : }
     104             : 
     105             : //----------------------------------------------------------------------
     106             : // nsISupports methods
     107             : 
     108             : NS_IMPL_CYCLE_COLLECTION_CLASS(SVGSVGElement)
     109             : 
     110           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGSVGElement,
     111             :                                                 SVGSVGElementBase)
     112           0 :   if (tmp->mTimedDocumentRoot) {
     113           0 :     tmp->mTimedDocumentRoot->Unlink();
     114             :   }
     115           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     116           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGSVGElement,
     117             :                                                   SVGSVGElementBase)
     118           0 :   if (tmp->mTimedDocumentRoot) {
     119           0 :     tmp->mTimedDocumentRoot->Traverse(&cb);
     120             :   }
     121           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     122             : 
     123        1088 : NS_IMPL_ADDREF_INHERITED(SVGSVGElement,SVGSVGElementBase)
     124         813 : NS_IMPL_RELEASE_INHERITED(SVGSVGElement,SVGSVGElementBase)
     125             : 
     126         425 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGSVGElement)
     127         403 :   NS_INTERFACE_TABLE_INHERITED(SVGSVGElement, nsIDOMNode, nsIDOMElement,
     128             :                                nsIDOMSVGElement)
     129         403 : NS_INTERFACE_TABLE_TAIL_INHERITING(SVGSVGElementBase)
     130             : 
     131           0 : SVGView::SVGView()
     132             : {
     133           0 :   mZoomAndPan.Init(SVGSVGElement::ZOOMANDPAN,
     134           0 :                    SVG_ZOOMANDPAN_MAGNIFY);
     135           0 :   mViewBox.Init();
     136           0 :   mPreserveAspectRatio.Init();
     137           0 : }
     138             : 
     139             : //----------------------------------------------------------------------
     140             : // Implementation
     141             : 
     142          22 : SVGSVGElement::SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
     143          22 :                              FromParser aFromParser)
     144             :   : SVGSVGElementBase(aNodeInfo),
     145             :     mCurrentTranslate(0.0f, 0.0f),
     146             :     mCurrentScale(1.0f),
     147             :     mPreviousTranslate(0.0f, 0.0f),
     148             :     mPreviousScale(1.0f),
     149          21 :     mStartAnimationOnBindToTree(aFromParser == NOT_FROM_PARSER ||
     150          43 :                                 aFromParser == FROM_PARSER_FRAGMENT ||
     151             :                                 aFromParser == FROM_PARSER_XSLT),
     152          44 :     mImageNeedsTransformInvalidation(false)
     153             : {
     154          22 : }
     155             : 
     156           0 : SVGSVGElement::~SVGSVGElement()
     157             : {
     158           0 : }
     159             : 
     160             : //----------------------------------------------------------------------
     161             : // nsIDOMNode methods
     162             : 
     163           0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT_AND_PARSER(SVGSVGElement)
     164             : 
     165             : //----------------------------------------------------------------------
     166             : // nsIDOMSVGSVGElement methods:
     167             : 
     168             : already_AddRefed<SVGAnimatedLength>
     169           0 : SVGSVGElement::X()
     170             : {
     171           0 :   return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
     172             : }
     173             : 
     174             : already_AddRefed<SVGAnimatedLength>
     175           0 : SVGSVGElement::Y()
     176             : {
     177           0 :   return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
     178             : }
     179             : 
     180             : already_AddRefed<SVGAnimatedLength>
     181           0 : SVGSVGElement::Width()
     182             : {
     183           0 :   return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
     184             : }
     185             : 
     186             : already_AddRefed<SVGAnimatedLength>
     187           0 : SVGSVGElement::Height()
     188             : {
     189           0 :   return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
     190             : }
     191             : float
     192           0 : SVGSVGElement::PixelUnitToMillimeterX()
     193             : {
     194           0 :   return MM_PER_INCH_FLOAT / 96;
     195             : }
     196             : 
     197             : float
     198           0 : SVGSVGElement::PixelUnitToMillimeterY()
     199             : {
     200           0 :   return PixelUnitToMillimeterX();
     201             : }
     202             : 
     203             : float
     204           0 : SVGSVGElement::ScreenPixelToMillimeterX()
     205             : {
     206           0 :   return MM_PER_INCH_FLOAT / 96;
     207             : }
     208             : 
     209             : float
     210           0 : SVGSVGElement::ScreenPixelToMillimeterY()
     211             : {
     212           0 :   return ScreenPixelToMillimeterX();
     213             : }
     214             : bool
     215           2 : SVGSVGElement::UseCurrentView()
     216             : {
     217           2 :   return mSVGView || mCurrentViewID;
     218             : }
     219             : 
     220             : float
     221           0 : SVGSVGElement::CurrentScale()
     222             : {
     223           0 :   return mCurrentScale;
     224             : }
     225             : 
     226             : #define CURRENT_SCALE_MAX 16.0f
     227             : #define CURRENT_SCALE_MIN 0.0625f
     228             : 
     229             : void
     230           0 : SVGSVGElement::SetCurrentScale(float aCurrentScale)
     231             : {
     232           0 :   SetCurrentScaleTranslate(aCurrentScale,
     233           0 :     mCurrentTranslate.GetX(), mCurrentTranslate.GetY());
     234           0 : }
     235             : 
     236             : already_AddRefed<nsISVGPoint>
     237           0 : SVGSVGElement::CurrentTranslate()
     238             : {
     239           0 :   nsCOMPtr<nsISVGPoint> point = new DOMSVGTranslatePoint(&mCurrentTranslate, this);
     240           0 :   return point.forget();
     241             : }
     242             : 
     243             : uint32_t
     244           0 : SVGSVGElement::SuspendRedraw(uint32_t max_wait_milliseconds)
     245             : {
     246             :   // suspendRedraw is a no-op in Mozilla, so it doesn't matter what
     247             :   // we return
     248           0 :   return 1;
     249             : }
     250             : 
     251             : void
     252           0 : SVGSVGElement::UnsuspendRedraw(uint32_t suspend_handle_id)
     253             : {
     254             :   // no-op
     255           0 : }
     256             : 
     257             : void
     258           0 : SVGSVGElement::UnsuspendRedrawAll()
     259             : {
     260             :   // no-op
     261           0 : }
     262             : 
     263             : void
     264           0 : SVGSVGElement::ForceRedraw()
     265             : {
     266             :   // no-op
     267           0 : }
     268             : 
     269             : void
     270           0 : SVGSVGElement::PauseAnimations()
     271             : {
     272           0 :   if (mTimedDocumentRoot) {
     273           0 :     mTimedDocumentRoot->Pause(nsSMILTimeContainer::PAUSE_SCRIPT);
     274             :   }
     275             :   // else we're not the outermost <svg> or not bound to a tree, so silently fail
     276           0 : }
     277             : 
     278             : void
     279           0 : SVGSVGElement::UnpauseAnimations()
     280             : {
     281           0 :   if (mTimedDocumentRoot) {
     282           0 :     mTimedDocumentRoot->Resume(nsSMILTimeContainer::PAUSE_SCRIPT);
     283             :   }
     284             :   // else we're not the outermost <svg> or not bound to a tree, so silently fail
     285           0 : }
     286             : 
     287             : bool
     288           0 : SVGSVGElement::AnimationsPaused()
     289             : {
     290           0 :   nsSMILTimeContainer* root = GetTimedDocumentRoot();
     291           0 :   return root && root->IsPausedByType(nsSMILTimeContainer::PAUSE_SCRIPT);
     292             : }
     293             : 
     294             : float
     295          91 : SVGSVGElement::GetCurrentTime()
     296             : {
     297          91 :   nsSMILTimeContainer* root = GetTimedDocumentRoot();
     298          91 :   if (root) {
     299          91 :     double fCurrentTimeMs = double(root->GetCurrentTime());
     300          91 :     return (float)(fCurrentTimeMs / PR_MSEC_PER_SEC);
     301             :   } else {
     302           0 :     return 0.f;
     303             :   }
     304             : }
     305             : 
     306             : void
     307          36 : SVGSVGElement::SetCurrentTime(float seconds)
     308             : {
     309          36 :   if (mTimedDocumentRoot) {
     310             :     // Make sure the timegraph is up-to-date
     311          36 :     FlushAnimations();
     312          36 :     double fMilliseconds = double(seconds) * PR_MSEC_PER_SEC;
     313             :     // Round to nearest whole number before converting, to avoid precision
     314             :     // errors
     315          36 :     nsSMILTime lMilliseconds = int64_t(NS_round(fMilliseconds));
     316          36 :     mTimedDocumentRoot->SetCurrentTime(lMilliseconds);
     317          36 :     AnimationNeedsResample();
     318             :     // Trigger synchronous sample now, to:
     319             :     //  - Make sure we get an up-to-date paint after this method
     320             :     //  - re-enable event firing (it got disabled during seeking, and it
     321             :     //  doesn't get re-enabled until the first sample after the seek -- so
     322             :     //  let's make that happen now.)
     323          36 :     FlushAnimations();
     324             :   }
     325             :   // else we're not the outermost <svg> or not bound to a tree, so silently fail
     326          36 : }
     327             : 
     328             : void
     329           0 : SVGSVGElement::DeselectAll()
     330             : {
     331           0 :   nsIFrame* frame = GetPrimaryFrame();
     332           0 :   if (frame) {
     333           0 :     RefPtr<nsFrameSelection> frameSelection = frame->GetFrameSelection();
     334           0 :     frameSelection->ClearNormalSelection();
     335             :   }
     336           0 : }
     337             : 
     338             : already_AddRefed<DOMSVGNumber>
     339           0 : SVGSVGElement::CreateSVGNumber()
     340             : {
     341           0 :   RefPtr<DOMSVGNumber> number = new DOMSVGNumber(ToSupports(this));
     342           0 :   return number.forget();
     343             : }
     344             : 
     345             : already_AddRefed<DOMSVGLength>
     346           0 : SVGSVGElement::CreateSVGLength()
     347             : {
     348           0 :   nsCOMPtr<DOMSVGLength> length = new DOMSVGLength();
     349           0 :   return length.forget();
     350             : }
     351             : 
     352             : already_AddRefed<SVGAngle>
     353           0 : SVGSVGElement::CreateSVGAngle()
     354             : {
     355           0 :   nsSVGAngle* angle = new nsSVGAngle();
     356           0 :   angle->Init();
     357           0 :   RefPtr<SVGAngle> svgangle = new SVGAngle(angle, this, SVGAngle::CreatedValue);
     358           0 :   return svgangle.forget();
     359             : }
     360             : 
     361             : already_AddRefed<nsISVGPoint>
     362           0 : SVGSVGElement::CreateSVGPoint()
     363             : {
     364           0 :   nsCOMPtr<nsISVGPoint> point = new DOMSVGPoint(0, 0);
     365           0 :   return point.forget();
     366             : }
     367             : 
     368             : already_AddRefed<SVGMatrix>
     369           0 : SVGSVGElement::CreateSVGMatrix()
     370             : {
     371           0 :   RefPtr<SVGMatrix> matrix = new SVGMatrix();
     372           0 :   return matrix.forget();
     373             : }
     374             : 
     375             : already_AddRefed<SVGIRect>
     376           0 : SVGSVGElement::CreateSVGRect()
     377             : {
     378           0 :   return NS_NewSVGRect(this);
     379             : }
     380             : 
     381             : already_AddRefed<SVGTransform>
     382           0 : SVGSVGElement::CreateSVGTransform()
     383             : {
     384           0 :   RefPtr<SVGTransform> transform = new SVGTransform();
     385           0 :   return transform.forget();
     386             : }
     387             : 
     388             : already_AddRefed<SVGTransform>
     389           0 : SVGSVGElement::CreateSVGTransformFromMatrix(SVGMatrix& matrix)
     390             : {
     391           0 :   RefPtr<SVGTransform> transform = new SVGTransform(matrix.GetMatrix());
     392           0 :   return transform.forget();
     393             : }
     394             : 
     395             : //----------------------------------------------------------------------
     396             : // helper method for implementing SetCurrentScale/Translate
     397             : 
     398             : void
     399           0 : SVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y)
     400             : {
     401           0 :   if (s == mCurrentScale &&
     402           0 :       x == mCurrentTranslate.GetX() && y == mCurrentTranslate.GetY()) {
     403           0 :     return;
     404             :   }
     405             : 
     406             :   // Prevent bizarre behaviour and maxing out of CPU and memory by clamping
     407           0 :   if (s < CURRENT_SCALE_MIN)
     408           0 :     s = CURRENT_SCALE_MIN;
     409           0 :   else if (s > CURRENT_SCALE_MAX)
     410           0 :     s = CURRENT_SCALE_MAX;
     411             : 
     412             :   // IMPORTANT: If either mCurrentTranslate *or* mCurrentScale is changed then
     413             :   // mPreviousTranslate_x, mPreviousTranslate_y *and* mPreviousScale must all
     414             :   // be updated otherwise SVGZoomEvents will end up with invalid data. I.e. an
     415             :   // SVGZoomEvent's properties previousScale and previousTranslate must contain
     416             :   // the state of currentScale and currentTranslate immediately before the
     417             :   // change that caused the event's dispatch, which is *not* necessarily the
     418             :   // same thing as the values of currentScale and currentTranslate prior to
     419             :   // their own last change.
     420             :   //
     421             :   // XXX This comment is out-of-date due to removal of SVGZoomEvent.  Can we
     422             :   // remove some of this code?
     423           0 :   mPreviousScale = mCurrentScale;
     424           0 :   mPreviousTranslate = mCurrentTranslate;
     425             : 
     426           0 :   mCurrentScale = s;
     427           0 :   mCurrentTranslate = SVGPoint(x, y);
     428             : 
     429             :   // now dispatch the appropriate event if we are the root element
     430           0 :   nsIDocument* doc = GetUncomposedDoc();
     431           0 :   if (doc) {
     432           0 :     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
     433           0 :     if (presShell && IsRoot()) {
     434           0 :       nsEventStatus status = nsEventStatus_eIgnore;
     435           0 :       if (mPreviousScale == mCurrentScale) {
     436           0 :         WidgetEvent svgScrollEvent(true, eSVGScroll);
     437           0 :         presShell->HandleDOMEventWithTarget(this, &svgScrollEvent, &status);
     438             :       }
     439           0 :       InvalidateTransformNotifyFrame();
     440             :     }
     441             :   }
     442             : }
     443             : 
     444             : void
     445           0 : SVGSVGElement::SetCurrentTranslate(float x, float y)
     446             : {
     447           0 :   SetCurrentScaleTranslate(mCurrentScale, x, y);
     448           0 : }
     449             : 
     450             : //----------------------------------------------------------------------
     451             : // SVGZoomAndPanValues
     452             : uint16_t
     453           0 : SVGSVGElement::ZoomAndPan()
     454             : {
     455           0 :   return mEnumAttributes[ZOOMANDPAN].GetAnimValue();
     456             : }
     457             : 
     458             : void
     459           0 : SVGSVGElement::SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv)
     460             : {
     461           0 :   if (aZoomAndPan == SVG_ZOOMANDPAN_DISABLE ||
     462             :       aZoomAndPan == SVG_ZOOMANDPAN_MAGNIFY) {
     463           0 :     mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this);
     464           0 :     return;
     465             :   }
     466             : 
     467           0 :   rv.ThrowRangeError<MSG_INVALID_ZOOMANDPAN_VALUE_ERROR>();
     468             : }
     469             : 
     470             : //----------------------------------------------------------------------
     471             : nsSMILTimeContainer*
     472          91 : SVGSVGElement::GetTimedDocumentRoot()
     473             : {
     474          91 :   if (mTimedDocumentRoot) {
     475          91 :     return mTimedDocumentRoot;
     476             :   }
     477             : 
     478             :   // We must not be the outermost <svg> element, try to find it
     479             :   SVGSVGElement *outerSVGElement =
     480           0 :     SVGContentUtils::GetOuterSVGElement(this);
     481             : 
     482           0 :   if (outerSVGElement) {
     483           0 :     return outerSVGElement->GetTimedDocumentRoot();
     484             :   }
     485             :   // invalid structure
     486           0 :   return nullptr;
     487             : }
     488             : //----------------------------------------------------------------------
     489             : // nsSVGElement
     490             : nsresult
     491          22 : SVGSVGElement::BindToTree(nsIDocument* aDocument,
     492             :                           nsIContent* aParent,
     493             :                           nsIContent* aBindingParent,
     494             :                           bool aCompileEventHandlers)
     495             : {
     496          22 :   nsSMILAnimationController* smilController = nullptr;
     497             : 
     498          22 :   if (aDocument) {
     499          22 :     smilController = aDocument->GetAnimationController();
     500          22 :     if (smilController) {
     501             :       // SMIL is enabled in this document
     502          22 :       if (WillBeOutermostSVG(aParent, aBindingParent)) {
     503             :         // We'll be the outermost <svg> element.  We'll need a time container.
     504          22 :         if (!mTimedDocumentRoot) {
     505          22 :           mTimedDocumentRoot = new nsSMILTimeContainer();
     506             :         }
     507             :       } else {
     508             :         // We're a child of some other <svg> element, so we don't need our own
     509             :         // time container. However, we need to make sure that we'll get a
     510             :         // kick-start if we get promoted to be outermost later on.
     511           0 :         mTimedDocumentRoot = nullptr;
     512           0 :         mStartAnimationOnBindToTree = true;
     513             :       }
     514             :     }
     515             :   }
     516             : 
     517          22 :   nsresult rv = SVGGraphicsElement::BindToTree(aDocument, aParent,
     518             :                                               aBindingParent,
     519          22 :                                               aCompileEventHandlers);
     520          22 :   NS_ENSURE_SUCCESS(rv,rv);
     521             : 
     522          22 :   nsIDocument* doc = GetComposedDoc();
     523          22 :   if (doc) {
     524             :     // Setup the style sheet during binding, not element construction,
     525             :     // because we could move the root SVG element from the document
     526             :     // that created it to another document.
     527          22 :     auto cache = nsLayoutStylesheetCache::For(doc->GetStyleBackendType());
     528          22 :     doc->EnsureOnDemandBuiltInUASheet(cache->SVGSheet());
     529             :   }
     530             : 
     531          22 :   if (mTimedDocumentRoot && smilController) {
     532          22 :     rv = mTimedDocumentRoot->SetParent(smilController);
     533          22 :     if (mStartAnimationOnBindToTree) {
     534           1 :       mTimedDocumentRoot->Begin();
     535           1 :       mStartAnimationOnBindToTree = false;
     536             :     }
     537             :   }
     538             : 
     539          22 :   return rv;
     540             : }
     541             : 
     542             : void
     543           0 : SVGSVGElement::UnbindFromTree(bool aDeep, bool aNullParent)
     544             : {
     545           0 :   if (mTimedDocumentRoot) {
     546           0 :     mTimedDocumentRoot->SetParent(nullptr);
     547             :   }
     548             : 
     549           0 :   SVGGraphicsElement::UnbindFromTree(aDeep, aNullParent);
     550           0 : }
     551             : 
     552             : nsSVGAnimatedTransformList*
     553         132 : SVGSVGElement::GetAnimatedTransformList(uint32_t aFlags)
     554             : {
     555         132 :   if (!(aFlags & DO_ALLOCATE) && mSVGView && mSVGView->mTransforms) {
     556           0 :     return mSVGView->mTransforms;
     557             :   }
     558         132 :   return SVGGraphicsElement::GetAnimatedTransformList(aFlags);
     559             : }
     560             : 
     561             : nsresult
     562          26 : SVGSVGElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     563             : {
     564          26 :   if (aVisitor.mEvent->mMessage == eSVGLoad) {
     565          21 :     if (mTimedDocumentRoot) {
     566          21 :       mTimedDocumentRoot->Begin();
     567             :       // Set 'resample needed' flag, so that if any script calls a DOM method
     568             :       // that requires up-to-date animations before our first sample callback,
     569             :       // we'll force a synchronous sample.
     570          21 :       AnimationNeedsResample();
     571             :     }
     572             :   }
     573          26 :   return SVGSVGElementBase::GetEventTargetParent(aVisitor);
     574             : }
     575             : 
     576             : bool
     577           0 : SVGSVGElement::IsEventAttributeNameInternal(nsIAtom* aName)
     578             : {
     579             :   /* The events in EventNameType_SVGSVG are for events that are only
     580             :      applicable to outermost 'svg' elements. We don't check if we're an outer
     581             :      'svg' element in case we're not inserted into the document yet, but since
     582             :      the target of the events in question will always be the outermost 'svg'
     583             :      element, this shouldn't cause any real problems.
     584             :   */
     585             :   return nsContentUtils::IsEventAttributeName(aName,
     586           0 :          (EventNameType_SVGGraphic | EventNameType_SVGSVG));
     587             : }
     588             : 
     589             : //----------------------------------------------------------------------
     590             : // public helpers:
     591             : 
     592             : int32_t
     593         325 : SVGSVGElement::GetIntrinsicWidth()
     594             : {
     595         325 :   if (mLengthAttributes[ATTR_WIDTH].IsPercentage()) {
     596           0 :     return -1;
     597             :   }
     598             :   // Passing |this| as a SVGViewportElement* invokes the variant of GetAnimValue
     599             :   // that uses the passed argument as the context, but that's fine since we
     600             :   // know the length isn't a percentage so the context won't be used (and we
     601             :   // need to pass the element to be able to resolve em/ex units).
     602         325 :   float width = mLengthAttributes[ATTR_WIDTH].GetAnimValue(this);
     603         325 :   return nsSVGUtils::ClampToInt(width);
     604             : }
     605             : 
     606             : int32_t
     607         325 : SVGSVGElement::GetIntrinsicHeight()
     608             : {
     609         325 :   if (mLengthAttributes[ATTR_HEIGHT].IsPercentage()) {
     610           0 :     return -1;
     611             :   }
     612             :   // Passing |this| as a SVGViewportElement* invokes the variant of GetAnimValue
     613             :   // that uses the passed argument as the context, but that's fine since we
     614             :   // know the length isn't a percentage so the context won't be used (and we
     615             :   // need to pass the element to be able to resolve em/ex units).
     616         325 :   float height = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(this);
     617         325 :   return nsSVGUtils::ClampToInt(height);
     618             : }
     619             : 
     620             : void
     621          18 : SVGSVGElement::FlushImageTransformInvalidation()
     622             : {
     623          18 :   MOZ_ASSERT(!GetParent(), "Should only be called on root node");
     624          18 :   MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
     625             :              "Should only be called on image documents");
     626             : 
     627          18 :   if (mImageNeedsTransformInvalidation) {
     628           0 :     InvalidateTransformNotifyFrame();
     629           0 :     mImageNeedsTransformInvalidation = false;
     630             :   }
     631          18 : }
     632             : 
     633             : //----------------------------------------------------------------------
     634             : // implementation helpers
     635             : 
     636             : bool
     637          22 : SVGSVGElement::WillBeOutermostSVG(nsIContent* aParent,
     638             :                                   nsIContent* aBindingParent) const
     639             : {
     640          22 :   nsIContent* parent = aBindingParent ? aBindingParent : aParent;
     641             : 
     642          22 :   while (parent && parent->IsSVGElement()) {
     643           0 :     if (parent->IsSVGElement(nsGkAtoms::foreignObject)) {
     644             :       // SVG in a foreignObject must have its own <svg> (nsSVGOuterSVGFrame).
     645           0 :       return false;
     646             :     }
     647           0 :     if (parent->IsSVGElement(nsGkAtoms::svg)) {
     648           0 :       return false;
     649             :     }
     650           0 :     parent = parent->GetParent();
     651             :   }
     652             : 
     653          22 :   return true;
     654             : }
     655             : 
     656             : void
     657           0 : SVGSVGElement::InvalidateTransformNotifyFrame()
     658             : {
     659           0 :   nsISVGSVGFrame* svgframe = do_QueryFrame(GetPrimaryFrame());
     660             :   // might fail this check if we've failed conditional processing
     661           0 :   if (svgframe) {
     662             :     svgframe->NotifyViewportOrTransformChanged(
     663           0 :                 nsSVGDisplayableFrame::TRANSFORM_CHANGED);
     664             :   }
     665           0 : }
     666             : 
     667             : nsSVGElement::EnumAttributesInfo
     668          42 : SVGSVGElement::GetEnumInfo()
     669             : {
     670             :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
     671          42 :                             ArrayLength(sEnumInfo));
     672             : }
     673             : 
     674             : void
     675           0 : SVGSVGElement::
     676             :   SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR)
     677             : {
     678             : #ifdef DEBUG
     679           0 :   MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
     680             :              "should only override preserveAspectRatio in images");
     681             : #endif
     682             : 
     683           0 :   bool hasViewBoxRect = HasViewBoxRect();
     684           0 :   if (!hasViewBoxRect && ShouldSynthesizeViewBox()) {
     685             :     // My non-<svg:image> clients will have been painting me with a synthesized
     686             :     // viewBox, but my <svg:image> client that's about to paint me now does NOT
     687             :     // want that.  Need to tell ourselves to flush our transform.
     688           0 :     mImageNeedsTransformInvalidation = true;
     689             :   }
     690             : 
     691           0 :   if (!hasViewBoxRect) {
     692           0 :     return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
     693             :   }
     694             : 
     695           0 :   if (SetPreserveAspectRatioProperty(aPAR)) {
     696           0 :     mImageNeedsTransformInvalidation = true;
     697             :   }
     698             : }
     699             : 
     700             : void
     701           0 : SVGSVGElement::ClearImageOverridePreserveAspectRatio()
     702             : {
     703             : #ifdef DEBUG
     704           0 :   MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
     705             :              "should only override image preserveAspectRatio in images");
     706             : #endif
     707             : 
     708           0 :   if (!HasViewBoxRect() && ShouldSynthesizeViewBox()) {
     709             :     // My non-<svg:image> clients will want to paint me with a synthesized
     710             :     // viewBox, but my <svg:image> client that just painted me did NOT
     711             :     // use that.  Need to tell ourselves to flush our transform.
     712           0 :     mImageNeedsTransformInvalidation = true;
     713             :   }
     714             : 
     715           0 :   if (ClearPreserveAspectRatioProperty()) {
     716           0 :     mImageNeedsTransformInvalidation = true;
     717             :   }
     718           0 : }
     719             : 
     720             : bool
     721           0 : SVGSVGElement::SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR)
     722             : {
     723           0 :   SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR);
     724           0 :   nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio,
     725             :                             pAROverridePtr,
     726             :                             nsINode::DeleteProperty<SVGPreserveAspectRatio>,
     727           0 :                             true);
     728           0 :   MOZ_ASSERT(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
     729             :              "Setting override value when it's already set...?");
     730             : 
     731           0 :   if (MOZ_UNLIKELY(NS_FAILED(rv))) {
     732             :     // property-insertion failed (e.g. OOM in property-table code)
     733             :     delete pAROverridePtr;
     734           0 :     return false;
     735             :   }
     736           0 :   return true;
     737             : }
     738             : 
     739             : const SVGPreserveAspectRatio*
     740         539 : SVGSVGElement::GetPreserveAspectRatioProperty() const
     741             : {
     742         539 :   void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio);
     743         539 :   if (valPtr) {
     744           0 :     return static_cast<SVGPreserveAspectRatio*>(valPtr);
     745             :   }
     746         539 :   return nullptr;
     747             : }
     748             : 
     749             : bool
     750           0 : SVGSVGElement::ClearPreserveAspectRatioProperty()
     751             : {
     752           0 :   void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio);
     753             :   delete static_cast<SVGPreserveAspectRatio*>(valPtr);
     754           0 :   return valPtr;
     755             : }
     756             : 
     757             : 
     758             : SVGPreserveAspectRatio
     759         539 : SVGSVGElement::GetPreserveAspectRatioWithOverride() const
     760             : {
     761         539 :   nsIDocument* doc = GetUncomposedDoc();
     762         539 :   if (doc && doc->IsBeingUsedAsImage()) {
     763         539 :     const SVGPreserveAspectRatio *pAROverridePtr = GetPreserveAspectRatioProperty();
     764         539 :     if (pAROverridePtr) {
     765           0 :       return *pAROverridePtr;
     766             :     }
     767             :   }
     768             : 
     769         539 :   SVGViewElement* viewElement = GetCurrentViewElement();
     770             : 
     771             :   // This check is equivalent to "!HasViewBoxRect() && ShouldSynthesizeViewBox()".
     772             :   // We're just holding onto the viewElement that HasViewBoxRect() would look up,
     773             :   // so that we don't have to look it up again later.
     774        1617 :   if (!((viewElement && viewElement->mViewBox.HasRect()) ||
     775         539 :         (mSVGView && mSVGView->mViewBox.HasRect()) ||
     776        1196 :         mViewBox.HasRect()) &&
     777         118 :       ShouldSynthesizeViewBox()) {
     778             :     // If we're synthesizing a viewBox, use preserveAspectRatio="none";
     779         118 :     return SVGPreserveAspectRatio(SVG_PRESERVEASPECTRATIO_NONE, SVG_MEETORSLICE_SLICE);
     780             :   }
     781             : 
     782         421 :   if (viewElement && viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
     783           0 :     return viewElement->mPreserveAspectRatio.GetAnimValue();
     784             :   }
     785         421 :   if (mSVGView && mSVGView->mPreserveAspectRatio.IsExplicitlySet()) {
     786           0 :     return mSVGView->mPreserveAspectRatio.GetAnimValue();
     787             :   }
     788         421 :   return mPreserveAspectRatio.GetAnimValue();
     789             : }
     790             : 
     791             : SVGViewElement*
     792        2015 : SVGSVGElement::GetCurrentViewElement() const
     793             : {
     794        2015 :   if (mCurrentViewID) {
     795             :     //XXXsmaug It is unclear how this should work in case we're in Shadow DOM.
     796           0 :     nsIDocument* doc = GetUncomposedDoc();
     797           0 :     if (doc) {
     798           0 :       Element *element = doc->GetElementById(*mCurrentViewID);
     799           0 :       if (element && element->IsSVGElement(nsGkAtoms::view)) {
     800           0 :         return static_cast<SVGViewElement*>(element);
     801             :       }
     802             :     }
     803             :   }
     804        2015 :   return nullptr;
     805             : }
     806             : 
     807             : const nsSVGViewBox&
     808        1475 : SVGSVGElement::GetViewBoxInternal() const
     809             : {
     810        1475 :   SVGViewElement* viewElement = GetCurrentViewElement();
     811             : 
     812        1475 :   if (viewElement && viewElement->mViewBox.HasRect()) {
     813           0 :     return viewElement->mViewBox;
     814        1475 :   } else if (mSVGView && mSVGView->mViewBox.HasRect()) {
     815           0 :     return mSVGView->mViewBox;
     816             :   }
     817             : 
     818        1475 :   return mViewBox;
     819             : }
     820             : 
     821             : nsSVGAnimatedTransformList*
     822           0 : SVGSVGElement::GetTransformInternal() const
     823             : {
     824           0 :   return (mSVGView && mSVGView->mTransforms)
     825           0 :          ? mSVGView->mTransforms: mTransforms;
     826             : }
     827             : 
     828             : } // namespace dom
     829             : } // namespace mozilla

Generated by: LCOV version 1.13