LCOV - app.info - content/svg/content/src/nsSVGSVGElement.cpp

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