Line data Source code
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 "DOMSVGAnimatedLengthList.h"
8 : #include "DOMSVGLengthList.h"
9 : #include "SVGAnimatedLengthList.h"
10 : #include "nsSVGElement.h"
11 : #include "nsCOMPtr.h"
12 : #include "nsSVGAttrTearoffTable.h"
13 : #include "mozilla/dom/SVGAnimatedLengthListBinding.h"
14 :
15 : // See the architecture comment in this file's header.
16 :
17 : namespace mozilla {
18 :
19 : static inline
20 : nsSVGAttrTearoffTable<SVGAnimatedLengthList, DOMSVGAnimatedLengthList>&
21 0 : SVGAnimatedLengthListTearoffTable()
22 : {
23 : static nsSVGAttrTearoffTable<SVGAnimatedLengthList, DOMSVGAnimatedLengthList>
24 0 : sSVGAnimatedLengthListTearoffTable;
25 0 : return sSVGAnimatedLengthListTearoffTable;
26 : }
27 :
28 0 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGAnimatedLengthList, mElement)
29 :
30 0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DOMSVGAnimatedLengthList, AddRef)
31 0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMSVGAnimatedLengthList, Release)
32 :
33 : JSObject*
34 0 : DOMSVGAnimatedLengthList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
35 : {
36 0 : return dom::SVGAnimatedLengthListBinding::Wrap(aCx, this, aGivenProto);
37 : }
38 :
39 : already_AddRefed<DOMSVGLengthList>
40 0 : DOMSVGAnimatedLengthList::BaseVal()
41 : {
42 0 : if (!mBaseVal) {
43 0 : mBaseVal = new DOMSVGLengthList(this, InternalAList().GetBaseValue());
44 : }
45 0 : RefPtr<DOMSVGLengthList> baseVal = mBaseVal;
46 0 : return baseVal.forget();
47 : }
48 :
49 : already_AddRefed<DOMSVGLengthList>
50 0 : DOMSVGAnimatedLengthList::AnimVal()
51 : {
52 0 : if (!mAnimVal) {
53 0 : mAnimVal = new DOMSVGLengthList(this, InternalAList().GetAnimValue());
54 : }
55 0 : RefPtr<DOMSVGLengthList> animVal = mAnimVal;
56 0 : return animVal.forget();
57 : }
58 :
59 : /* static */ already_AddRefed<DOMSVGAnimatedLengthList>
60 0 : DOMSVGAnimatedLengthList::GetDOMWrapper(SVGAnimatedLengthList *aList,
61 : nsSVGElement *aElement,
62 : uint8_t aAttrEnum,
63 : uint8_t aAxis)
64 : {
65 : RefPtr<DOMSVGAnimatedLengthList> wrapper =
66 0 : SVGAnimatedLengthListTearoffTable().GetTearoff(aList);
67 0 : if (!wrapper) {
68 0 : wrapper = new DOMSVGAnimatedLengthList(aElement, aAttrEnum, aAxis);
69 0 : SVGAnimatedLengthListTearoffTable().AddTearoff(aList, wrapper);
70 : }
71 0 : return wrapper.forget();
72 : }
73 :
74 : /* static */ DOMSVGAnimatedLengthList*
75 0 : DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(SVGAnimatedLengthList *aList)
76 : {
77 0 : return SVGAnimatedLengthListTearoffTable().GetTearoff(aList);
78 : }
79 :
80 0 : DOMSVGAnimatedLengthList::~DOMSVGAnimatedLengthList()
81 : {
82 : // Script no longer has any references to us, to our base/animVal objects, or
83 : // to any of their list items.
84 0 : SVGAnimatedLengthListTearoffTable().RemoveTearoff(&InternalAList());
85 0 : }
86 :
87 : void
88 0 : DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo(const SVGLengthList& aNewValue)
89 : {
90 : // When the number of items in our internal counterpart's baseVal changes,
91 : // we MUST keep our baseVal in sync. If we don't, script will either see a
92 : // list that is too short and be unable to access indexes that should be
93 : // valid, or else, MUCH WORSE, script will see a list that is too long and be
94 : // able to access "items" at indexes that are out of bounds (read/write to
95 : // bad memory)!!
96 :
97 0 : RefPtr<DOMSVGAnimatedLengthList> kungFuDeathGrip;
98 0 : if (mBaseVal) {
99 0 : if (aNewValue.Length() < mBaseVal->LengthNoFlush()) {
100 : // InternalListLengthWillChange might clear last reference to |this|.
101 : // Retain a temporary reference to keep from dying before returning.
102 0 : kungFuDeathGrip = this;
103 : }
104 0 : mBaseVal->InternalListLengthWillChange(aNewValue.Length());
105 : }
106 :
107 : // If our attribute is not animating, then our animVal mirrors our baseVal
108 : // and we must sync its length too. (If our attribute is animating, then the
109 : // SMIL engine takes care of calling InternalAnimValListWillChangeTo() if
110 : // necessary.)
111 :
112 0 : if (!IsAnimating()) {
113 0 : InternalAnimValListWillChangeTo(aNewValue);
114 : }
115 0 : }
116 :
117 : void
118 0 : DOMSVGAnimatedLengthList::InternalAnimValListWillChangeTo(const SVGLengthList& aNewValue)
119 : {
120 0 : if (mAnimVal) {
121 0 : mAnimVal->InternalListLengthWillChange(aNewValue.Length());
122 : }
123 0 : }
124 :
125 : bool
126 0 : DOMSVGAnimatedLengthList::IsAnimating() const
127 : {
128 0 : return InternalAList().IsAnimating();
129 : }
130 :
131 : SVGAnimatedLengthList&
132 0 : DOMSVGAnimatedLengthList::InternalAList()
133 : {
134 0 : return *mElement->GetAnimatedLengthList(mAttrEnum);
135 : }
136 :
137 : const SVGAnimatedLengthList&
138 0 : DOMSVGAnimatedLengthList::InternalAList() const
139 : {
140 0 : return *mElement->GetAnimatedLengthList(mAttrEnum);
141 : }
142 :
143 : } // namespace mozilla
|