1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "DOMSVGPoint.h" 8 #include "DOMSVGPointList.h" 9 #include "SVGPoint.h" 10 #include "gfx2DGlue.h" 11 #include "nsSVGElement.h" 12 #include "nsError.h" 13 #include "mozilla/dom/SVGMatrix.h" 14 15 // See the architecture comment in DOMSVGPointList.h. 16 17 using namespace mozilla; 18 using namespace mozilla::gfx; 19 20 namespace mozilla { 21 22 //---------------------------------------------------------------------- 23 // Helper class: AutoChangePointNotifier 24 // Stack-based helper class to pair calls to WillChangePointList and 25 // DidChangePointList. 26 class MOZ_RAII AutoChangePointNotifier { 27 public: AutoChangePointNotifier(DOMSVGPoint * aPoint MOZ_GUARD_OBJECT_NOTIFIER_PARAM)28 explicit AutoChangePointNotifier( 29 DOMSVGPoint* aPoint MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 30 : mPoint(aPoint) { 31 MOZ_GUARD_OBJECT_NOTIFIER_INIT; 32 MOZ_ASSERT(mPoint, "Expecting non-null point"); 33 MOZ_ASSERT(mPoint->HasOwner(), 34 "Expecting list to have an owner for notification"); 35 mEmptyOrOldValue = mPoint->Element()->WillChangePointList(); 36 } 37 ~AutoChangePointNotifier()38 ~AutoChangePointNotifier() { 39 mPoint->Element()->DidChangePointList(mEmptyOrOldValue); 40 if (mPoint->mList->AttrIsAnimating()) { 41 mPoint->Element()->AnimationNeedsResample(); 42 } 43 } 44 45 private: 46 DOMSVGPoint* const mPoint; 47 nsAttrValue mEmptyOrOldValue; 48 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 49 }; 50 51 } // namespace mozilla 52 X()53float DOMSVGPoint::X() { 54 if (mIsAnimValItem && HasOwner()) { 55 Element()->FlushAnimations(); // May make HasOwner() == false 56 } 57 return HasOwner() ? InternalItem().mX : mPt.mX; 58 } 59 SetX(float aX,ErrorResult & rv)60void DOMSVGPoint::SetX(float aX, ErrorResult& rv) { 61 if (mIsAnimValItem || mIsReadonly) { 62 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); 63 return; 64 } 65 66 if (HasOwner()) { 67 if (InternalItem().mX == aX) { 68 return; 69 } 70 AutoChangePointNotifier notifier(this); 71 InternalItem().mX = aX; 72 return; 73 } 74 mPt.mX = aX; 75 } 76 Y()77float DOMSVGPoint::Y() { 78 if (mIsAnimValItem && HasOwner()) { 79 Element()->FlushAnimations(); // May make HasOwner() == false 80 } 81 return HasOwner() ? InternalItem().mY : mPt.mY; 82 } 83 SetY(float aY,ErrorResult & rv)84void DOMSVGPoint::SetY(float aY, ErrorResult& rv) { 85 if (mIsAnimValItem || mIsReadonly) { 86 rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); 87 return; 88 } 89 90 if (HasOwner()) { 91 if (InternalItem().mY == aY) { 92 return; 93 } 94 AutoChangePointNotifier notifier(this); 95 InternalItem().mY = aY; 96 return; 97 } 98 mPt.mY = aY; 99 } 100 MatrixTransform(dom::SVGMatrix & matrix)101already_AddRefed<nsISVGPoint> DOMSVGPoint::MatrixTransform( 102 dom::SVGMatrix& matrix) { 103 float x = HasOwner() ? InternalItem().mX : mPt.mX; 104 float y = HasOwner() ? InternalItem().mY : mPt.mY; 105 106 Point pt = ToMatrix(matrix.GetMatrix()).TransformPoint(Point(x, y)); 107 nsCOMPtr<nsISVGPoint> newPoint = new DOMSVGPoint(pt); 108 return newPoint.forget(); 109 } 110