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 Mozilla SVG Project code.
16 : *
17 : * The Initial Developer of the Original Code is the Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2010
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPL"), or
25 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 : #include "SVGAnimatedNumberList.h"
38 : #include "DOMSVGAnimatedNumberList.h"
39 : #include "nsSVGElement.h"
40 : #include "nsSVGAttrTearoffTable.h"
41 : #include "nsSMILValue.h"
42 : #include "SVGNumberListSMILType.h"
43 :
44 : namespace mozilla {
45 :
46 : nsresult
47 0 : SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue)
48 : {
49 0 : SVGNumberList newBaseValue;
50 0 : nsresult rv = newBaseValue.SetValueFromString(aValue);
51 0 : if (NS_FAILED(rv)) {
52 0 : return rv;
53 : }
54 :
55 : DOMSVGAnimatedNumberList *domWrapper =
56 0 : DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
57 0 : if (domWrapper) {
58 : // We must send this notification *before* changing mBaseVal! If the length
59 : // of our baseVal is being reduced, our baseVal's DOM wrapper list may have
60 : // to remove DOM items from itself, and any removed DOM items need to copy
61 : // their internal counterpart values *before* we change them.
62 : //
63 0 : domWrapper->InternalBaseValListWillChangeTo(newBaseValue);
64 : }
65 :
66 : // We don't need to call DidChange* here - we're only called by
67 : // nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
68 : // which takes care of notifying.
69 :
70 0 : mIsBaseSet = true;
71 0 : rv = mBaseVal.CopyFrom(newBaseValue);
72 0 : if (NS_FAILED(rv) && domWrapper) {
73 : // Attempting to increase mBaseVal's length failed - reduce domWrapper
74 : // back to the same length:
75 0 : domWrapper->InternalBaseValListWillChangeTo(mBaseVal);
76 : }
77 0 : return rv;
78 : }
79 :
80 : void
81 0 : SVGAnimatedNumberList::ClearBaseValue(PRUint32 aAttrEnum)
82 : {
83 : DOMSVGAnimatedNumberList *domWrapper =
84 0 : DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
85 0 : if (domWrapper) {
86 : // We must send this notification *before* changing mBaseVal! (See above.)
87 0 : domWrapper->InternalBaseValListWillChangeTo(SVGNumberList());
88 : }
89 0 : mBaseVal.Clear();
90 0 : mIsBaseSet = false;
91 : // Caller notifies
92 0 : }
93 :
94 : nsresult
95 0 : SVGAnimatedNumberList::SetAnimValue(const SVGNumberList& aNewAnimValue,
96 : nsSVGElement *aElement,
97 : PRUint32 aAttrEnum)
98 : {
99 : DOMSVGAnimatedNumberList *domWrapper =
100 0 : DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
101 0 : if (domWrapper) {
102 : // A new animation may totally change the number of items in the animVal
103 : // list, replacing what was essentially a mirror of the baseVal list, or
104 : // else replacing and overriding an existing animation. When this happens
105 : // we must try and keep our animVal's DOM wrapper in sync (see the comment
106 : // in DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo).
107 : //
108 : // It's not possible for us to reliably distinguish between calls to this
109 : // method that are setting a new sample for an existing animation, and
110 : // calls that are setting the first sample of an animation that will
111 : // override an existing animation. Happily it's cheap to just blindly
112 : // notify our animVal's DOM wrapper of its internal counterpart's new value
113 : // each time this method is called, so that's what we do.
114 : //
115 : // Note that we must send this notification *before* setting or changing
116 : // mAnimVal! (See the comment in SetBaseValueString above.)
117 : //
118 0 : domWrapper->InternalAnimValListWillChangeTo(aNewAnimValue);
119 : }
120 0 : if (!mAnimVal) {
121 0 : mAnimVal = new SVGNumberList();
122 : }
123 0 : nsresult rv = mAnimVal->CopyFrom(aNewAnimValue);
124 0 : if (NS_FAILED(rv)) {
125 : // OOM. We clear the animation, and, importantly, ClearAnimValue() ensures
126 : // that mAnimVal and its DOM wrapper (if any) will have the same length!
127 0 : ClearAnimValue(aElement, aAttrEnum);
128 0 : return rv;
129 : }
130 0 : aElement->DidAnimateNumberList(aAttrEnum);
131 0 : return NS_OK;
132 : }
133 :
134 : void
135 0 : SVGAnimatedNumberList::ClearAnimValue(nsSVGElement *aElement,
136 : PRUint32 aAttrEnum)
137 : {
138 : DOMSVGAnimatedNumberList *domWrapper =
139 0 : DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
140 0 : if (domWrapper) {
141 : // When all animation ends, animVal simply mirrors baseVal, which may have
142 : // a different number of items to the last active animated value. We must
143 : // keep the length of our animVal's DOM wrapper list in sync, and again we
144 : // must do that before touching mAnimVal. See comments above.
145 : //
146 0 : domWrapper->InternalAnimValListWillChangeTo(mBaseVal);
147 : }
148 0 : mAnimVal = nsnull;
149 0 : aElement->DidAnimateNumberList(aAttrEnum);
150 0 : }
151 :
152 : nsISMILAttr*
153 0 : SVGAnimatedNumberList::ToSMILAttr(nsSVGElement *aSVGElement,
154 : PRUint8 aAttrEnum)
155 : {
156 0 : return new SMILAnimatedNumberList(this, aSVGElement, aAttrEnum);
157 : }
158 :
159 : nsresult
160 0 : SVGAnimatedNumberList::
161 : SMILAnimatedNumberList::ValueFromString(const nsAString& aStr,
162 : const nsISMILAnimationElement* /*aSrcElement*/,
163 : nsSMILValue& aValue,
164 : bool& aPreventCachingOfSandwich) const
165 : {
166 0 : nsSMILValue val(&SVGNumberListSMILType::sSingleton);
167 0 : SVGNumberListAndInfo *nlai = static_cast<SVGNumberListAndInfo*>(val.mU.mPtr);
168 0 : nsresult rv = nlai->SetValueFromString(aStr);
169 0 : if (NS_SUCCEEDED(rv)) {
170 0 : nlai->SetInfo(mElement);
171 0 : aValue.Swap(val);
172 : }
173 0 : aPreventCachingOfSandwich = false;
174 0 : return rv;
175 : }
176 :
177 : nsSMILValue
178 0 : SVGAnimatedNumberList::SMILAnimatedNumberList::GetBaseValue() const
179 : {
180 : // To benefit from Return Value Optimization and avoid copy constructor calls
181 : // due to our use of return-by-value, we must return the exact same object
182 : // from ALL return points. This function must only return THIS variable:
183 0 : nsSMILValue val;
184 :
185 0 : nsSMILValue tmp(&SVGNumberListSMILType::sSingleton);
186 0 : SVGNumberListAndInfo *nlai = static_cast<SVGNumberListAndInfo*>(tmp.mU.mPtr);
187 0 : nsresult rv = nlai->CopyFrom(mVal->mBaseVal);
188 0 : if (NS_SUCCEEDED(rv)) {
189 0 : nlai->SetInfo(mElement);
190 0 : val.Swap(tmp);
191 : }
192 : return val;
193 : }
194 :
195 : nsresult
196 0 : SVGAnimatedNumberList::SMILAnimatedNumberList::SetAnimValue(const nsSMILValue& aValue)
197 : {
198 0 : NS_ASSERTION(aValue.mType == &SVGNumberListSMILType::sSingleton,
199 : "Unexpected type to assign animated value");
200 0 : if (aValue.mType == &SVGNumberListSMILType::sSingleton) {
201 : mVal->SetAnimValue(*static_cast<SVGNumberListAndInfo*>(aValue.mU.mPtr),
202 : mElement,
203 0 : mAttrEnum);
204 : }
205 0 : return NS_OK;
206 : }
207 :
208 : void
209 0 : SVGAnimatedNumberList::SMILAnimatedNumberList::ClearAnimValue()
210 : {
211 0 : if (mVal->mAnimVal) {
212 0 : mVal->ClearAnimValue(mElement, mAttrEnum);
213 : }
214 0 : }
215 :
216 : } // namespace mozilla
|