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