/src/mozilla-central/dom/svg/DOMSVGLength.cpp
Line | Count | Source (jump to first uncovered line) |
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 "DOMSVGLength.h" |
8 | | #include "DOMSVGLengthList.h" |
9 | | #include "DOMSVGAnimatedLengthList.h" |
10 | | #include "SVGLength.h" |
11 | | #include "SVGAnimatedLengthList.h" |
12 | | #include "nsSVGElement.h" |
13 | | #include "nsSVGLength2.h" |
14 | | #include "nsError.h" |
15 | | #include "nsMathUtils.h" |
16 | | #include "mozilla/dom/SVGLengthBinding.h" |
17 | | #include "mozilla/FloatingPoint.h" |
18 | | #include "nsSVGAttrTearoffTable.h" |
19 | | |
20 | | // See the architecture comment in DOMSVGAnimatedLengthList.h. |
21 | | |
22 | | namespace mozilla { |
23 | | |
24 | | using namespace dom; |
25 | | |
26 | | static nsSVGAttrTearoffTable<nsSVGLength2, DOMSVGLength> |
27 | | sBaseSVGLengthTearOffTable, |
28 | | sAnimSVGLengthTearOffTable; |
29 | | |
30 | | // We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to |
31 | | // clear our list's weak ref to us to be safe. (The other option would be to |
32 | | // not unlink and rely on the breaking of the other edges in the cycle, as |
33 | | // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.) |
34 | | NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLength) |
35 | | |
36 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLength) |
37 | 0 | tmp->CleanupWeakRefs(); |
38 | 0 | tmp->mVal = nullptr; // (owned by mSVGElement, which we drop our ref to here) |
39 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mList) |
40 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mSVGElement) |
41 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER |
42 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK_END |
43 | | |
44 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLength) |
45 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList) |
46 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSVGElement) |
47 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END |
48 | | |
49 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGLength) |
50 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER |
51 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_END |
52 | | |
53 | | NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGLength) |
54 | | NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGLength) |
55 | | |
56 | 0 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGLength) |
57 | 0 | NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY |
58 | 0 | NS_INTERFACE_MAP_ENTRY(mozilla::DOMSVGLength) // pseudo-interface |
59 | 0 | NS_INTERFACE_MAP_ENTRY(nsISupports) |
60 | 0 | NS_INTERFACE_MAP_END |
61 | | |
62 | | //---------------------------------------------------------------------- |
63 | | // Helper class: AutoChangeLengthNotifier |
64 | | // Stack-based helper class to pair calls to WillChangeLengthList and |
65 | | // DidChangeLengthList. |
66 | | class MOZ_RAII AutoChangeLengthNotifier |
67 | | { |
68 | | public: |
69 | | explicit AutoChangeLengthNotifier(DOMSVGLength* aLength MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
70 | | : mLength(aLength) |
71 | 0 | { |
72 | 0 | MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
73 | 0 | MOZ_ASSERT(mLength, "Expecting non-null length"); |
74 | 0 | MOZ_ASSERT(mLength->HasOwner(), |
75 | 0 | "Expecting list to have an owner for notification"); |
76 | 0 | mEmptyOrOldValue = |
77 | 0 | mLength->Element()->WillChangeLengthList(mLength->mAttrEnum); |
78 | 0 | } |
79 | | |
80 | | ~AutoChangeLengthNotifier() |
81 | 0 | { |
82 | 0 | mLength->Element()->DidChangeLengthList(mLength->mAttrEnum, |
83 | 0 | mEmptyOrOldValue); |
84 | 0 | if (mLength->mList->IsAnimating()) { |
85 | 0 | mLength->Element()->AnimationNeedsResample(); |
86 | 0 | } |
87 | 0 | } |
88 | | |
89 | | private: |
90 | | DOMSVGLength* const mLength; |
91 | | nsAttrValue mEmptyOrOldValue; |
92 | | MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
93 | | }; |
94 | | |
95 | | DOMSVGLength::DOMSVGLength(DOMSVGLengthList *aList, |
96 | | uint8_t aAttrEnum, |
97 | | uint32_t aListIndex, |
98 | | bool aIsAnimValItem) |
99 | | : mList(aList) |
100 | | , mListIndex(aListIndex) |
101 | | , mAttrEnum(aAttrEnum) |
102 | | , mIsAnimValItem(aIsAnimValItem) |
103 | | , mUnit(SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) |
104 | | , mValue(0.0f) |
105 | | , mVal(nullptr) |
106 | 0 | { |
107 | 0 | // These shifts are in sync with the members in the header. |
108 | 0 | MOZ_ASSERT(aList && |
109 | 0 | aAttrEnum < (1 << 4) && |
110 | 0 | aListIndex <= MaxListIndex(), |
111 | 0 | "bad arg"); |
112 | 0 |
|
113 | 0 | MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!"); |
114 | 0 | } |
115 | | |
116 | | DOMSVGLength::DOMSVGLength() |
117 | | : mList(nullptr) |
118 | | , mListIndex(0) |
119 | | , mAttrEnum(0) |
120 | | , mIsAnimValItem(false) |
121 | | , mUnit(SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) |
122 | | , mValue(0.0f) |
123 | | , mVal(nullptr) |
124 | 0 | { |
125 | 0 | } |
126 | | |
127 | | DOMSVGLength::DOMSVGLength(nsSVGLength2* aVal, nsSVGElement* aSVGElement, |
128 | | bool aAnimVal) |
129 | | : mList(nullptr) |
130 | | , mListIndex(0) |
131 | | , mAttrEnum(0) |
132 | | , mIsAnimValItem(aAnimVal) |
133 | | , mUnit(SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) |
134 | | , mValue(0.0f) |
135 | | , mVal(aVal) |
136 | | , mSVGElement(aSVGElement) |
137 | 0 | { |
138 | 0 | } |
139 | | |
140 | | void |
141 | | DOMSVGLength::CleanupWeakRefs() |
142 | 0 | { |
143 | 0 | // Our mList's weak ref to us must be nulled out when we die (or when we're |
144 | 0 | // cycle collected), so we that don't leave behind a pointer to |
145 | 0 | // free / soon-to-be-free memory. |
146 | 0 | if (mList) { |
147 | 0 | MOZ_ASSERT(mList->mItems[mListIndex] == this, |
148 | 0 | "Clearing out the wrong list index...?"); |
149 | 0 | mList->mItems[mListIndex] = nullptr; |
150 | 0 | } |
151 | 0 |
|
152 | 0 | // Similarly, we must update the tearoff table to remove its (non-owning) |
153 | 0 | // pointer to mVal. |
154 | 0 | if (mVal) { |
155 | 0 | auto& table = mIsAnimValItem ? |
156 | 0 | sAnimSVGLengthTearOffTable : sBaseSVGLengthTearOffTable; |
157 | 0 | table.RemoveTearoff(mVal); |
158 | 0 | } |
159 | 0 | } |
160 | | |
161 | | DOMSVGLength::~DOMSVGLength() |
162 | 0 | { |
163 | 0 | CleanupWeakRefs(); |
164 | 0 | } |
165 | | |
166 | | already_AddRefed<DOMSVGLength> |
167 | | DOMSVGLength::GetTearOff(nsSVGLength2* aVal, nsSVGElement* aSVGElement, |
168 | | bool aAnimVal) |
169 | 0 | { |
170 | 0 | auto& table = aAnimVal ? sAnimSVGLengthTearOffTable : sBaseSVGLengthTearOffTable; |
171 | 0 | RefPtr<DOMSVGLength> domLength = table.GetTearoff(aVal); |
172 | 0 | if (!domLength) { |
173 | 0 | domLength = new DOMSVGLength(aVal, aSVGElement, aAnimVal); |
174 | 0 | table.AddTearoff(aVal, domLength); |
175 | 0 | } |
176 | 0 |
|
177 | 0 | return domLength.forget(); |
178 | 0 | } |
179 | | |
180 | | DOMSVGLength* |
181 | | DOMSVGLength::Copy() |
182 | 0 | { |
183 | 0 | NS_ASSERTION(HasOwner() || IsReflectingAttribute(), "unexpected caller"); |
184 | 0 | DOMSVGLength *copy = new DOMSVGLength(); |
185 | 0 | uint16_t unit; |
186 | 0 | float value; |
187 | 0 | if (mVal) { |
188 | 0 | unit = mVal->mSpecifiedUnitType; |
189 | 0 | value = mIsAnimValItem ? mVal->mAnimVal : mVal->mBaseVal; |
190 | 0 | } else { |
191 | 0 | SVGLength &length = InternalItem(); |
192 | 0 | unit = length.GetUnit(); |
193 | 0 | value = length.GetValueInCurrentUnits(); |
194 | 0 | } |
195 | 0 | copy->NewValueSpecifiedUnits(unit, value, IgnoreErrors()); |
196 | 0 | return copy; |
197 | 0 | } |
198 | | |
199 | | uint16_t |
200 | | DOMSVGLength::UnitType() |
201 | 0 | { |
202 | 0 | if (mVal) { |
203 | 0 | if (mIsAnimValItem) { |
204 | 0 | mSVGElement->FlushAnimations(); |
205 | 0 | } |
206 | 0 | return mVal->mSpecifiedUnitType; |
207 | 0 | } |
208 | 0 |
|
209 | 0 | if (mIsAnimValItem && HasOwner()) { |
210 | 0 | Element()->FlushAnimations(); // May make HasOwner() == false |
211 | 0 | } |
212 | 0 | return HasOwner() ? InternalItem().GetUnit() : mUnit; |
213 | 0 | } |
214 | | |
215 | | float |
216 | | DOMSVGLength::GetValue(ErrorResult& aRv) |
217 | 0 | { |
218 | 0 | if (mVal) { |
219 | 0 | if (mIsAnimValItem) { |
220 | 0 | mSVGElement->FlushAnimations(); |
221 | 0 | return mVal->GetAnimValue(mSVGElement); |
222 | 0 | } |
223 | 0 | return mVal->GetBaseValue(mSVGElement); |
224 | 0 | } |
225 | 0 | |
226 | 0 | if (mIsAnimValItem && HasOwner()) { |
227 | 0 | Element()->FlushAnimations(); // May make HasOwner() == false |
228 | 0 | } |
229 | 0 | if (HasOwner()) { |
230 | 0 | float value = InternalItem().GetValueInUserUnits(Element(), Axis()); |
231 | 0 | if (!IsFinite(value)) { |
232 | 0 | aRv.Throw(NS_ERROR_FAILURE); |
233 | 0 | } |
234 | 0 | return value; |
235 | 0 | } else if (mUnit == SVGLength_Binding::SVG_LENGTHTYPE_NUMBER || |
236 | 0 | mUnit == SVGLength_Binding::SVG_LENGTHTYPE_PX) { |
237 | 0 | return mValue; |
238 | 0 | } |
239 | 0 | // else [SVGWG issue] Can't convert this length's value to user units |
240 | 0 | // ReportToConsole |
241 | 0 | aRv.Throw(NS_ERROR_FAILURE); |
242 | 0 | return 0.0f; |
243 | 0 | } |
244 | | |
245 | | void |
246 | | DOMSVGLength::SetValue(float aUserUnitValue, ErrorResult& aRv) |
247 | 0 | { |
248 | 0 | if (mIsAnimValItem) { |
249 | 0 | aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); |
250 | 0 | return; |
251 | 0 | } |
252 | 0 | |
253 | 0 | if (mVal) { |
254 | 0 | aRv = mVal->SetBaseValue(aUserUnitValue, mSVGElement, true); |
255 | 0 | return; |
256 | 0 | } |
257 | 0 | |
258 | 0 | // Although the value passed in is in user units, this method does not turn |
259 | 0 | // this length into a user unit length. Instead it converts the user unit |
260 | 0 | // value to this length's current unit and sets that, leaving this length's |
261 | 0 | // unit as it is. |
262 | 0 | |
263 | 0 | if (HasOwner()) { |
264 | 0 | if (InternalItem().GetValueInUserUnits(Element(), Axis()) == |
265 | 0 | aUserUnitValue) { |
266 | 0 | return; |
267 | 0 | } |
268 | 0 | float uuPerUnit = InternalItem().GetUserUnitsPerUnit(Element(), Axis()); |
269 | 0 | if (uuPerUnit > 0) { |
270 | 0 | float newValue = aUserUnitValue / uuPerUnit; |
271 | 0 | if (IsFinite(newValue)) { |
272 | 0 | AutoChangeLengthNotifier notifier(this); |
273 | 0 | InternalItem().SetValueAndUnit(newValue, InternalItem().GetUnit()); |
274 | 0 | return; |
275 | 0 | } |
276 | 0 | } |
277 | 0 | } else if (mUnit == SVGLength_Binding::SVG_LENGTHTYPE_NUMBER || |
278 | 0 | mUnit == SVGLength_Binding::SVG_LENGTHTYPE_PX) { |
279 | 0 | mValue = aUserUnitValue; |
280 | 0 | return; |
281 | 0 | } |
282 | 0 | // else [SVGWG issue] Can't convert user unit value to this length's unit |
283 | 0 | // ReportToConsole |
284 | 0 | aRv.Throw(NS_ERROR_FAILURE); |
285 | 0 | } |
286 | | |
287 | | float |
288 | | DOMSVGLength::ValueInSpecifiedUnits() |
289 | 0 | { |
290 | 0 | if (mVal) { |
291 | 0 | if (mIsAnimValItem) { |
292 | 0 | mSVGElement->FlushAnimations(); |
293 | 0 | return mVal->mAnimVal; |
294 | 0 | } |
295 | 0 | return mVal->mBaseVal; |
296 | 0 | } |
297 | 0 | |
298 | 0 | if (mIsAnimValItem && HasOwner()) { |
299 | 0 | Element()->FlushAnimations(); // May make HasOwner() == false |
300 | 0 | } |
301 | 0 | return HasOwner() ? InternalItem().GetValueInCurrentUnits() : mValue; |
302 | 0 | } |
303 | | |
304 | | void |
305 | | DOMSVGLength::SetValueInSpecifiedUnits(float aValue, ErrorResult& aRv) |
306 | 0 | { |
307 | 0 | if (mIsAnimValItem) { |
308 | 0 | aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); |
309 | 0 | return; |
310 | 0 | } |
311 | 0 | |
312 | 0 | if (mVal) { |
313 | 0 | mVal->SetBaseValueInSpecifiedUnits(aValue, mSVGElement, true); |
314 | 0 | return; |
315 | 0 | } |
316 | 0 | |
317 | 0 | if (HasOwner()) { |
318 | 0 | if (InternalItem().GetValueInCurrentUnits() == aValue) { |
319 | 0 | return; |
320 | 0 | } |
321 | 0 | AutoChangeLengthNotifier notifier(this); |
322 | 0 | InternalItem().SetValueInCurrentUnits(aValue); |
323 | 0 | return; |
324 | 0 | } |
325 | 0 | mValue = aValue; |
326 | 0 | } |
327 | | |
328 | | void |
329 | | DOMSVGLength::SetValueAsString(const nsAString& aValue, ErrorResult& aRv) |
330 | 0 | { |
331 | 0 | if (mIsAnimValItem) { |
332 | 0 | aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); |
333 | 0 | return; |
334 | 0 | } |
335 | 0 | |
336 | 0 | if (mVal) { |
337 | 0 | aRv = mVal->SetBaseValueString(aValue, mSVGElement, true); |
338 | 0 | return; |
339 | 0 | } |
340 | 0 | |
341 | 0 | SVGLength value; |
342 | 0 | if (!value.SetValueFromString(aValue)) { |
343 | 0 | aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); |
344 | 0 | return; |
345 | 0 | } |
346 | 0 | if (HasOwner()) { |
347 | 0 | if (InternalItem() == value) { |
348 | 0 | return; |
349 | 0 | } |
350 | 0 | AutoChangeLengthNotifier notifier(this); |
351 | 0 | InternalItem() = value; |
352 | 0 | return; |
353 | 0 | } |
354 | 0 | mValue = value.GetValueInCurrentUnits(); |
355 | 0 | mUnit = value.GetUnit(); |
356 | 0 | } |
357 | | |
358 | | void |
359 | | DOMSVGLength::GetValueAsString(nsAString& aValue) |
360 | 0 | { |
361 | 0 | if (mVal) { |
362 | 0 | if (mIsAnimValItem) { |
363 | 0 | mSVGElement->FlushAnimations(); |
364 | 0 | mVal->GetAnimValueString(aValue); |
365 | 0 | } else { |
366 | 0 | mVal->GetBaseValueString(aValue); |
367 | 0 | } |
368 | 0 | return; |
369 | 0 | } |
370 | 0 |
|
371 | 0 | if (mIsAnimValItem && HasOwner()) { |
372 | 0 | Element()->FlushAnimations(); // May make HasOwner() == false |
373 | 0 | } |
374 | 0 | if (HasOwner()) { |
375 | 0 | InternalItem().GetValueAsString(aValue); |
376 | 0 | return; |
377 | 0 | } |
378 | 0 | SVGLength(mValue, mUnit).GetValueAsString(aValue); |
379 | 0 | } |
380 | | |
381 | | void |
382 | | DOMSVGLength::NewValueSpecifiedUnits(uint16_t aUnit, float aValue, |
383 | | ErrorResult& aRv) |
384 | 0 | { |
385 | 0 | if (mIsAnimValItem) { |
386 | 0 | aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); |
387 | 0 | return; |
388 | 0 | } |
389 | 0 | |
390 | 0 | if (mVal) { |
391 | 0 | mVal->NewValueSpecifiedUnits(aUnit, aValue, mSVGElement); |
392 | 0 | return; |
393 | 0 | } |
394 | 0 | |
395 | 0 | if (!SVGLength::IsValidUnitType(aUnit)) { |
396 | 0 | aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); |
397 | 0 | return; |
398 | 0 | } |
399 | 0 | if (HasOwner()) { |
400 | 0 | if (InternalItem().GetUnit() == aUnit && |
401 | 0 | InternalItem().GetValueInCurrentUnits() == aValue) { |
402 | 0 | return; |
403 | 0 | } |
404 | 0 | AutoChangeLengthNotifier notifier(this); |
405 | 0 | InternalItem().SetValueAndUnit(aValue, uint8_t(aUnit)); |
406 | 0 | return; |
407 | 0 | } |
408 | 0 | mUnit = uint8_t(aUnit); |
409 | 0 | mValue = aValue; |
410 | 0 | } |
411 | | |
412 | | void |
413 | | DOMSVGLength::ConvertToSpecifiedUnits(uint16_t aUnit, ErrorResult& aRv) |
414 | 0 | { |
415 | 0 | if (mIsAnimValItem) { |
416 | 0 | aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); |
417 | 0 | return; |
418 | 0 | } |
419 | 0 | |
420 | 0 | if (mVal) { |
421 | 0 | mVal->ConvertToSpecifiedUnits(aUnit, mSVGElement); |
422 | 0 | return; |
423 | 0 | } |
424 | 0 | |
425 | 0 | if (!SVGLength::IsValidUnitType(aUnit)) { |
426 | 0 | aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); |
427 | 0 | return; |
428 | 0 | } |
429 | 0 | if (HasOwner()) { |
430 | 0 | if (InternalItem().GetUnit() == aUnit) { |
431 | 0 | return; |
432 | 0 | } |
433 | 0 | float val = InternalItem().GetValueInSpecifiedUnit( |
434 | 0 | aUnit, Element(), Axis()); |
435 | 0 | if (IsFinite(val)) { |
436 | 0 | AutoChangeLengthNotifier notifier(this); |
437 | 0 | InternalItem().SetValueAndUnit(val, aUnit); |
438 | 0 | return; |
439 | 0 | } |
440 | 0 | } else { |
441 | 0 | SVGLength len(mValue, mUnit); |
442 | 0 | float val = len.GetValueInSpecifiedUnit(aUnit, nullptr, 0); |
443 | 0 | if (IsFinite(val)) { |
444 | 0 | mValue = val; |
445 | 0 | mUnit = aUnit; |
446 | 0 | return; |
447 | 0 | } |
448 | 0 | } |
449 | 0 | // else [SVGWG issue] Can't convert unit |
450 | 0 | // ReportToConsole |
451 | 0 | aRv.Throw(NS_ERROR_FAILURE); |
452 | 0 | } |
453 | | |
454 | | JSObject* |
455 | | DOMSVGLength::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) |
456 | 0 | { |
457 | 0 | return SVGLength_Binding::Wrap(aCx, this, aGivenProto); |
458 | 0 | } |
459 | | |
460 | | void |
461 | | DOMSVGLength::InsertingIntoList(DOMSVGLengthList *aList, |
462 | | uint8_t aAttrEnum, |
463 | | uint32_t aListIndex, |
464 | | bool aIsAnimValItem) |
465 | 0 | { |
466 | 0 | NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list"); |
467 | 0 |
|
468 | 0 | mList = aList; |
469 | 0 | mAttrEnum = aAttrEnum; |
470 | 0 | mListIndex = aListIndex; |
471 | 0 | mIsAnimValItem = aIsAnimValItem; |
472 | 0 |
|
473 | 0 | MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGLength!"); |
474 | 0 | } |
475 | | |
476 | | void |
477 | | DOMSVGLength::RemovingFromList() |
478 | 0 | { |
479 | 0 | mValue = InternalItem().GetValueInCurrentUnits(); |
480 | 0 | mUnit = InternalItem().GetUnit(); |
481 | 0 | mList = nullptr; |
482 | 0 | mIsAnimValItem = false; |
483 | 0 | } |
484 | | |
485 | | SVGLength |
486 | | DOMSVGLength::ToSVGLength() |
487 | 0 | { |
488 | 0 | if (HasOwner()) { |
489 | 0 | return SVGLength(InternalItem().GetValueInCurrentUnits(), |
490 | 0 | InternalItem().GetUnit()); |
491 | 0 | } |
492 | 0 | return SVGLength(mValue, mUnit); |
493 | 0 | } |
494 | | |
495 | | SVGLength& |
496 | | DOMSVGLength::InternalItem() |
497 | 0 | { |
498 | 0 | SVGAnimatedLengthList *alist = Element()->GetAnimatedLengthList(mAttrEnum); |
499 | 0 | return mIsAnimValItem && alist->mAnimVal ? |
500 | 0 | (*alist->mAnimVal)[mListIndex] : |
501 | 0 | alist->mBaseVal[mListIndex]; |
502 | 0 | } |
503 | | |
504 | | #ifdef DEBUG |
505 | | bool |
506 | | DOMSVGLength::IndexIsValid() |
507 | | { |
508 | | SVGAnimatedLengthList *alist = Element()->GetAnimatedLengthList(mAttrEnum); |
509 | | return (mIsAnimValItem && |
510 | | mListIndex < alist->GetAnimValue().Length()) || |
511 | | (!mIsAnimValItem && |
512 | | mListIndex < alist->GetBaseValue().Length()); |
513 | | } |
514 | | #endif |
515 | | |
516 | | } // namespace mozilla |