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"
10 #include "SMILIntegerType.h"
11 #include "SVGAttrTearoffTable.h"
12 #include "mozilla/SMILValue.h"
13 #include "mozilla/SVGContentUtils.h"
15 using namespace mozilla::dom
;
21 //----------------------------------------------------------------------
22 // Helper class: AutoChangeIntegerNotifier
23 // Stack-based helper class ensure DidChangeInteger is called.
24 class MOZ_RAII AutoChangeIntegerNotifier
{
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() {
35 mSVGElement
->DidChangeInteger(mInteger
->mAttrEnum
);
37 if (mInteger
->mIsAnimated
) {
38 mSVGElement
->AnimationNeedsResample();
43 SVGAnimatedInteger
* const mInteger
;
44 SVGElement
* const mSVGElement
;
48 MOZ_CONSTINIT
static SVGAttrTearoffTable
<SVGAnimatedInteger
,
49 SVGAnimatedInteger::DOMAnimatedInteger
>
50 sSVGAnimatedIntegerTearoffTable
;
52 nsresult
SVGAnimatedInteger::SetBaseValueString(const nsAString
& aValueAsString
,
53 SVGElement
* aSVGElement
) {
55 auto token
= SVGContentUtils::GetAndEnsureOneToken(aValueAsString
, success
);
58 return NS_ERROR_DOM_SYNTAX_ERR
;
63 if (!SVGContentUtils::ParseInteger(token
, value
)) {
64 return NS_ERROR_DOM_SYNTAX_ERR
;
67 AutoChangeIntegerNotifier
notifier(this, aSVGElement
, false);
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
) {
91 AutoChangeIntegerNotifier
notifier(this, aSVGElement
);
100 void SVGAnimatedInteger::SetAnimValue(int aValue
, SVGElement
* aSVGElement
) {
101 if (mIsAnimated
&& aValue
== mAnimVal
) {
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 {
134 if (!SVGContentUtils::ParseInteger(aStr
, val
)) {
135 return NS_ERROR_DOM_SYNTAX_ERR
;
138 SMILValue
smilVal(SMILIntegerType::Singleton());
139 smilVal
.mU
.mInt
= val
;
144 SMILValue
SVGAnimatedInteger::SMILInteger::GetBaseValue() const {
145 SMILValue
val(SMILIntegerType::Singleton());
146 val
.mU
.mInt
= mVal
->mBaseVal
;
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
);
168 } // namespace mozilla