Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/svg/DOMSVGNumber.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 "DOMSVGNumber.h"
8
#include "DOMSVGNumberList.h"
9
#include "DOMSVGAnimatedNumberList.h"
10
#include "SVGAnimatedNumberList.h"
11
#include "nsSVGElement.h"
12
#include "nsError.h"
13
#include "nsContentUtils.h" // for NS_ENSURE_FINITE
14
#include "mozilla/dom/SVGNumberBinding.h"
15
16
// See the architecture comment in DOMSVGAnimatedNumberList.h.
17
18
namespace mozilla {
19
20
// We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
21
// clear our list's weak ref to us to be safe. (The other option would be to
22
// not unlink and rely on the breaking of the other edges in the cycle, as
23
// NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
24
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumber)
25
26
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumber)
27
0
  // We may not belong to a list, so we must null check tmp->mList.
28
0
  if (tmp->mList) {
29
0
    tmp->mList->mItems[tmp->mListIndex] = nullptr;
30
0
  }
31
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
32
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
33
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
34
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
35
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumber)
36
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
37
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
38
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
39
0
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGNumber)
40
0
  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
41
0
NS_IMPL_CYCLE_COLLECTION_TRACE_END
42
43
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGNumber)
44
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGNumber)
45
46
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGNumber)
47
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
48
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
49
0
NS_INTERFACE_MAP_END
50
51
//----------------------------------------------------------------------
52
// Helper class: AutoChangeNumberNotifier
53
// Stack-based helper class to pair calls to WillChangeNumberList and
54
// DidChangeNumberList.
55
class MOZ_RAII AutoChangeNumberNotifier
56
{
57
public:
58
  explicit AutoChangeNumberNotifier(DOMSVGNumber* aNumber MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
59
    : mNumber(aNumber)
60
0
  {
61
0
    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
62
0
    MOZ_ASSERT(mNumber, "Expecting non-null number");
63
0
    MOZ_ASSERT(mNumber->HasOwner(),
64
0
               "Expecting list to have an owner for notification");
65
0
    mEmptyOrOldValue =
66
0
      mNumber->Element()->WillChangeNumberList(mNumber->mAttrEnum);
67
0
  }
68
69
  ~AutoChangeNumberNotifier()
70
0
  {
71
0
    mNumber->Element()->DidChangeNumberList(mNumber->mAttrEnum,
72
0
                                            mEmptyOrOldValue);
73
0
    if (mNumber->mList->IsAnimating()) {
74
0
      mNumber->Element()->AnimationNeedsResample();
75
0
    }
76
0
  }
77
78
private:
79
  DOMSVGNumber* const mNumber;
80
  nsAttrValue   mEmptyOrOldValue;
81
  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
82
};
83
84
DOMSVGNumber::DOMSVGNumber(DOMSVGNumberList *aList,
85
                           uint8_t aAttrEnum,
86
                           uint32_t aListIndex,
87
                           bool aIsAnimValItem)
88
  : mList(aList)
89
  , mParent(aList)
90
  , mListIndex(aListIndex)
91
  , mAttrEnum(aAttrEnum)
92
  , mIsAnimValItem(aIsAnimValItem)
93
  , mValue(0.0f)
94
0
{
95
0
  // These shifts are in sync with the members in the header.
96
0
  MOZ_ASSERT(aList &&
97
0
             aAttrEnum < (1 << 4) &&
98
0
             aListIndex <= MaxListIndex(),
99
0
             "bad arg");
100
0
101
0
  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!");
102
0
}
103
104
DOMSVGNumber::DOMSVGNumber(nsISupports* aParent)
105
  : mList(nullptr)
106
  , mParent(aParent)
107
  , mListIndex(0)
108
  , mAttrEnum(0)
109
  , mIsAnimValItem(false)
110
  , mValue(0.0f)
111
0
{
112
0
}
113
114
float
115
DOMSVGNumber::Value()
116
0
{
117
0
  if (mIsAnimValItem && HasOwner()) {
118
0
    Element()->FlushAnimations(); // May make HasOwner() == false
119
0
  }
120
0
  return HasOwner() ? InternalItem() : mValue;
121
0
}
122
123
void
124
DOMSVGNumber::SetValue(float aValue, ErrorResult& aRv)
125
0
{
126
0
  if (mIsAnimValItem) {
127
0
    aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
128
0
    return;
129
0
  }
130
0
131
0
  if (HasOwner()) {
132
0
    if (InternalItem() == aValue) {
133
0
      return;
134
0
    }
135
0
    AutoChangeNumberNotifier notifier(this);
136
0
    InternalItem() = aValue;
137
0
    return;
138
0
  }
139
0
140
0
  mValue = aValue;
141
0
}
142
143
void
144
DOMSVGNumber::InsertingIntoList(DOMSVGNumberList *aList,
145
                                uint8_t aAttrEnum,
146
                                uint32_t aListIndex,
147
                                bool aIsAnimValItem)
148
0
{
149
0
  NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list");
150
0
151
0
  mList = aList;
152
0
  mAttrEnum = aAttrEnum;
153
0
  mListIndex = aListIndex;
154
0
  mIsAnimValItem = aIsAnimValItem;
155
0
156
0
  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!");
157
0
}
158
159
void
160
DOMSVGNumber::RemovingFromList()
161
0
{
162
0
  mValue = InternalItem();
163
0
  mList = nullptr;
164
0
  mIsAnimValItem = false;
165
0
}
166
167
float
168
DOMSVGNumber::ToSVGNumber()
169
0
{
170
0
  return HasOwner() ? InternalItem() : mValue;
171
0
}
172
173
float&
174
DOMSVGNumber::InternalItem()
175
0
{
176
0
  SVGAnimatedNumberList *alist = Element()->GetAnimatedNumberList(mAttrEnum);
177
0
  return mIsAnimValItem && alist->mAnimVal ?
178
0
    (*alist->mAnimVal)[mListIndex] :
179
0
    alist->mBaseVal[mListIndex];
180
0
}
181
182
#ifdef DEBUG
183
bool
184
DOMSVGNumber::IndexIsValid()
185
{
186
  SVGAnimatedNumberList *alist = Element()->GetAnimatedNumberList(mAttrEnum);
187
  return (mIsAnimValItem &&
188
          mListIndex < alist->GetAnimValue().Length()) ||
189
         (!mIsAnimValItem &&
190
          mListIndex < alist->GetBaseValue().Length());
191
}
192
#endif
193
194
JSObject*
195
DOMSVGNumber::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
196
0
{
197
0
  return dom::SVGNumber_Binding::Wrap(aCx, this, aGivenProto);
198
0
}
199
200
} // namespace mozilla