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 "nsSVGInteger.h"
10 #include "nsSMILValue.h"
11 #include "SMILIntegerType.h"
12 #include "SVGContentUtils.h"
13
14 using namespace mozilla;
15 using namespace mozilla::dom;
16
17 /* Implementation */
18
19 static nsSVGAttrTearoffTable<nsSVGInteger, nsSVGInteger::DOMAnimatedInteger>
20 sSVGAnimatedIntegerTearoffTable;
21
22 nsresult
SetBaseValueString(const nsAString & aValueAsString,nsSVGElement * aSVGElement)23 nsSVGInteger::SetBaseValueString(const nsAString &aValueAsString,
24 nsSVGElement *aSVGElement)
25 {
26 int32_t value;
27
28 if (!SVGContentUtils::ParseInteger(aValueAsString, value)) {
29 return NS_ERROR_DOM_SYNTAX_ERR;
30 }
31
32 mIsBaseSet = true;
33 mBaseVal = value;
34 if (!mIsAnimated) {
35 mAnimVal = mBaseVal;
36 }
37 else {
38 aSVGElement->AnimationNeedsResample();
39 }
40 return NS_OK;
41 }
42
43 void
GetBaseValueString(nsAString & aValueAsString)44 nsSVGInteger::GetBaseValueString(nsAString & aValueAsString)
45 {
46 aValueAsString.Truncate();
47 aValueAsString.AppendInt(mBaseVal);
48 }
49
50 void
SetBaseValue(int aValue,nsSVGElement * aSVGElement)51 nsSVGInteger::SetBaseValue(int aValue, nsSVGElement *aSVGElement)
52 {
53 // We can't just rely on SetParsedAttrValue (as called by DidChangeInteger)
54 // detecting redundant changes since it will compare false if the existing
55 // attribute value has an associated serialized version (a string value) even
56 // if the integers match due to the way integers are stored in nsAttrValue.
57 if (aValue == mBaseVal && mIsBaseSet) {
58 return;
59 }
60
61 mBaseVal = aValue;
62 mIsBaseSet = true;
63 if (!mIsAnimated) {
64 mAnimVal = mBaseVal;
65 }
66 else {
67 aSVGElement->AnimationNeedsResample();
68 }
69 aSVGElement->DidChangeInteger(mAttrEnum);
70 }
71
72 void
SetAnimValue(int aValue,nsSVGElement * aSVGElement)73 nsSVGInteger::SetAnimValue(int aValue, nsSVGElement *aSVGElement)
74 {
75 if (mIsAnimated && aValue == mAnimVal) {
76 return;
77 }
78 mAnimVal = aValue;
79 mIsAnimated = true;
80 aSVGElement->DidAnimateInteger(mAttrEnum);
81 }
82
83 already_AddRefed<SVGAnimatedInteger>
ToDOMAnimatedInteger(nsSVGElement * aSVGElement)84 nsSVGInteger::ToDOMAnimatedInteger(nsSVGElement *aSVGElement)
85 {
86 RefPtr<DOMAnimatedInteger> domAnimatedInteger =
87 sSVGAnimatedIntegerTearoffTable.GetTearoff(this);
88 if (!domAnimatedInteger) {
89 domAnimatedInteger = new DOMAnimatedInteger(this, aSVGElement);
90 sSVGAnimatedIntegerTearoffTable.AddTearoff(this, domAnimatedInteger);
91 }
92
93 return domAnimatedInteger.forget();
94 }
95
~DOMAnimatedInteger()96 nsSVGInteger::DOMAnimatedInteger::~DOMAnimatedInteger()
97 {
98 sSVGAnimatedIntegerTearoffTable.RemoveTearoff(mVal);
99 }
100
101 nsISMILAttr*
ToSMILAttr(nsSVGElement * aSVGElement)102 nsSVGInteger::ToSMILAttr(nsSVGElement *aSVGElement)
103 {
104 return new SMILInteger(this, aSVGElement);
105 }
106
107 nsresult
ValueFromString(const nsAString & aStr,const dom::SVGAnimationElement *,nsSMILValue & aValue,bool & aPreventCachingOfSandwich) const108 nsSVGInteger::SMILInteger::ValueFromString(const nsAString& aStr,
109 const dom::SVGAnimationElement* /*aSrcElement*/,
110 nsSMILValue& aValue,
111 bool& aPreventCachingOfSandwich) const
112 {
113 int32_t val;
114
115 if (!SVGContentUtils::ParseInteger(aStr, val)) {
116 return NS_ERROR_DOM_SYNTAX_ERR;
117 }
118
119 nsSMILValue smilVal(SMILIntegerType::Singleton());
120 smilVal.mU.mInt = val;
121 aValue = smilVal;
122 aPreventCachingOfSandwich = false;
123 return NS_OK;
124 }
125
126 nsSMILValue
GetBaseValue() const127 nsSVGInteger::SMILInteger::GetBaseValue() const
128 {
129 nsSMILValue val(SMILIntegerType::Singleton());
130 val.mU.mInt = mVal->mBaseVal;
131 return val;
132 }
133
134 void
ClearAnimValue()135 nsSVGInteger::SMILInteger::ClearAnimValue()
136 {
137 if (mVal->mIsAnimated) {
138 mVal->mIsAnimated = false;
139 mVal->mAnimVal = mVal->mBaseVal;
140 mSVGElement->DidAnimateInteger(mVal->mAttrEnum);
141 }
142 }
143
144 nsresult
SetAnimValue(const nsSMILValue & aValue)145 nsSVGInteger::SMILInteger::SetAnimValue(const nsSMILValue& aValue)
146 {
147 NS_ASSERTION(aValue.mType == SMILIntegerType::Singleton(),
148 "Unexpected type to assign animated value");
149 if (aValue.mType == SMILIntegerType::Singleton()) {
150 mVal->SetAnimValue(int(aValue.mU.mInt), mSVGElement);
151 }
152 return NS_OK;
153 }
154