Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / svg / SVGAnimatedInteger.cpp
blobb14a32ce1c8c8eddbef805dbadc65492f79b04b1
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/. */
7 #include "SVGAnimatedInteger.h"
9 #include "nsError.h"
10 #include "SMILIntegerType.h"
11 #include "SVGAttrTearoffTable.h"
12 #include "mozilla/SMILValue.h"
13 #include "mozilla/SVGContentUtils.h"
15 using namespace mozilla::dom;
17 namespace mozilla {
19 /* Implementation */
21 //----------------------------------------------------------------------
22 // Helper class: AutoChangeIntegerNotifier
23 // Stack-based helper class ensure DidChangeInteger is called.
24 class MOZ_RAII AutoChangeIntegerNotifier {
25 public:
26 AutoChangeIntegerNotifier(SVGAnimatedInteger* aInteger,
27 SVGElement* aSVGElement, bool aDoSetAttr = true)
28 : mInteger(aInteger), mSVGElement(aSVGElement), mDoSetAttr(aDoSetAttr) {
29 MOZ_ASSERT(mInteger, "Expecting non-null integer");
30 MOZ_ASSERT(mSVGElement, "Expecting non-null element");
33 ~AutoChangeIntegerNotifier() {
34 if (mDoSetAttr) {
35 mSVGElement->DidChangeInteger(mInteger->mAttrEnum);
37 if (mInteger->mIsAnimated) {
38 mSVGElement->AnimationNeedsResample();
42 private:
43 SVGAnimatedInteger* const mInteger;
44 SVGElement* const mSVGElement;
45 bool mDoSetAttr;
48 static SVGAttrTearoffTable<SVGAnimatedInteger,
49 SVGAnimatedInteger::DOMAnimatedInteger>
50 sSVGAnimatedIntegerTearoffTable;
52 nsresult SVGAnimatedInteger::SetBaseValueString(const nsAString& aValueAsString,
53 SVGElement* aSVGElement) {
54 bool success;
55 auto token = SVGContentUtils::GetAndEnsureOneToken(aValueAsString, success);
57 if (!success) {
58 return NS_ERROR_DOM_SYNTAX_ERR;
61 int32_t value;
63 if (!SVGContentUtils::ParseInteger(token, value)) {
64 return NS_ERROR_DOM_SYNTAX_ERR;
67 AutoChangeIntegerNotifier notifier(this, aSVGElement, false);
69 mIsBaseSet = true;
70 mBaseVal = value;
71 if (!mIsAnimated) {
72 mAnimVal = mBaseVal;
74 return NS_OK;
77 void SVGAnimatedInteger::GetBaseValueString(nsAString& aValueAsString) {
78 aValueAsString.Truncate();
79 aValueAsString.AppendInt(mBaseVal);
82 void SVGAnimatedInteger::SetBaseValue(int aValue, SVGElement* aSVGElement) {
83 // We can't just rely on SetParsedAttrValue (as called by DidChangeInteger)
84 // detecting redundant changes since it will compare false if the existing
85 // attribute value has an associated serialized version (a string value) even
86 // if the integers match due to the way integers are stored in nsAttrValue.
87 if (aValue == mBaseVal && mIsBaseSet) {
88 return;
91 AutoChangeIntegerNotifier notifier(this, aSVGElement);
93 mBaseVal = aValue;
94 mIsBaseSet = true;
95 if (!mIsAnimated) {
96 mAnimVal = mBaseVal;
100 void SVGAnimatedInteger::SetAnimValue(int aValue, SVGElement* aSVGElement) {
101 if (mIsAnimated && aValue == mAnimVal) {
102 return;
104 mAnimVal = aValue;
105 mIsAnimated = true;
106 aSVGElement->DidAnimateInteger(mAttrEnum);
109 already_AddRefed<DOMSVGAnimatedInteger>
110 SVGAnimatedInteger::ToDOMAnimatedInteger(SVGElement* aSVGElement) {
111 RefPtr<DOMAnimatedInteger> domAnimatedInteger =
112 sSVGAnimatedIntegerTearoffTable.GetTearoff(this);
113 if (!domAnimatedInteger) {
114 domAnimatedInteger = new DOMAnimatedInteger(this, aSVGElement);
115 sSVGAnimatedIntegerTearoffTable.AddTearoff(this, domAnimatedInteger);
118 return domAnimatedInteger.forget();
121 SVGAnimatedInteger::DOMAnimatedInteger::~DOMAnimatedInteger() {
122 sSVGAnimatedIntegerTearoffTable.RemoveTearoff(mVal);
125 UniquePtr<SMILAttr> SVGAnimatedInteger::ToSMILAttr(SVGElement* aSVGElement) {
126 return MakeUnique<SMILInteger>(this, aSVGElement);
129 nsresult SVGAnimatedInteger::SMILInteger::ValueFromString(
130 const nsAString& aStr, const dom::SVGAnimationElement* /*aSrcElement*/,
131 SMILValue& aValue, bool& aPreventCachingOfSandwich) const {
132 int32_t val;
134 if (!SVGContentUtils::ParseInteger(aStr, val)) {
135 return NS_ERROR_DOM_SYNTAX_ERR;
138 SMILValue smilVal(SMILIntegerType::Singleton());
139 smilVal.mU.mInt = val;
140 aValue = smilVal;
141 return NS_OK;
144 SMILValue SVGAnimatedInteger::SMILInteger::GetBaseValue() const {
145 SMILValue val(SMILIntegerType::Singleton());
146 val.mU.mInt = mVal->mBaseVal;
147 return val;
150 void SVGAnimatedInteger::SMILInteger::ClearAnimValue() {
151 if (mVal->mIsAnimated) {
152 mVal->mIsAnimated = false;
153 mVal->mAnimVal = mVal->mBaseVal;
154 mSVGElement->DidAnimateInteger(mVal->mAttrEnum);
158 nsresult SVGAnimatedInteger::SMILInteger::SetAnimValue(
159 const SMILValue& aValue) {
160 NS_ASSERTION(aValue.mType == SMILIntegerType::Singleton(),
161 "Unexpected type to assign animated value");
162 if (aValue.mType == SMILIntegerType::Singleton()) {
163 mVal->SetAnimValue(int(aValue.mU.mInt), mSVGElement);
165 return NS_OK;
168 } // namespace mozilla