1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "mozilla/dom/SVGAnimatedTransformList.h"
8 #include "DOMSVGTransformList.h"
9 #include "nsSVGAnimatedTransformList.h"
10 #include "nsSVGAttrTearoffTable.h"
11 #include "mozilla/dom/SVGAnimatedTransformListBinding.h"
12
13 namespace mozilla {
14 namespace dom {
15
16 static
17 nsSVGAttrTearoffTable<nsSVGAnimatedTransformList, SVGAnimatedTransformList>
18 sSVGAnimatedTransformListTearoffTable;
19
NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(SVGAnimatedTransformList,mElement)20 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(SVGAnimatedTransformList, mElement)
21
22 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SVGAnimatedTransformList, AddRef)
23 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SVGAnimatedTransformList, Release)
24
25 JSObject*
26 SVGAnimatedTransformList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
27 {
28 return SVGAnimatedTransformListBinding::Wrap(aCx, this, aGivenProto);
29 }
30
31 //----------------------------------------------------------------------
32 already_AddRefed<DOMSVGTransformList>
BaseVal()33 SVGAnimatedTransformList::BaseVal()
34 {
35 if (!mBaseVal) {
36 mBaseVal = new DOMSVGTransformList(this, InternalAList().GetBaseValue());
37 }
38 RefPtr<DOMSVGTransformList> baseVal = mBaseVal;
39 return baseVal.forget();
40 }
41
42 already_AddRefed<DOMSVGTransformList>
AnimVal()43 SVGAnimatedTransformList::AnimVal()
44 {
45 if (!mAnimVal) {
46 mAnimVal = new DOMSVGTransformList(this, InternalAList().GetAnimValue());
47 }
48 RefPtr<DOMSVGTransformList> animVal = mAnimVal;
49 return animVal.forget();
50 }
51
52 /* static */ already_AddRefed<SVGAnimatedTransformList>
GetDOMWrapper(nsSVGAnimatedTransformList * aList,nsSVGElement * aElement)53 SVGAnimatedTransformList::GetDOMWrapper(nsSVGAnimatedTransformList *aList,
54 nsSVGElement *aElement)
55 {
56 RefPtr<SVGAnimatedTransformList> wrapper =
57 sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
58 if (!wrapper) {
59 wrapper = new SVGAnimatedTransformList(aElement);
60 sSVGAnimatedTransformListTearoffTable.AddTearoff(aList, wrapper);
61 }
62 return wrapper.forget();
63 }
64
65 /* static */ SVGAnimatedTransformList*
GetDOMWrapperIfExists(nsSVGAnimatedTransformList * aList)66 SVGAnimatedTransformList::GetDOMWrapperIfExists(
67 nsSVGAnimatedTransformList *aList)
68 {
69 return sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
70 }
71
~SVGAnimatedTransformList()72 SVGAnimatedTransformList::~SVGAnimatedTransformList()
73 {
74 // Script no longer has any references to us, to our base/animVal objects, or
75 // to any of their list items.
76 sSVGAnimatedTransformListTearoffTable.RemoveTearoff(&InternalAList());
77 }
78
79 void
InternalBaseValListWillChangeLengthTo(uint32_t aNewLength)80 SVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo(
81 uint32_t aNewLength)
82 {
83 // When the number of items in our internal counterpart's baseVal changes,
84 // we MUST keep our baseVal in sync. If we don't, script will either see a
85 // list that is too short and be unable to access indexes that should be
86 // valid, or else, MUCH WORSE, script will see a list that is too long and be
87 // able to access "items" at indexes that are out of bounds (read/write to
88 // bad memory)!!
89
90 RefPtr<SVGAnimatedTransformList> kungFuDeathGrip;
91 if (mBaseVal) {
92 if (aNewLength < mBaseVal->LengthNoFlush()) {
93 // InternalListLengthWillChange might clear last reference to |this|.
94 // Retain a temporary reference to keep from dying before returning.
95 kungFuDeathGrip = this;
96 }
97 mBaseVal->InternalListLengthWillChange(aNewLength);
98 }
99
100 // If our attribute is not animating, then our animVal mirrors our baseVal
101 // and we must sync its length too. (If our attribute is animating, then the
102 // SMIL engine takes care of calling InternalAnimValListWillChangeLengthTo()
103 // if necessary.)
104
105 if (!IsAnimating()) {
106 InternalAnimValListWillChangeLengthTo(aNewLength);
107 }
108 }
109
110 void
InternalAnimValListWillChangeLengthTo(uint32_t aNewLength)111 SVGAnimatedTransformList::InternalAnimValListWillChangeLengthTo(
112 uint32_t aNewLength)
113 {
114 if (mAnimVal) {
115 mAnimVal->InternalListLengthWillChange(aNewLength);
116 }
117 }
118
119 bool
IsAnimating() const120 SVGAnimatedTransformList::IsAnimating() const
121 {
122 return InternalAList().IsAnimating();
123 }
124
125 nsSVGAnimatedTransformList&
InternalAList()126 SVGAnimatedTransformList::InternalAList()
127 {
128 return *mElement->GetAnimatedTransformList();
129 }
130
131 const nsSVGAnimatedTransformList&
InternalAList() const132 SVGAnimatedTransformList::InternalAList() const
133 {
134 return *mElement->GetAnimatedTransformList();
135 }
136
137 } // namespace dom
138 } // namespace mozilla
139