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 "nsError.h"
8 : #include "nsSVGAttrTearoffTable.h"
9 : #include "nsSVGEnum.h"
10 : #include "nsIAtom.h"
11 : #include "nsSVGElement.h"
12 : #include "nsSMILValue.h"
13 : #include "SMILEnumType.h"
14 :
15 : using namespace mozilla;
16 : using namespace mozilla::dom;
17 :
18 : static nsSVGAttrTearoffTable<nsSVGEnum, nsSVGEnum::DOMAnimatedEnum>
19 3 : sSVGAnimatedEnumTearoffTable;
20 :
21 : nsSVGEnumMapping *
22 6 : nsSVGEnum::GetMapping(nsSVGElement *aSVGElement)
23 : {
24 6 : nsSVGElement::EnumAttributesInfo info = aSVGElement->GetEnumInfo();
25 :
26 6 : NS_ASSERTION(info.mEnumCount > 0 && mAttrEnum < info.mEnumCount,
27 : "mapping request for a non-attrib enum");
28 :
29 6 : return info.mEnumInfo[mAttrEnum].mMapping;
30 : }
31 :
32 : nsresult
33 6 : nsSVGEnum::SetBaseValueAtom(const nsIAtom* aValue, nsSVGElement *aSVGElement)
34 : {
35 6 : nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
36 :
37 18 : while (mapping && mapping->mKey) {
38 12 : if (aValue == *(mapping->mKey)) {
39 6 : mIsBaseSet = true;
40 6 : if (mBaseVal != mapping->mVal) {
41 6 : mBaseVal = mapping->mVal;
42 6 : if (!mIsAnimated) {
43 6 : mAnimVal = mBaseVal;
44 : }
45 : else {
46 0 : aSVGElement->AnimationNeedsResample();
47 : }
48 : // We don't need to call DidChange* here - we're only called by
49 : // nsSVGElement::ParseAttribute under Element::SetAttr,
50 : // which takes care of notifying.
51 : }
52 6 : return NS_OK;
53 : }
54 6 : mapping++;
55 : }
56 :
57 : // only a warning since authors may mistype attribute values
58 0 : NS_WARNING("unknown enumeration key");
59 0 : return NS_ERROR_DOM_SYNTAX_ERR;
60 : }
61 :
62 : nsIAtom*
63 0 : nsSVGEnum::GetBaseValueAtom(nsSVGElement *aSVGElement)
64 : {
65 0 : nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
66 :
67 0 : while (mapping && mapping->mKey) {
68 0 : if (mBaseVal == mapping->mVal) {
69 0 : return *mapping->mKey;
70 : }
71 0 : mapping++;
72 : }
73 0 : NS_ERROR("unknown enumeration value");
74 0 : return nsGkAtoms::_empty;
75 : }
76 :
77 : nsresult
78 0 : nsSVGEnum::SetBaseValue(uint16_t aValue,
79 : nsSVGElement *aSVGElement)
80 : {
81 0 : nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
82 :
83 0 : while (mapping && mapping->mKey) {
84 0 : if (mapping->mVal == aValue) {
85 0 : mIsBaseSet = true;
86 0 : if (mBaseVal != uint8_t(aValue)) {
87 0 : mBaseVal = uint8_t(aValue);
88 0 : if (!mIsAnimated) {
89 0 : mAnimVal = mBaseVal;
90 : }
91 : else {
92 0 : aSVGElement->AnimationNeedsResample();
93 : }
94 0 : aSVGElement->DidChangeEnum(mAttrEnum);
95 : }
96 0 : return NS_OK;
97 : }
98 0 : mapping++;
99 : }
100 0 : return NS_ERROR_DOM_SYNTAX_ERR;
101 : }
102 :
103 : void
104 0 : nsSVGEnum::SetAnimValue(uint16_t aValue, nsSVGElement *aSVGElement)
105 : {
106 0 : if (mIsAnimated && aValue == mAnimVal) {
107 0 : return;
108 : }
109 0 : mAnimVal = aValue;
110 0 : mIsAnimated = true;
111 0 : aSVGElement->DidAnimateEnum(mAttrEnum);
112 : }
113 :
114 : already_AddRefed<SVGAnimatedEnumeration>
115 0 : nsSVGEnum::ToDOMAnimatedEnum(nsSVGElement* aSVGElement)
116 : {
117 : RefPtr<DOMAnimatedEnum> domAnimatedEnum =
118 0 : sSVGAnimatedEnumTearoffTable.GetTearoff(this);
119 0 : if (!domAnimatedEnum) {
120 0 : domAnimatedEnum = new DOMAnimatedEnum(this, aSVGElement);
121 0 : sSVGAnimatedEnumTearoffTable.AddTearoff(this, domAnimatedEnum);
122 : }
123 :
124 0 : return domAnimatedEnum.forget();
125 : }
126 :
127 0 : nsSVGEnum::DOMAnimatedEnum::~DOMAnimatedEnum()
128 : {
129 0 : sSVGAnimatedEnumTearoffTable.RemoveTearoff(mVal);
130 0 : }
131 :
132 : UniquePtr<nsISMILAttr>
133 0 : nsSVGEnum::ToSMILAttr(nsSVGElement *aSVGElement)
134 : {
135 0 : return MakeUnique<SMILEnum>(this, aSVGElement);
136 : }
137 :
138 : nsresult
139 0 : nsSVGEnum::SMILEnum::ValueFromString(const nsAString& aStr,
140 : const dom::SVGAnimationElement* /*aSrcElement*/,
141 : nsSMILValue& aValue,
142 : bool& aPreventCachingOfSandwich) const
143 : {
144 0 : nsIAtom *valAtom = NS_GetStaticAtom(aStr);
145 0 : if (valAtom) {
146 0 : nsSVGEnumMapping *mapping = mVal->GetMapping(mSVGElement);
147 :
148 0 : while (mapping && mapping->mKey) {
149 0 : if (valAtom == *(mapping->mKey)) {
150 0 : nsSMILValue val(SMILEnumType::Singleton());
151 0 : val.mU.mUint = mapping->mVal;
152 0 : aValue = val;
153 0 : aPreventCachingOfSandwich = false;
154 0 : return NS_OK;
155 : }
156 0 : mapping++;
157 : }
158 : }
159 :
160 : // only a warning since authors may mistype attribute values
161 0 : NS_WARNING("unknown enumeration key");
162 0 : return NS_ERROR_FAILURE;
163 : }
164 :
165 : nsSMILValue
166 0 : nsSVGEnum::SMILEnum::GetBaseValue() const
167 : {
168 0 : nsSMILValue val(SMILEnumType::Singleton());
169 0 : val.mU.mUint = mVal->mBaseVal;
170 0 : return val;
171 : }
172 :
173 : void
174 0 : nsSVGEnum::SMILEnum::ClearAnimValue()
175 : {
176 0 : if (mVal->mIsAnimated) {
177 0 : mVal->mIsAnimated = false;
178 0 : mVal->mAnimVal = mVal->mBaseVal;
179 0 : mSVGElement->DidAnimateEnum(mVal->mAttrEnum);
180 : }
181 0 : }
182 :
183 : nsresult
184 0 : nsSVGEnum::SMILEnum::SetAnimValue(const nsSMILValue& aValue)
185 : {
186 0 : NS_ASSERTION(aValue.mType == SMILEnumType::Singleton(),
187 : "Unexpected type to assign animated value");
188 0 : if (aValue.mType == SMILEnumType::Singleton()) {
189 0 : MOZ_ASSERT(aValue.mU.mUint <= USHRT_MAX,
190 : "Very large enumerated value - too big for uint16_t");
191 0 : mVal->SetAnimValue(uint16_t(aValue.mU.mUint), mSVGElement);
192 : }
193 0 : return NS_OK;
194 : }
|