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()53 float 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)60 void 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()77 float 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)84 void 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)101 already_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