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