LCOV - code coverage report
Current view: directory - content/svg/content/src - nsSVGSVGElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 516 3 0.6 %
Date: 2012-06-02 Functions: 100 2 2.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
      18                 :  * Crocodile Clips Ltd..
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
      24                 :  *   Jonathan Watt <jonathan.watt@strath.ac.uk>
      25                 :  *   Chris Double  <chris.double@double.co.nz>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "mozilla/Util.h"
      42                 : 
      43                 : #include "nsGkAtoms.h"
      44                 : #include "DOMSVGNumber.h"
      45                 : #include "DOMSVGLength.h"
      46                 : #include "nsSVGAngle.h"
      47                 : #include "nsCOMPtr.h"
      48                 : #include "nsIPresShell.h"
      49                 : #include "nsContentUtils.h"
      50                 : #include "nsIDocument.h"
      51                 : #include "nsPresContext.h"
      52                 : #include "DOMSVGMatrix.h"
      53                 : #include "DOMSVGPoint.h"
      54                 : #include "nsIDOMEventTarget.h"
      55                 : #include "nsIFrame.h"
      56                 : #include "nsISVGSVGFrame.h" //XXX
      57                 : #include "nsSVGRect.h"
      58                 : #include "nsDOMError.h"
      59                 : #include "nsISVGChildFrame.h"
      60                 : #include "nsGUIEvent.h"
      61                 : #include "nsSVGUtils.h"
      62                 : #include "nsSVGSVGElement.h"
      63                 : #include "nsContentErrors.h" // For NS_PROPTABLE_PROP_OVERWRITTEN
      64                 : #include "nsContentUtils.h"
      65                 : #include "nsStyleUtil.h"
      66                 : 
      67                 : #include "nsEventDispatcher.h"
      68                 : #include "nsSMILTimeContainer.h"
      69                 : #include "nsSMILAnimationController.h"
      70                 : #include "nsSMILTypes.h"
      71                 : #include "nsIContentIterator.h"
      72                 : 
      73                 : nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
      74                 : 
      75                 : using namespace mozilla;
      76                 : using namespace mozilla::dom;
      77                 : 
      78            1464 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGTranslatePoint::DOMVal, mElement)
      79                 : 
      80               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGTranslatePoint::DOMVal)
      81               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGTranslatePoint::DOMVal)
      82                 : 
      83               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGTranslatePoint::DOMVal)
      84               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPoint)
      85               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      86               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPoint)
      87               0 : NS_INTERFACE_MAP_END
      88                 : 
      89                 : nsresult
      90               0 : nsSVGTranslatePoint::ToDOMVal(nsSVGSVGElement *aElement,
      91                 :                               nsIDOMSVGPoint **aResult)
      92                 : {
      93               0 :   *aResult = new DOMVal(this, aElement);
      94               0 :   if (!*aResult)
      95               0 :     return NS_ERROR_OUT_OF_MEMORY;
      96                 :   
      97               0 :   NS_ADDREF(*aResult);
      98               0 :   return NS_OK;
      99                 : }
     100                 : 
     101                 : NS_IMETHODIMP
     102               0 : nsSVGTranslatePoint::DOMVal::SetX(float aValue)
     103                 : {
     104               0 :   NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
     105               0 :   return mElement->SetCurrentTranslate(aValue, mVal->GetY());
     106                 : }
     107                 : 
     108                 : NS_IMETHODIMP
     109               0 : nsSVGTranslatePoint::DOMVal::SetY(float aValue)
     110                 : {
     111               0 :   NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
     112               0 :   return mElement->SetCurrentTranslate(mVal->GetX(), aValue);
     113                 : }
     114                 : 
     115                 : /* nsIDOMSVGPoint matrixTransform (in nsIDOMSVGMatrix matrix); */
     116                 : NS_IMETHODIMP
     117               0 : nsSVGTranslatePoint::DOMVal::MatrixTransform(nsIDOMSVGMatrix *matrix,
     118                 :                                              nsIDOMSVGPoint **_retval)
     119                 : {
     120               0 :   if (!matrix)
     121               0 :     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     122                 : 
     123                 :   float a, b, c, d, e, f;
     124               0 :   matrix->GetA(&a);
     125               0 :   matrix->GetB(&b);
     126               0 :   matrix->GetC(&c);
     127               0 :   matrix->GetD(&d);
     128               0 :   matrix->GetE(&e);
     129               0 :   matrix->GetF(&f);
     130                 : 
     131               0 :   float x = mVal->GetX();
     132               0 :   float y = mVal->GetY();
     133                 : 
     134               0 :   NS_ADDREF(*_retval = new DOMSVGPoint(a*x + c*y + e, b*x + d*y + f));
     135               0 :   return NS_OK;
     136                 : }
     137                 : 
     138                 : nsSVGElement::LengthInfo nsSVGSVGElement::sLengthInfo[4] =
     139                 : {
     140                 :   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, nsSVGUtils::X },
     141                 :   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, nsSVGUtils::Y },
     142                 :   { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, nsSVGUtils::X },
     143                 :   { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, nsSVGUtils::Y },
     144                 : };
     145                 : 
     146                 : nsSVGEnumMapping nsSVGSVGElement::sZoomAndPanMap[] = {
     147                 :   {&nsGkAtoms::disable, nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE},
     148                 :   {&nsGkAtoms::magnify, nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY},
     149                 :   {nsnull, 0}
     150                 : };
     151                 : 
     152                 : nsSVGElement::EnumInfo nsSVGSVGElement::sEnumInfo[1] =
     153                 : {
     154                 :   { &nsGkAtoms::zoomAndPan,
     155                 :     sZoomAndPanMap,
     156                 :     nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY
     157                 :   }
     158                 : };
     159                 : 
     160               0 : NS_IMPL_NS_NEW_SVG_ELEMENT_CHECK_PARSER(SVG)
     161                 : 
     162                 : //----------------------------------------------------------------------
     163                 : // nsISupports methods
     164                 : 
     165            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGSVGElement)
     166               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGSVGElement,
     167                 :                                                 nsSVGSVGElementBase)
     168               0 :   if (tmp->mTimedDocumentRoot) {
     169               0 :     tmp->mTimedDocumentRoot->Unlink();
     170                 :   }
     171               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     172               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGSVGElement,
     173                 :                                                   nsSVGSVGElementBase)
     174               0 :   if (tmp->mTimedDocumentRoot) {
     175               0 :     tmp->mTimedDocumentRoot->Traverse(&cb);
     176                 :   }
     177               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     178                 : 
     179               0 : NS_IMPL_ADDREF_INHERITED(nsSVGSVGElement,nsSVGSVGElementBase)
     180               0 : NS_IMPL_RELEASE_INHERITED(nsSVGSVGElement,nsSVGSVGElementBase)
     181                 : 
     182               0 : DOMCI_NODE_DATA(SVGSVGElement, nsSVGSVGElement)
     183                 : 
     184               0 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGSVGElement)
     185               0 :   NS_NODE_INTERFACE_TABLE8(nsSVGSVGElement, nsIDOMNode, nsIDOMElement,
     186                 :                            nsIDOMSVGElement, nsIDOMSVGTests,
     187                 :                            nsIDOMSVGSVGElement,
     188                 :                            nsIDOMSVGFitToViewBox, nsIDOMSVGLocatable,
     189                 :                            nsIDOMSVGZoomAndPan)
     190               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSVGElement)
     191               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGSVGElementBase)
     192                 : 
     193                 : //----------------------------------------------------------------------
     194                 : // Implementation
     195                 : 
     196               0 : nsSVGSVGElement::nsSVGSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo,
     197                 :                                  FromParser aFromParser)
     198                 :   : nsSVGSVGElementBase(aNodeInfo),
     199                 :     mCoordCtx(nsnull),
     200                 :     mViewportWidth(0),
     201                 :     mViewportHeight(0),
     202                 :     mCurrentTranslate(0.0f, 0.0f),
     203                 :     mCurrentScale(1.0f),
     204                 :     mPreviousTranslate(0.0f, 0.0f),
     205                 :     mPreviousScale(1.0f),
     206                 :     mRedrawSuspendCount(0),
     207               0 :     mStartAnimationOnBindToTree(!aFromParser),
     208                 :     mImageNeedsTransformInvalidation(false),
     209               0 :     mIsPaintingSVGImageElement(false)
     210                 : {
     211               0 : }
     212                 : 
     213                 : //----------------------------------------------------------------------
     214                 : // nsIDOMNode methods
     215                 : 
     216                 : // From NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSVGElement)
     217                 : nsresult
     218               0 : nsSVGSVGElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
     219                 : {
     220               0 :   *aResult = nsnull;
     221               0 :   nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     222               0 :   nsSVGSVGElement *it = new nsSVGSVGElement(ni.forget(), NOT_FROM_PARSER);
     223                 : 
     224               0 :   nsCOMPtr<nsINode> kungFuDeathGrip = it;
     225               0 :   nsresult rv = it->Init();
     226               0 :   rv |= CopyInnerTo(it);
     227               0 :   if (NS_SUCCEEDED(rv)) {
     228               0 :     kungFuDeathGrip.swap(*aResult);
     229                 :   }
     230                 : 
     231               0 :   return rv;
     232                 : }
     233                 : 
     234                 : 
     235                 : //----------------------------------------------------------------------
     236                 : // nsIDOMSVGSVGElement methods:
     237                 : 
     238                 : /* readonly attribute nsIDOMSVGAnimatedLength x; */
     239                 : NS_IMETHODIMP
     240               0 : nsSVGSVGElement::GetX(nsIDOMSVGAnimatedLength * *aX)
     241                 : {
     242               0 :   return mLengthAttributes[X].ToDOMAnimatedLength(aX, this);
     243                 : }
     244                 : 
     245                 : /* readonly attribute nsIDOMSVGAnimatedLength y; */
     246                 : NS_IMETHODIMP
     247               0 : nsSVGSVGElement::GetY(nsIDOMSVGAnimatedLength * *aY)
     248                 : {
     249               0 :   return mLengthAttributes[Y].ToDOMAnimatedLength(aY, this);
     250                 : }
     251                 : 
     252                 : /* readonly attribute nsIDOMSVGAnimatedLength width; */
     253                 : NS_IMETHODIMP
     254               0 : nsSVGSVGElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth)
     255                 : {
     256               0 :   return mLengthAttributes[WIDTH].ToDOMAnimatedLength(aWidth, this);
     257                 : }
     258                 : 
     259                 : /* readonly attribute nsIDOMSVGAnimatedLength height; */
     260                 : NS_IMETHODIMP
     261               0 : nsSVGSVGElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
     262                 : {
     263               0 :   return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
     264                 : }
     265                 : 
     266                 : /* attribute DOMString contentScriptType; */
     267                 : NS_IMETHODIMP
     268               0 : nsSVGSVGElement::GetContentScriptType(nsAString & aContentScriptType)
     269                 : {
     270               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetContentScriptType");
     271               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     272                 : }
     273                 : NS_IMETHODIMP
     274               0 : nsSVGSVGElement::SetContentScriptType(const nsAString & aContentScriptType)
     275                 : {
     276               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetContentScriptType");
     277               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     278                 : }
     279                 : 
     280                 : /* attribute DOMString contentStyleType; */
     281                 : NS_IMETHODIMP
     282               0 : nsSVGSVGElement::GetContentStyleType(nsAString & aContentStyleType)
     283                 : {
     284               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetContentStyleType");
     285               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     286                 : }
     287                 : NS_IMETHODIMP
     288               0 : nsSVGSVGElement::SetContentStyleType(const nsAString & aContentStyleType)
     289                 : {
     290               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetContentStyleType");
     291               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     292                 : }
     293                 : 
     294                 : /* readonly attribute nsIDOMSVGRect viewport; */
     295                 : NS_IMETHODIMP
     296               0 : nsSVGSVGElement::GetViewport(nsIDOMSVGRect * *aViewport)
     297                 : {
     298                 :   // XXX
     299               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     300                 : }
     301                 : 
     302                 : /* readonly attribute float pixelUnitToMillimeterX; */
     303                 : NS_IMETHODIMP
     304               0 : nsSVGSVGElement::GetPixelUnitToMillimeterX(float *aPixelUnitToMillimeterX)
     305                 : {
     306               0 :   *aPixelUnitToMillimeterX = MM_PER_INCH_FLOAT / 96;
     307               0 :   return NS_OK;
     308                 : }
     309                 : 
     310                 : /* readonly attribute float pixelUnitToMillimeterY; */
     311                 : NS_IMETHODIMP
     312               0 : nsSVGSVGElement::GetPixelUnitToMillimeterY(float *aPixelUnitToMillimeterY)
     313                 : {
     314               0 :   return GetPixelUnitToMillimeterX(aPixelUnitToMillimeterY);
     315                 : }
     316                 : 
     317                 : /* readonly attribute float screenPixelToMillimeterX; */
     318                 : NS_IMETHODIMP
     319               0 : nsSVGSVGElement::GetScreenPixelToMillimeterX(float *aScreenPixelToMillimeterX)
     320                 : {
     321               0 :   *aScreenPixelToMillimeterX = MM_PER_INCH_FLOAT / 96;
     322               0 :   return NS_OK;
     323                 : }
     324                 : 
     325                 : /* readonly attribute float screenPixelToMillimeterY; */
     326                 : NS_IMETHODIMP
     327               0 : nsSVGSVGElement::GetScreenPixelToMillimeterY(float *aScreenPixelToMillimeterY)
     328                 : {
     329               0 :   return GetScreenPixelToMillimeterX(aScreenPixelToMillimeterY);
     330                 : }
     331                 : 
     332                 : /* attribute boolean useCurrentView; */
     333                 : NS_IMETHODIMP
     334               0 : nsSVGSVGElement::GetUseCurrentView(bool *aUseCurrentView)
     335                 : {
     336               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetUseCurrentView");
     337               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     338                 : }
     339                 : NS_IMETHODIMP
     340               0 : nsSVGSVGElement::SetUseCurrentView(bool aUseCurrentView)
     341                 : {
     342               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetUseCurrentView");
     343               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     344                 : }
     345                 : 
     346                 : /* readonly attribute nsIDOMSVGViewSpec currentView; */
     347                 : NS_IMETHODIMP
     348               0 : nsSVGSVGElement::GetCurrentView(nsIDOMSVGViewSpec * *aCurrentView)
     349                 : {
     350               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetCurrentView");
     351               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     352                 : }
     353                 : 
     354                 : /* attribute float currentScale; */
     355                 : NS_IMETHODIMP
     356               0 : nsSVGSVGElement::GetCurrentScale(float *aCurrentScale)
     357                 : {
     358               0 :   *aCurrentScale = mCurrentScale;
     359               0 :   return NS_OK;
     360                 : }
     361                 : 
     362                 : #define CURRENT_SCALE_MAX 16.0f
     363                 : #define CURRENT_SCALE_MIN 0.0625f
     364                 : 
     365                 : NS_IMETHODIMP
     366               0 : nsSVGSVGElement::SetCurrentScale(float aCurrentScale)
     367                 : {
     368                 :   return SetCurrentScaleTranslate(aCurrentScale,
     369               0 :     mCurrentTranslate.GetX(), mCurrentTranslate.GetY());
     370                 : }
     371                 : 
     372                 : /* readonly attribute nsIDOMSVGPoint currentTranslate; */
     373                 : NS_IMETHODIMP
     374               0 : nsSVGSVGElement::GetCurrentTranslate(nsIDOMSVGPoint * *aCurrentTranslate)
     375                 : {
     376               0 :   return mCurrentTranslate.ToDOMVal(this, aCurrentTranslate);
     377                 : }
     378                 : 
     379                 : /* unsigned long suspendRedraw (in unsigned long max_wait_milliseconds); */
     380                 : NS_IMETHODIMP
     381               0 : nsSVGSVGElement::SuspendRedraw(PRUint32 max_wait_milliseconds, PRUint32 *_retval)
     382                 : {
     383               0 :   *_retval = 1;
     384                 : 
     385               0 :   if (++mRedrawSuspendCount > 1) 
     386               0 :     return NS_OK;
     387                 : 
     388               0 :   nsIFrame* frame = GetPrimaryFrame();
     389               0 :   if (frame) {
     390               0 :     nsISVGSVGFrame* svgframe = do_QueryFrame(frame);
     391                 :     // might fail this check if we've failed conditional processing
     392               0 :     if (svgframe) {
     393               0 :       svgframe->SuspendRedraw();
     394                 :     }
     395                 :   }
     396                 :   
     397               0 :   return NS_OK;
     398                 : }
     399                 : 
     400                 : /* void unsuspendRedraw (in unsigned long suspend_handle_id); */
     401                 : NS_IMETHODIMP
     402               0 : nsSVGSVGElement::UnsuspendRedraw(PRUint32 suspend_handle_id)
     403                 : {
     404               0 :   if (mRedrawSuspendCount == 0) {
     405               0 :     return NS_ERROR_FAILURE;
     406                 :   }
     407                 :                  
     408               0 :   if (mRedrawSuspendCount > 1) {
     409               0 :     --mRedrawSuspendCount;
     410               0 :     return NS_OK;
     411                 :   }
     412                 :   
     413               0 :   return UnsuspendRedrawAll();
     414                 : }
     415                 : 
     416                 : /* void unsuspendRedrawAll (); */
     417                 : NS_IMETHODIMP
     418               0 : nsSVGSVGElement::UnsuspendRedrawAll()
     419                 : {
     420               0 :   mRedrawSuspendCount = 0;
     421                 : 
     422               0 :   nsIFrame* frame = GetPrimaryFrame();
     423               0 :   if (frame) {
     424               0 :     nsISVGSVGFrame* svgframe = do_QueryFrame(frame);
     425                 :     // might fail this check if we've failed conditional processing
     426               0 :     if (svgframe) {
     427               0 :       svgframe->UnsuspendRedraw();
     428                 :     }
     429                 :   }  
     430               0 :   return NS_OK;
     431                 : }
     432                 : 
     433                 : /* void forceRedraw (); */
     434                 : NS_IMETHODIMP
     435               0 : nsSVGSVGElement::ForceRedraw()
     436                 : {
     437               0 :   nsIDocument* doc = GetCurrentDoc();
     438               0 :   if (!doc) return NS_ERROR_FAILURE;
     439                 : 
     440               0 :   doc->FlushPendingNotifications(Flush_Display);
     441                 : 
     442               0 :   return NS_OK;
     443                 : }
     444                 : 
     445                 : /* void pauseAnimations (); */
     446                 : NS_IMETHODIMP
     447               0 : nsSVGSVGElement::PauseAnimations()
     448                 : {
     449               0 :   if (NS_SMILEnabled()) {
     450               0 :     if (mTimedDocumentRoot) {
     451               0 :       mTimedDocumentRoot->Pause(nsSMILTimeContainer::PAUSE_SCRIPT);
     452                 :     }
     453                 :     // else we're not the outermost <svg> or not bound to a tree, so silently fail
     454               0 :     return NS_OK;
     455                 :   }
     456               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::PauseAnimations");
     457               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     458                 : }
     459                 : 
     460                 : /* void unpauseAnimations (); */
     461                 : NS_IMETHODIMP
     462               0 : nsSVGSVGElement::UnpauseAnimations()
     463                 : {
     464               0 :   if (NS_SMILEnabled()) {
     465               0 :     if (mTimedDocumentRoot) {
     466               0 :       mTimedDocumentRoot->Resume(nsSMILTimeContainer::PAUSE_SCRIPT);
     467                 :     }
     468                 :     // else we're not the outermost <svg> or not bound to a tree, so silently fail
     469               0 :     return NS_OK;
     470                 :   }
     471               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::UnpauseAnimations");
     472               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     473                 : }
     474                 : 
     475                 : /* boolean animationsPaused (); */
     476                 : NS_IMETHODIMP
     477               0 : nsSVGSVGElement::AnimationsPaused(bool *_retval)
     478                 : {
     479               0 :   if (NS_SMILEnabled()) {
     480               0 :     nsSMILTimeContainer* root = GetTimedDocumentRoot();
     481               0 :     *_retval = root && root->IsPausedByType(nsSMILTimeContainer::PAUSE_SCRIPT);
     482               0 :     return NS_OK;
     483                 :   }
     484               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::AnimationsPaused");
     485               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     486                 : }
     487                 : 
     488                 : /* float getCurrentTime (); */
     489                 : NS_IMETHODIMP
     490               0 : nsSVGSVGElement::GetCurrentTime(float *_retval)
     491                 : {
     492               0 :   if (NS_SMILEnabled()) {
     493               0 :     nsSMILTimeContainer* root = GetTimedDocumentRoot();
     494               0 :     if (root) {
     495               0 :       double fCurrentTimeMs = double(root->GetCurrentTime());
     496               0 :       *_retval = (float)(fCurrentTimeMs / PR_MSEC_PER_SEC);
     497                 :     } else {
     498               0 :       *_retval = 0.f;
     499                 :     }
     500               0 :     return NS_OK;
     501                 :   }
     502               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetCurrentTime");
     503               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     504                 : }
     505                 : 
     506                 : /* void setCurrentTime (in float seconds); */
     507                 : NS_IMETHODIMP
     508               0 : nsSVGSVGElement::SetCurrentTime(float seconds)
     509                 : {
     510               0 :   NS_ENSURE_FINITE(seconds, NS_ERROR_ILLEGAL_VALUE);
     511               0 :   if (NS_SMILEnabled()) {
     512               0 :     if (mTimedDocumentRoot) {
     513                 :       // Make sure the timegraph is up-to-date
     514               0 :       FlushAnimations();
     515               0 :       double fMilliseconds = double(seconds) * PR_MSEC_PER_SEC;
     516                 :       // Round to nearest whole number before converting, to avoid precision
     517                 :       // errors
     518               0 :       nsSMILTime lMilliseconds = PRInt64(NS_round(fMilliseconds));
     519               0 :       mTimedDocumentRoot->SetCurrentTime(lMilliseconds);
     520               0 :       AnimationNeedsResample();
     521                 :       // Trigger synchronous sample now, to:
     522                 :       //  - Make sure we get an up-to-date paint after this method
     523                 :       //  - re-enable event firing (it got disabled during seeking, and it
     524                 :       //  doesn't get re-enabled until the first sample after the seek -- so
     525                 :       //  let's make that happen now.)
     526               0 :       FlushAnimations();
     527                 :     } // else we're not the outermost <svg> or not bound to a tree, so silently
     528                 :       // fail
     529               0 :     return NS_OK;
     530                 :   }
     531               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetCurrentTime");
     532               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     533                 : }
     534                 : 
     535                 : /* nsIDOMNodeList getIntersectionList (in nsIDOMSVGRect rect, in nsIDOMSVGElement referenceElement); */
     536                 : NS_IMETHODIMP
     537               0 : nsSVGSVGElement::GetIntersectionList(nsIDOMSVGRect *rect,
     538                 :                                      nsIDOMSVGElement *referenceElement,
     539                 :                                      nsIDOMNodeList **_retval)
     540                 : {
     541                 :   // null check when implementing - this method can be used by scripts!
     542                 :   // if (!rect || !referenceElement)
     543                 :   //   return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     544                 : 
     545               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetIntersectionList");
     546               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     547                 : }
     548                 : 
     549                 : /* nsIDOMNodeList getEnclosureList (in nsIDOMSVGRect rect, in nsIDOMSVGElement referenceElement); */
     550                 : NS_IMETHODIMP
     551               0 : nsSVGSVGElement::GetEnclosureList(nsIDOMSVGRect *rect,
     552                 :                                   nsIDOMSVGElement *referenceElement,
     553                 :                                   nsIDOMNodeList **_retval)
     554                 : {
     555                 :   // null check when implementing - this method can be used by scripts!
     556                 :   // if (!rect || !referenceElement)
     557                 :   //   return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     558                 : 
     559               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetEnclosureList");
     560               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     561                 : }
     562                 : 
     563                 : /* boolean checkIntersection (in nsIDOMSVGElement element, in nsIDOMSVGRect rect); */
     564                 : NS_IMETHODIMP
     565               0 : nsSVGSVGElement::CheckIntersection(nsIDOMSVGElement *element,
     566                 :                                    nsIDOMSVGRect *rect,
     567                 :                                    bool *_retval)
     568                 : {
     569                 :   // null check when implementing - this method can be used by scripts!
     570                 :   // if (!element || !rect)
     571                 :   //   return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     572                 : 
     573               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::CheckIntersection");
     574               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     575                 : }
     576                 : 
     577                 : /* boolean checkEnclosure (in nsIDOMSVGElement element, in nsIDOMSVGRect rect); */
     578                 : NS_IMETHODIMP
     579               0 : nsSVGSVGElement::CheckEnclosure(nsIDOMSVGElement *element,
     580                 :                                 nsIDOMSVGRect *rect,
     581                 :                                 bool *_retval)
     582                 : {
     583                 :   // null check when implementing - this method can be used by scripts!
     584                 :   // if (!element || !rect)
     585                 :   //   return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     586                 : 
     587               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::CheckEnclosure");
     588               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     589                 : }
     590                 : 
     591                 : /* void deSelectAll (); */
     592                 : NS_IMETHODIMP
     593               0 : nsSVGSVGElement::DeSelectAll()
     594                 : {
     595               0 :   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::DeSelectAll");
     596               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     597                 : }
     598                 : 
     599                 : /* nsIDOMSVGNumber createSVGNumber (); */
     600                 : NS_IMETHODIMP
     601               0 : nsSVGSVGElement::CreateSVGNumber(nsIDOMSVGNumber **_retval)
     602                 : {
     603               0 :   NS_ADDREF(*_retval = new DOMSVGNumber());
     604               0 :   return NS_OK;
     605                 : }
     606                 : 
     607                 : /* nsIDOMSVGLength createSVGLength (); */
     608                 : NS_IMETHODIMP
     609               0 : nsSVGSVGElement::CreateSVGLength(nsIDOMSVGLength **_retval)
     610                 : {
     611               0 :   NS_ADDREF(*_retval = new DOMSVGLength());
     612               0 :   return NS_OK;
     613                 : }
     614                 : 
     615                 : /* nsIDOMSVGAngle createSVGAngle (); */
     616                 : NS_IMETHODIMP
     617               0 : nsSVGSVGElement::CreateSVGAngle(nsIDOMSVGAngle **_retval)
     618                 : {
     619               0 :   return NS_NewDOMSVGAngle(_retval);
     620                 : }
     621                 : 
     622                 : /* nsIDOMSVGPoint createSVGPoint (); */
     623                 : NS_IMETHODIMP
     624               0 : nsSVGSVGElement::CreateSVGPoint(nsIDOMSVGPoint **_retval)
     625                 : {
     626               0 :   NS_ADDREF(*_retval = new DOMSVGPoint(0, 0));
     627               0 :   return NS_OK;
     628                 : }
     629                 : 
     630                 : /* nsIDOMSVGMatrix createSVGMatrix (); */
     631                 : NS_IMETHODIMP
     632               0 : nsSVGSVGElement::CreateSVGMatrix(nsIDOMSVGMatrix **_retval)
     633                 : {
     634               0 :   NS_ADDREF(*_retval = new DOMSVGMatrix());
     635               0 :   return NS_OK;
     636                 : }
     637                 : 
     638                 : /* nsIDOMSVGRect createSVGRect (); */
     639                 : NS_IMETHODIMP
     640               0 : nsSVGSVGElement::CreateSVGRect(nsIDOMSVGRect **_retval)
     641                 : {
     642               0 :   return NS_NewSVGRect(_retval);
     643                 : }
     644                 : 
     645                 : /* nsIDOMSVGTransform createSVGTransform (); */
     646                 : NS_IMETHODIMP
     647               0 : nsSVGSVGElement::CreateSVGTransform(nsIDOMSVGTransform **_retval)
     648                 : {
     649               0 :   NS_ADDREF(*_retval = new DOMSVGTransform());
     650               0 :   return NS_OK;
     651                 : }
     652                 : 
     653                 : /* nsIDOMSVGTransform createSVGTransformFromMatrix (in nsIDOMSVGMatrix matrix); */
     654                 : NS_IMETHODIMP
     655               0 : nsSVGSVGElement::CreateSVGTransformFromMatrix(nsIDOMSVGMatrix *matrix, 
     656                 :                                               nsIDOMSVGTransform **_retval)
     657                 : {
     658               0 :   nsCOMPtr<DOMSVGMatrix> domItem = do_QueryInterface(matrix);
     659               0 :   if (!domItem) {
     660               0 :     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     661                 :   }
     662                 : 
     663               0 :   NS_ADDREF(*_retval = new DOMSVGTransform(domItem->Matrix()));
     664               0 :   return NS_OK;
     665                 : }
     666                 : 
     667                 : /* nsIDOMElement getElementById (in DOMString elementId); */
     668                 : NS_IMETHODIMP
     669               0 : nsSVGSVGElement::GetElementById(const nsAString & elementId, nsIDOMElement **_retval)
     670                 : {
     671               0 :   NS_ENSURE_ARG_POINTER(_retval);
     672               0 :   *_retval = nsnull;
     673                 : 
     674               0 :   nsresult rv = NS_OK;
     675               0 :   nsAutoString selector(NS_LITERAL_STRING("#"));
     676               0 :   nsStyleUtil::AppendEscapedCSSIdent(PromiseFlatString(elementId), selector);
     677               0 :   nsIContent* element = nsGenericElement::doQuerySelector(this, selector, &rv);
     678               0 :   if (NS_SUCCEEDED(rv) && element) {
     679               0 :     return CallQueryInterface(element, _retval);
     680                 :   }
     681               0 :   return rv;
     682                 : }
     683                 : 
     684                 : //----------------------------------------------------------------------
     685                 : // nsIDOMSVGFitToViewBox methods
     686                 : 
     687                 : /* readonly attribute nsIDOMSVGAnimatedRect viewBox; */
     688                 : NS_IMETHODIMP
     689               0 : nsSVGSVGElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
     690                 : {
     691               0 :   return mViewBox.ToDOMAnimatedRect(aViewBox, this);
     692                 : }
     693                 : 
     694                 : /* readonly attribute nsIDOMSVGAnimatedPreserveAspectRatio preserveAspectRatio; */
     695                 : NS_IMETHODIMP
     696               0 : nsSVGSVGElement::GetPreserveAspectRatio(nsIDOMSVGAnimatedPreserveAspectRatio
     697                 :                                         **aPreserveAspectRatio)
     698                 : {
     699               0 :   return mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(aPreserveAspectRatio, this);
     700                 : }
     701                 : 
     702                 : //----------------------------------------------------------------------
     703                 : // nsIDOMSVGLocatable methods
     704                 : 
     705                 : /* readonly attribute nsIDOMSVGElement nearestViewportElement; */
     706                 : NS_IMETHODIMP
     707               0 : nsSVGSVGElement::GetNearestViewportElement(nsIDOMSVGElement * *aNearestViewportElement)
     708                 : {
     709               0 :   *aNearestViewportElement = nsSVGUtils::GetNearestViewportElement(this).get();
     710               0 :   return NS_OK;
     711                 : }
     712                 : 
     713                 : /* readonly attribute nsIDOMSVGElement farthestViewportElement; */
     714                 : NS_IMETHODIMP
     715               0 : nsSVGSVGElement::GetFarthestViewportElement(nsIDOMSVGElement * *aFarthestViewportElement)
     716                 : {
     717               0 :   NS_IF_ADDREF(*aFarthestViewportElement = nsSVGUtils::GetOuterSVGElement(this));
     718               0 :   return NS_OK;
     719                 : }
     720                 : 
     721                 : /* nsIDOMSVGRect getBBox (); */
     722                 : NS_IMETHODIMP
     723               0 : nsSVGSVGElement::GetBBox(nsIDOMSVGRect **_retval)
     724                 : {
     725               0 :   *_retval = nsnull;
     726                 : 
     727               0 :   nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
     728                 : 
     729               0 :   if (!frame || (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD))
     730               0 :     return NS_ERROR_FAILURE;
     731                 : 
     732               0 :   nsISVGChildFrame* svgframe = do_QueryFrame(frame);
     733               0 :   if (svgframe) {
     734               0 :     return NS_NewSVGRect(_retval, nsSVGUtils::GetBBox(frame));
     735                 :   }
     736               0 :   return NS_ERROR_NOT_IMPLEMENTED; // XXX: outer svg
     737                 : }
     738                 : 
     739                 : /* nsIDOMSVGMatrix getCTM (); */
     740                 : NS_IMETHODIMP
     741               0 : nsSVGSVGElement::GetCTM(nsIDOMSVGMatrix * *aCTM)
     742                 : {
     743               0 :   gfxMatrix m = nsSVGUtils::GetCTM(this, false);
     744               0 :   *aCTM = m.IsSingular() ? nsnull : new DOMSVGMatrix(m);
     745               0 :   NS_IF_ADDREF(*aCTM);
     746               0 :   return NS_OK;
     747                 : }
     748                 : 
     749                 : /* nsIDOMSVGMatrix getScreenCTM (); */
     750                 : NS_IMETHODIMP
     751               0 : nsSVGSVGElement::GetScreenCTM(nsIDOMSVGMatrix **aCTM)
     752                 : {
     753               0 :   gfxMatrix m;
     754               0 :   if (IsRoot()) {
     755                 :     // Consistency with other elements would have us return only the
     756                 :     // eFromUserSpace transforms, but this is what we've been doing for
     757                 :     // a while, and it keeps us consistent with WebKit and Opera (if not
     758                 :     // really with the ambiguous spec).
     759               0 :     m = PrependLocalTransformsTo(m);
     760                 :   } else {
     761               0 :     m = nsSVGUtils::GetCTM(this, true);
     762                 :   }
     763               0 :   *aCTM = m.IsSingular() ? nsnull : new DOMSVGMatrix(m);
     764               0 :   NS_IF_ADDREF(*aCTM);
     765               0 :   return NS_OK;
     766                 : }
     767                 : 
     768                 : /* nsIDOMSVGMatrix getTransformToElement (in nsIDOMSVGElement element); */
     769                 : NS_IMETHODIMP
     770               0 : nsSVGSVGElement::GetTransformToElement(nsIDOMSVGElement *element,
     771                 :                                        nsIDOMSVGMatrix **_retval)
     772                 : {
     773               0 :   if (!element)
     774               0 :     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
     775                 : 
     776                 :   nsresult rv;
     777               0 :   *_retval = nsnull;
     778               0 :   nsCOMPtr<nsIDOMSVGMatrix> ourScreenCTM;
     779               0 :   nsCOMPtr<nsIDOMSVGMatrix> targetScreenCTM;
     780               0 :   nsCOMPtr<nsIDOMSVGMatrix> tmp;
     781               0 :   nsCOMPtr<nsIDOMSVGLocatable> target = do_QueryInterface(element, &rv);
     782               0 :   if (NS_FAILED(rv)) return rv;
     783                 : 
     784                 :   // the easiest way to do this (if likely to increase rounding error):
     785               0 :   GetScreenCTM(getter_AddRefs(ourScreenCTM));
     786               0 :   if (!ourScreenCTM) return NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE;
     787               0 :   target->GetScreenCTM(getter_AddRefs(targetScreenCTM));
     788               0 :   if (!targetScreenCTM) return NS_ERROR_DOM_SVG_MATRIX_NOT_INVERTABLE;
     789               0 :   rv = targetScreenCTM->Inverse(getter_AddRefs(tmp));
     790               0 :   if (NS_FAILED(rv)) return rv;
     791               0 :   return tmp->Multiply(ourScreenCTM, _retval);  // addrefs, so we don't
     792                 : }
     793                 : 
     794                 : //----------------------------------------------------------------------
     795                 : // nsIDOMSVGZoomAndPan methods
     796                 : 
     797                 : /* attribute unsigned short zoomAndPan; */
     798                 : NS_IMETHODIMP
     799               0 : nsSVGSVGElement::GetZoomAndPan(PRUint16 *aZoomAndPan)
     800                 : {
     801               0 :   *aZoomAndPan = mEnumAttributes[ZOOMANDPAN].GetAnimValue();
     802               0 :   return NS_OK;
     803                 : }
     804                 : 
     805                 : NS_IMETHODIMP
     806               0 : nsSVGSVGElement::SetZoomAndPan(PRUint16 aZoomAndPan)
     807                 : {
     808               0 :   if (aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE ||
     809                 :       aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY) {
     810               0 :     mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this);
     811               0 :     return NS_OK;
     812                 :   }
     813                 : 
     814               0 :   return NS_ERROR_DOM_SVG_INVALID_VALUE_ERR;
     815                 : }
     816                 : 
     817                 : //----------------------------------------------------------------------
     818                 : // helper methods for implementing SVGZoomEvent:
     819                 : 
     820                 : NS_IMETHODIMP
     821               0 : nsSVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y)
     822                 : {
     823               0 :   NS_ENSURE_FINITE3(s, x, y, NS_ERROR_ILLEGAL_VALUE);
     824                 : 
     825               0 :   if (s == mCurrentScale &&
     826               0 :       x == mCurrentTranslate.GetX() && y == mCurrentTranslate.GetY()) {
     827               0 :     return NS_OK;
     828                 :   }
     829                 : 
     830                 :   // Prevent bizarre behaviour and maxing out of CPU and memory by clamping
     831               0 :   if (s < CURRENT_SCALE_MIN)
     832               0 :     s = CURRENT_SCALE_MIN;
     833               0 :   else if (s > CURRENT_SCALE_MAX)
     834               0 :     s = CURRENT_SCALE_MAX;
     835                 :   
     836                 :   // IMPORTANT: If either mCurrentTranslate *or* mCurrentScale is changed then
     837                 :   // mPreviousTranslate_x, mPreviousTranslate_y *and* mPreviousScale must all
     838                 :   // be updated otherwise SVGZoomEvents will end up with invalid data. I.e. an
     839                 :   // SVGZoomEvent's properties previousScale and previousTranslate must contain
     840                 :   // the state of currentScale and currentTranslate immediately before the
     841                 :   // change that caused the event's dispatch, which is *not* necessarily the
     842                 :   // same thing as the values of currentScale and currentTranslate prior to
     843                 :   // their own last change.
     844               0 :   mPreviousScale = mCurrentScale;
     845               0 :   mPreviousTranslate = mCurrentTranslate;
     846                 :   
     847               0 :   mCurrentScale = s;
     848               0 :   mCurrentTranslate = nsSVGTranslatePoint(x, y);
     849                 : 
     850                 :   // now dispatch the appropriate event if we are the root element
     851               0 :   nsIDocument* doc = GetCurrentDoc();
     852               0 :   if (doc) {
     853               0 :     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
     854               0 :     if (presShell && IsRoot()) {
     855               0 :       bool scaling = (mPreviousScale != mCurrentScale);
     856               0 :       nsEventStatus status = nsEventStatus_eIgnore;
     857               0 :       nsGUIEvent event(true, scaling ? NS_SVG_ZOOM : NS_SVG_SCROLL, 0);
     858               0 :       event.eventStructType = scaling ? NS_SVGZOOM_EVENT : NS_SVG_EVENT;
     859               0 :       presShell->HandleDOMEventWithTarget(this, &event, &status);
     860               0 :       InvalidateTransformNotifyFrame();
     861                 :     }
     862                 :   }
     863               0 :   return NS_OK;
     864                 : }
     865                 : 
     866                 : NS_IMETHODIMP
     867               0 : nsSVGSVGElement::SetCurrentTranslate(float x, float y)
     868                 : {
     869               0 :   return SetCurrentScaleTranslate(mCurrentScale, x, y);
     870                 : }
     871                 : 
     872                 : nsSMILTimeContainer*
     873               0 : nsSVGSVGElement::GetTimedDocumentRoot()
     874                 : {
     875               0 :   if (mTimedDocumentRoot) {
     876               0 :     return mTimedDocumentRoot;
     877                 :   }
     878                 : 
     879                 :   // We must not be the outermost <svg> element, try to find it
     880                 :   nsSVGSVGElement *outerSVGElement =
     881               0 :     nsSVGUtils::GetOuterSVGElement(this);
     882                 : 
     883               0 :   if (outerSVGElement) {
     884               0 :     return outerSVGElement->GetTimedDocumentRoot();
     885                 :   }
     886                 :   // invalid structure
     887               0 :   return nsnull;
     888                 : }
     889                 : 
     890                 : //----------------------------------------------------------------------
     891                 : // nsIContent methods
     892                 : 
     893                 : NS_IMETHODIMP_(bool)
     894               0 : nsSVGSVGElement::IsAttributeMapped(const nsIAtom* name) const
     895                 : {
     896                 :   // We want to map the 'width' and 'height' attributes into style for
     897                 :   // outer-<svg>, except when the attributes aren't set (since their default
     898                 :   // values of '100%' can cause unexpected and undesirable behaviour for SVG
     899                 :   // inline in HTML). We rely on nsSVGElement::UpdateContentStyleRule() to
     900                 :   // prevent mapping of the default values into style (it only maps attributes
     901                 :   // that are set). We also rely on a check in nsSVGElement::
     902                 :   // UpdateContentStyleRule() to prevent us mapping the attributes when they're
     903                 :   // given a <length> value that is not currently recognized by the SVG
     904                 :   // specification.
     905                 : 
     906               0 :   if (!IsInner() && (name == nsGkAtoms::width || name == nsGkAtoms::height)) {
     907               0 :     return true;
     908                 :   }
     909                 : 
     910                 :   static const MappedAttributeEntry* const map[] = {
     911                 :     sColorMap,
     912                 :     sFEFloodMap,
     913                 :     sFillStrokeMap,
     914                 :     sFiltersMap,
     915                 :     sFontSpecificationMap,
     916                 :     sGradientStopMap,
     917                 :     sGraphicsMap,
     918                 :     sLightingEffectsMap,
     919                 :     sMarkersMap,
     920                 :     sTextContentElementsMap,
     921                 :     sViewportsMap
     922                 :   };
     923                 : 
     924               0 :   return FindAttributeDependence(name, map) ||
     925               0 :     nsSVGSVGElementBase::IsAttributeMapped(name);
     926                 : }
     927                 : 
     928                 : //----------------------------------------------------------------------
     929                 : // nsIContent methods:
     930                 : 
     931                 : nsresult
     932               0 : nsSVGSVGElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
     933                 : {
     934               0 :   if (aVisitor.mEvent->message == NS_SVG_LOAD) {
     935               0 :     if (mTimedDocumentRoot) {
     936               0 :       mTimedDocumentRoot->Begin();
     937                 :       // Set 'resample needed' flag, so that if any script calls a DOM method
     938                 :       // that requires up-to-date animations before our first sample callback,
     939                 :       // we'll force a synchronous sample.
     940               0 :       AnimationNeedsResample();
     941                 :     }
     942                 :   }
     943               0 :   return nsSVGSVGElementBase::PreHandleEvent(aVisitor);
     944                 : }
     945                 : 
     946                 : //----------------------------------------------------------------------
     947                 : // nsSVGElement overrides
     948                 : 
     949                 : bool
     950               0 : nsSVGSVGElement::IsEventName(nsIAtom* aName)
     951                 : {
     952                 :   /* The events in EventNameType_SVGSVG are for events that are only
     953                 :      applicable to outermost 'svg' elements. We don't check if we're an outer
     954                 :      'svg' element in case we're not inserted into the document yet, but since
     955                 :      the target of the events in question will always be the outermost 'svg'
     956                 :      element, this shouldn't cause any real problems.
     957                 :   */
     958                 :   return nsContentUtils::IsEventAttributeName(aName,
     959               0 :          (EventNameType_SVGGraphic | EventNameType_SVGSVG));
     960                 : }
     961                 : 
     962                 : // Helper for GetViewBoxTransform on root <svg> node
     963                 : // * aLength: internal value for our <svg> width or height attribute.
     964                 : // * aViewportLength: length of the corresponding dimension of the viewport.
     965                 : // * aSelf: the outermost <svg> node itself.
     966                 : // NOTE: aSelf is not an ancestor viewport element, so it can't be used to
     967                 : // resolve percentage lengths. (It can only be used to resolve
     968                 : // 'em'/'ex'-valued units).
     969                 : inline float
     970               0 : ComputeSynthesizedViewBoxDimension(const nsSVGLength2& aLength,
     971                 :                                    float aViewportLength,
     972                 :                                    const nsSVGSVGElement* aSelf)
     973                 : {
     974               0 :   if (aLength.IsPercentage()) {
     975               0 :     return aViewportLength * aLength.GetAnimValInSpecifiedUnits() / 100.0f;
     976                 :   }
     977                 : 
     978               0 :   return aLength.GetAnimValue(const_cast<nsSVGSVGElement*>(aSelf));
     979                 : }
     980                 : 
     981                 : //----------------------------------------------------------------------
     982                 : // public helpers:
     983                 : 
     984                 : gfxMatrix
     985               0 : nsSVGSVGElement::GetViewBoxTransform() const
     986                 : {
     987                 :   // Do we have an override preserveAspectRatio value?
     988                 :   const SVGPreserveAspectRatio* overridePARPtr =
     989               0 :     GetImageOverridePreserveAspectRatio();
     990                 : 
     991                 :   // May assign this to overridePARPtr if we have no viewBox but are faking one:
     992               0 :   SVGPreserveAspectRatio tmpPAR;
     993                 : 
     994                 :   float viewportWidth, viewportHeight;
     995               0 :   if (IsInner()) {
     996               0 :     nsSVGSVGElement *ctx = GetCtx();
     997               0 :     viewportWidth = mLengthAttributes[WIDTH].GetAnimValue(ctx);
     998               0 :     viewportHeight = mLengthAttributes[HEIGHT].GetAnimValue(ctx);
     999                 :   } else {
    1000               0 :     viewportWidth = mViewportWidth;
    1001               0 :     viewportHeight = mViewportHeight;
    1002                 :   }
    1003                 : 
    1004               0 :   if (viewportWidth <= 0.0f || viewportHeight <= 0.0f) {
    1005               0 :     return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
    1006                 :   }
    1007                 : 
    1008               0 :   nsSVGViewBoxRect viewBox;
    1009               0 :   if (mViewBox.IsValid()) {
    1010               0 :     viewBox = mViewBox.GetAnimValue();
    1011                 :   } else {
    1012               0 :     viewBox.x = viewBox.y = 0.0f;
    1013               0 :     if (ShouldSynthesizeViewBox()) {
    1014                 :       // Special case -- fake a viewBox, using height & width attrs.
    1015                 :       // (Use |this| as context, since if we get here, we're outermost <svg>.)
    1016                 :       viewBox.width =
    1017                 :         ComputeSynthesizedViewBoxDimension(mLengthAttributes[WIDTH],
    1018               0 :                                            mViewportWidth, this);
    1019                 :       viewBox.height =
    1020                 :         ComputeSynthesizedViewBoxDimension(mLengthAttributes[HEIGHT],
    1021               0 :                                            mViewportHeight, this);
    1022               0 :       NS_ABORT_IF_FALSE(!overridePARPtr,
    1023                 :                         "shouldn't have overridePAR if we're "
    1024                 :                         "synthesizing a viewBox");
    1025                 : 
    1026                 :       // If we're synthesizing a viewBox, use preserveAspectRatio="none";
    1027               0 :       tmpPAR.SetAlign(nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE);
    1028                 : 
    1029                 :       // (set the other pAR attributes too, just so they're initialized):
    1030               0 :       tmpPAR.SetDefer(false);
    1031               0 :       tmpPAR.SetMeetOrSlice(nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE);
    1032                 : 
    1033               0 :       overridePARPtr = &tmpPAR;
    1034                 :     } else {
    1035                 :       // No viewBox attribute, so we shouldn't auto-scale. This is equivalent
    1036                 :       // to having a viewBox that exactly matches our viewport size.
    1037               0 :       viewBox.width  = viewportWidth;
    1038               0 :       viewBox.height = viewportHeight;
    1039                 :     }
    1040                 :   }
    1041                 : 
    1042               0 :   if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
    1043               0 :     return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // singular
    1044                 :   }
    1045                 : 
    1046                 :   return nsSVGUtils::GetViewBoxTransform(this,
    1047                 :                                          viewportWidth, viewportHeight,
    1048                 :                                          viewBox.x, viewBox.y,
    1049                 :                                          viewBox.width, viewBox.height,
    1050                 :                                          overridePARPtr ? *overridePARPtr :
    1051               0 :                                          mPreserveAspectRatio.GetAnimValue());
    1052                 : }
    1053                 : 
    1054                 : nsresult
    1055               0 : nsSVGSVGElement::BindToTree(nsIDocument* aDocument,
    1056                 :                             nsIContent* aParent,
    1057                 :                             nsIContent* aBindingParent,
    1058                 :                             bool aCompileEventHandlers)
    1059                 : {
    1060               0 :   nsSMILAnimationController* smilController = nsnull;
    1061                 : 
    1062               0 :   if (aDocument) {
    1063               0 :     smilController = aDocument->GetAnimationController();
    1064               0 :     if (smilController) {
    1065                 :       // SMIL is enabled in this document
    1066               0 :       if (WillBeOutermostSVG(aParent, aBindingParent)) {
    1067                 :         // We'll be the outermost <svg> element.  We'll need a time container.
    1068               0 :         if (!mTimedDocumentRoot) {
    1069               0 :           mTimedDocumentRoot = new nsSMILTimeContainer();
    1070               0 :           NS_ENSURE_TRUE(mTimedDocumentRoot, NS_ERROR_OUT_OF_MEMORY);
    1071                 :         }
    1072                 :       } else {
    1073                 :         // We're a child of some other <svg> element, so we don't need our own
    1074                 :         // time container. However, we need to make sure that we'll get a
    1075                 :         // kick-start if we get promoted to be outermost later on.
    1076               0 :         mTimedDocumentRoot = nsnull;
    1077               0 :         mStartAnimationOnBindToTree = true;
    1078                 :       }
    1079                 :     }
    1080                 :   }
    1081                 : 
    1082                 :   nsresult rv = nsSVGSVGElementBase::BindToTree(aDocument, aParent,
    1083                 :                                                 aBindingParent,
    1084               0 :                                                 aCompileEventHandlers);
    1085               0 :   NS_ENSURE_SUCCESS(rv,rv);
    1086                 : 
    1087               0 :   if (mTimedDocumentRoot && smilController) {
    1088               0 :     rv = mTimedDocumentRoot->SetParent(smilController);
    1089               0 :     if (mStartAnimationOnBindToTree) {
    1090               0 :       mTimedDocumentRoot->Begin();
    1091               0 :       mStartAnimationOnBindToTree = false;
    1092                 :     }
    1093                 :   }
    1094                 : 
    1095               0 :   return rv;
    1096                 : }
    1097                 : 
    1098                 : void
    1099               0 : nsSVGSVGElement::UnbindFromTree(bool aDeep, bool aNullParent)
    1100                 : {
    1101               0 :   if (mTimedDocumentRoot) {
    1102               0 :     mTimedDocumentRoot->SetParent(nsnull);
    1103                 :   }
    1104                 : 
    1105               0 :   nsSVGSVGElementBase::UnbindFromTree(aDeep, aNullParent);
    1106               0 : }
    1107                 : 
    1108                 : //----------------------------------------------------------------------
    1109                 : // implementation helpers
    1110                 : 
    1111                 : bool
    1112               0 : nsSVGSVGElement::WillBeOutermostSVG(nsIContent* aParent,
    1113                 :                                     nsIContent* aBindingParent) const
    1114                 : {
    1115               0 :   nsIContent* parent = aBindingParent ? aBindingParent : aParent;
    1116                 : 
    1117               0 :   while (parent && parent->IsSVG()) {
    1118               0 :     nsIAtom* tag = parent->Tag();
    1119               0 :     if (tag == nsGkAtoms::foreignObject) {
    1120                 :       // SVG in a foreignObject must have its own <svg> (nsSVGOuterSVGFrame).
    1121               0 :       return false;
    1122                 :     }
    1123               0 :     if (tag == nsGkAtoms::svg) {
    1124               0 :       return false;
    1125                 :     }
    1126               0 :     parent = parent->GetParent();
    1127                 :   }
    1128                 : 
    1129               0 :   return true;
    1130                 : }
    1131                 : 
    1132                 : void
    1133               0 : nsSVGSVGElement::InvalidateTransformNotifyFrame()
    1134                 : {
    1135               0 :   nsIFrame* frame = GetPrimaryFrame();
    1136               0 :   if (frame) {
    1137               0 :     nsISVGSVGFrame* svgframe = do_QueryFrame(frame);
    1138                 :     // might fail this check if we've failed conditional processing
    1139               0 :     if (svgframe) {
    1140               0 :       svgframe->NotifyViewportChange();
    1141                 :     }
    1142                 :   }
    1143               0 : }
    1144                 : 
    1145                 : bool
    1146               0 : nsSVGSVGElement::HasPreserveAspectRatio()
    1147                 : {
    1148               0 :   return HasAttr(kNameSpaceID_None, nsGkAtoms::preserveAspectRatio) ||
    1149               0 :     mPreserveAspectRatio.IsAnimated();
    1150                 : }
    1151                 : 
    1152                 : //----------------------------------------------------------------------
    1153                 : // nsSVGSVGElement
    1154                 : 
    1155                 : float
    1156               0 : nsSVGSVGElement::GetLength(PRUint8 aCtxType)
    1157                 : {
    1158                 :   float h, w;
    1159                 : 
    1160               0 :   if (mViewBox.IsValid()) {
    1161               0 :     const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue();
    1162               0 :     w = viewbox.width;
    1163               0 :     h = viewbox.height;
    1164               0 :   } else if (IsInner()) {
    1165               0 :     nsSVGSVGElement *ctx = GetCtx();
    1166               0 :     w = mLengthAttributes[WIDTH].GetAnimValue(ctx);
    1167               0 :     h = mLengthAttributes[HEIGHT].GetAnimValue(ctx);
    1168               0 :   } else if (ShouldSynthesizeViewBox()) {
    1169                 :     w = ComputeSynthesizedViewBoxDimension(mLengthAttributes[WIDTH],
    1170               0 :                                            mViewportWidth, this);
    1171                 :     h = ComputeSynthesizedViewBoxDimension(mLengthAttributes[HEIGHT],
    1172               0 :                                            mViewportHeight, this);
    1173                 :   } else {
    1174               0 :     w = mViewportWidth;
    1175               0 :     h = mViewportHeight;
    1176                 :   }
    1177                 : 
    1178               0 :   w = NS_MAX(w, 0.0f);
    1179               0 :   h = NS_MAX(h, 0.0f);
    1180                 : 
    1181               0 :   switch (aCtxType) {
    1182                 :   case nsSVGUtils::X:
    1183               0 :     return w;
    1184                 :   case nsSVGUtils::Y:
    1185               0 :     return h;
    1186                 :   case nsSVGUtils::XY:
    1187               0 :     return float(nsSVGUtils::ComputeNormalizedHypotenuse(w, h));
    1188                 :   }
    1189               0 :   return 0;
    1190                 : }
    1191                 : 
    1192                 : void
    1193               0 : nsSVGSVGElement::SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const
    1194                 : {
    1195               0 :   NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height,
    1196                 :                "The clue is in the function name");
    1197                 : 
    1198               0 :   PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT;
    1199               0 :   aTarget->SetLength(aName, mLengthAttributes[index]);
    1200               0 : }
    1201                 : 
    1202                 : //----------------------------------------------------------------------
    1203                 : // nsSVGElement methods
    1204                 : 
    1205                 : /* virtual */ gfxMatrix
    1206               0 : nsSVGSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
    1207                 :                                           TransformTypes aWhich) const
    1208                 : {
    1209               0 :   NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
    1210                 :                     "Skipping eUserSpaceToParent transforms makes no sense");
    1211                 : 
    1212               0 :   if (IsInner()) {
    1213                 :     float x, y;
    1214               0 :     const_cast<nsSVGSVGElement*>(this)->GetAnimatedLengthValues(&x, &y, nsnull);
    1215               0 :     if (aWhich == eAllTransforms) {
    1216                 :       // the common case
    1217               0 :       return GetViewBoxTransform() * gfxMatrix().Translate(gfxPoint(x, y)) * aMatrix;
    1218                 :     }
    1219               0 :     if (aWhich == eUserSpaceToParent) {
    1220               0 :       return gfxMatrix().Translate(gfxPoint(x, y)) * aMatrix;
    1221                 :     }
    1222               0 :     NS_ABORT_IF_FALSE(aWhich == eChildToUserSpace, "Unknown TransformTypes");
    1223               0 :     return GetViewBoxTransform(); // no need to multiply identity aMatrix
    1224                 :   }
    1225                 : 
    1226               0 :   if (aWhich == eUserSpaceToParent) {
    1227                 :     // only inner-<svg> has eUserSpaceToParent transforms
    1228               0 :     return aMatrix;
    1229                 :   }
    1230                 : 
    1231               0 :   if (IsRoot()) {
    1232               0 :     gfxMatrix zoomPanTM;
    1233               0 :     zoomPanTM.Translate(gfxPoint(mCurrentTranslate.GetX(), mCurrentTranslate.GetY()));
    1234               0 :     zoomPanTM.Scale(mCurrentScale, mCurrentScale);
    1235               0 :     return GetViewBoxTransform() * zoomPanTM * aMatrix;
    1236                 :   }
    1237                 : 
    1238                 :   // outer-<svg>, but inline in some other content:
    1239               0 :   return GetViewBoxTransform() * aMatrix;
    1240                 : }
    1241                 : 
    1242                 : /* virtual */ bool
    1243               0 : nsSVGSVGElement::HasValidDimensions() const
    1244                 : {
    1245               0 :   return !IsInner() ||
    1246               0 :     ((!mLengthAttributes[WIDTH].IsExplicitlySet() ||
    1247               0 :        mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
    1248               0 :      (!mLengthAttributes[HEIGHT].IsExplicitlySet() || 
    1249               0 :        mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0));
    1250                 : }
    1251                 : 
    1252                 : nsSVGElement::LengthAttributesInfo
    1253               0 : nsSVGSVGElement::GetLengthInfo()
    1254                 : {
    1255                 :   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
    1256               0 :                               ArrayLength(sLengthInfo));
    1257                 : }
    1258                 : 
    1259                 : nsSVGElement::EnumAttributesInfo
    1260               0 : nsSVGSVGElement::GetEnumInfo()
    1261                 : {
    1262                 :   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
    1263               0 :                             ArrayLength(sEnumInfo));
    1264                 : }
    1265                 : 
    1266                 : nsSVGViewBox *
    1267               0 : nsSVGSVGElement::GetViewBox()
    1268                 : {
    1269               0 :   return &mViewBox;
    1270                 : }
    1271                 : 
    1272                 : SVGAnimatedPreserveAspectRatio *
    1273               0 : nsSVGSVGElement::GetPreserveAspectRatio()
    1274                 : {
    1275               0 :   return &mPreserveAspectRatio;
    1276                 : }
    1277                 : 
    1278                 : bool
    1279               0 : nsSVGSVGElement::ShouldSynthesizeViewBox() const
    1280                 : {
    1281               0 :   NS_ABORT_IF_FALSE(!HasValidViewbox(),
    1282                 :                     "Should only be called if we lack a viewBox");
    1283                 : 
    1284               0 :   nsIDocument* doc = GetCurrentDoc();
    1285                 :   return doc &&
    1286               0 :     doc->IsBeingUsedAsImage() &&
    1287               0 :     !mIsPaintingSVGImageElement &&
    1288               0 :     !GetParent();
    1289                 : }
    1290                 : 
    1291                 : 
    1292                 : // Callback function, for freeing PRUint64 values stored in property table
    1293                 : static void
    1294               0 : ReleasePreserveAspectRatioPropertyValue(void*    aObject,       /* unused */
    1295                 :                                         nsIAtom* aPropertyName, /* unused */
    1296                 :                                         void*    aPropertyValue,
    1297                 :                                         void*    aData          /* unused */)
    1298                 : {
    1299                 :   SVGPreserveAspectRatio* valPtr =
    1300               0 :     static_cast<SVGPreserveAspectRatio*>(aPropertyValue);
    1301                 :   delete valPtr;
    1302               0 : }
    1303                 : 
    1304                 : void
    1305               0 : nsSVGSVGElement::
    1306                 :   SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR)
    1307                 : {
    1308                 : #ifdef DEBUG
    1309               0 :   NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
    1310                 :                     "should only override preserveAspectRatio in images");
    1311                 : #endif
    1312                 : 
    1313               0 :   if (!HasValidViewbox() && ShouldSynthesizeViewBox()) {
    1314                 :     // My non-<svg:image> clients will have been painting me with a synthesized
    1315                 :     // viewBox, but my <svg:image> client that's about to paint me now does NOT
    1316                 :     // want that.  Need to tell ourselves to flush our transform.
    1317               0 :     mImageNeedsTransformInvalidation = true;
    1318                 :   }
    1319               0 :   mIsPaintingSVGImageElement = true;
    1320                 : 
    1321               0 :   if (!mViewBox.IsValid()) {
    1322               0 :     return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
    1323                 :   }
    1324                 : 
    1325               0 :   if (aPAR.GetDefer() && HasPreserveAspectRatio()) {
    1326               0 :     return; // Referring element defers to my own preserveAspectRatio value.
    1327                 :   }
    1328                 : 
    1329               0 :   SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR);
    1330                 :   nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio,
    1331                 :                             pAROverridePtr,
    1332               0 :                             ReleasePreserveAspectRatioPropertyValue);
    1333               0 :   NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
    1334                 :                     "Setting override value when it's already set...?"); 
    1335                 : 
    1336               0 :   if (NS_LIKELY(NS_SUCCEEDED(rv))) {
    1337               0 :     mImageNeedsTransformInvalidation = true;
    1338                 :   } else {
    1339                 :     // property-insertion failed (e.g. OOM in property-table code)
    1340                 :     delete pAROverridePtr;
    1341                 :   }
    1342                 : }
    1343                 : 
    1344                 : void
    1345               0 : nsSVGSVGElement::ClearImageOverridePreserveAspectRatio()
    1346                 : {
    1347                 : #ifdef DEBUG
    1348               0 :   NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
    1349                 :                     "should only override preserveAspectRatio in images");
    1350                 : #endif
    1351                 : 
    1352               0 :   mIsPaintingSVGImageElement = false;
    1353               0 :   if (!HasValidViewbox() && ShouldSynthesizeViewBox()) {
    1354                 :     // My non-<svg:image> clients will want to paint me with a synthesized
    1355                 :     // viewBox, but my <svg:image> client that just painted me did NOT
    1356                 :     // use that.  Need to tell ourselves to flush our transform.
    1357               0 :     mImageNeedsTransformInvalidation = true;
    1358                 :   }
    1359                 : 
    1360               0 :   void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio);
    1361               0 :   if (valPtr) {
    1362               0 :     mImageNeedsTransformInvalidation = true;
    1363                 :     delete static_cast<SVGPreserveAspectRatio*>(valPtr);
    1364                 :   }
    1365               0 : }
    1366                 : 
    1367                 : const SVGPreserveAspectRatio*
    1368               0 : nsSVGSVGElement::GetImageOverridePreserveAspectRatio() const
    1369                 : {
    1370               0 :   void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio);
    1371                 : #ifdef DEBUG
    1372               0 :   if (valPtr) {
    1373               0 :     NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
    1374                 :                       "should only override preserveAspectRatio in images");
    1375                 :   }
    1376                 : #endif
    1377                 : 
    1378               0 :   return static_cast<SVGPreserveAspectRatio*>(valPtr);
    1379                 : }
    1380                 : 
    1381                 : void
    1382               0 : nsSVGSVGElement::FlushImageTransformInvalidation()
    1383                 : {
    1384               0 :   NS_ABORT_IF_FALSE(!GetParent(), "Should only be called on root node");
    1385               0 :   NS_ABORT_IF_FALSE(GetCurrentDoc()->IsBeingUsedAsImage(),
    1386                 :                     "Should only be called on image documents");
    1387                 : 
    1388               0 :   if (mImageNeedsTransformInvalidation) {
    1389               0 :     InvalidateTransformNotifyFrame();
    1390               0 :     mImageNeedsTransformInvalidation = false;
    1391                 :   }
    1392            4392 : }

Generated by: LCOV version 1.7