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 "nsSVGNumber2.h"
8 : #include "mozilla/Attributes.h"
9 : #include "nsContentUtils.h" // NS_ENSURE_FINITE
10 : #include "nsSMILFloatType.h"
11 : #include "nsSMILValue.h"
12 : #include "nsSVGAttrTearoffTable.h"
13 : #include "SVGContentUtils.h"
14 :
15 : using namespace mozilla;
16 : using namespace mozilla::dom;
17 :
18 : /* Implementation */
19 :
20 : static nsSVGAttrTearoffTable<nsSVGNumber2, nsSVGNumber2::DOMAnimatedNumber>
21 3 : sSVGAnimatedNumberTearoffTable;
22 :
23 : static bool
24 0 : GetValueFromString(const nsAString& aString,
25 : bool aPercentagesAllowed,
26 : float& aValue)
27 : {
28 : RangedPtr<const char16_t> iter =
29 0 : SVGContentUtils::GetStartRangedPtr(aString);
30 : const RangedPtr<const char16_t> end =
31 0 : SVGContentUtils::GetEndRangedPtr(aString);
32 :
33 0 : if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
34 0 : return false;
35 : }
36 :
37 0 : if (aPercentagesAllowed) {
38 0 : const nsAString& units = Substring(iter.get(), end.get());
39 0 : if (units.EqualsLiteral("%")) {
40 0 : aValue /= 100;
41 0 : return true;
42 : }
43 : }
44 :
45 0 : return iter == end;
46 : }
47 :
48 : nsresult
49 0 : nsSVGNumber2::SetBaseValueString(const nsAString &aValueAsString,
50 : nsSVGElement *aSVGElement)
51 : {
52 : float val;
53 :
54 0 : if (!GetValueFromString(aValueAsString,
55 0 : aSVGElement->NumberAttrAllowsPercentage(mAttrEnum),
56 : val)) {
57 0 : return NS_ERROR_DOM_SYNTAX_ERR;
58 : }
59 :
60 0 : mBaseVal = val;
61 0 : mIsBaseSet = true;
62 0 : if (!mIsAnimated) {
63 0 : mAnimVal = mBaseVal;
64 : }
65 : else {
66 0 : aSVGElement->AnimationNeedsResample();
67 : }
68 :
69 : // We don't need to call DidChange* here - we're only called by
70 : // nsSVGElement::ParseAttribute under Element::SetAttr,
71 : // which takes care of notifying.
72 0 : return NS_OK;
73 : }
74 :
75 : void
76 0 : nsSVGNumber2::GetBaseValueString(nsAString & aValueAsString)
77 : {
78 0 : aValueAsString.Truncate();
79 0 : aValueAsString.AppendFloat(mBaseVal);
80 0 : }
81 :
82 : void
83 0 : nsSVGNumber2::SetBaseValue(float aValue, nsSVGElement *aSVGElement)
84 : {
85 0 : if (mIsBaseSet && aValue == mBaseVal) {
86 0 : return;
87 : }
88 :
89 0 : mBaseVal = aValue;
90 0 : mIsBaseSet = true;
91 0 : if (!mIsAnimated) {
92 0 : mAnimVal = mBaseVal;
93 : }
94 : else {
95 0 : aSVGElement->AnimationNeedsResample();
96 : }
97 0 : aSVGElement->DidChangeNumber(mAttrEnum);
98 : }
99 :
100 : void
101 0 : nsSVGNumber2::SetAnimValue(float aValue, nsSVGElement *aSVGElement)
102 : {
103 0 : if (mIsAnimated && aValue == mAnimVal) {
104 0 : return;
105 : }
106 0 : mAnimVal = aValue;
107 0 : mIsAnimated = true;
108 0 : aSVGElement->DidAnimateNumber(mAttrEnum);
109 : }
110 :
111 : already_AddRefed<SVGAnimatedNumber>
112 0 : nsSVGNumber2::ToDOMAnimatedNumber(nsSVGElement* aSVGElement)
113 : {
114 : RefPtr<DOMAnimatedNumber> domAnimatedNumber =
115 0 : sSVGAnimatedNumberTearoffTable.GetTearoff(this);
116 0 : if (!domAnimatedNumber) {
117 0 : domAnimatedNumber = new DOMAnimatedNumber(this, aSVGElement);
118 0 : sSVGAnimatedNumberTearoffTable.AddTearoff(this, domAnimatedNumber);
119 : }
120 :
121 0 : return domAnimatedNumber.forget();
122 : }
123 :
124 0 : nsSVGNumber2::DOMAnimatedNumber::~DOMAnimatedNumber()
125 : {
126 0 : sSVGAnimatedNumberTearoffTable.RemoveTearoff(mVal);
127 0 : }
128 :
129 : UniquePtr<nsISMILAttr>
130 0 : nsSVGNumber2::ToSMILAttr(nsSVGElement *aSVGElement)
131 : {
132 0 : return MakeUnique<SMILNumber>(this, aSVGElement);
133 : }
134 :
135 : nsresult
136 0 : nsSVGNumber2::SMILNumber::ValueFromString(const nsAString& aStr,
137 : const mozilla::dom::SVGAnimationElement* /*aSrcElement*/,
138 : nsSMILValue& aValue,
139 : bool& aPreventCachingOfSandwich) const
140 : {
141 : float value;
142 :
143 0 : if (!GetValueFromString(aStr,
144 0 : mSVGElement->NumberAttrAllowsPercentage(mVal->mAttrEnum),
145 : value)) {
146 0 : return NS_ERROR_DOM_SYNTAX_ERR;
147 : }
148 :
149 0 : nsSMILValue val(nsSMILFloatType::Singleton());
150 0 : val.mU.mDouble = value;
151 0 : aValue = val;
152 0 : aPreventCachingOfSandwich = false;
153 :
154 0 : return NS_OK;
155 : }
156 :
157 : nsSMILValue
158 0 : nsSVGNumber2::SMILNumber::GetBaseValue() const
159 : {
160 0 : nsSMILValue val(nsSMILFloatType::Singleton());
161 0 : val.mU.mDouble = mVal->mBaseVal;
162 0 : return val;
163 : }
164 :
165 : void
166 0 : nsSVGNumber2::SMILNumber::ClearAnimValue()
167 : {
168 0 : if (mVal->mIsAnimated) {
169 0 : mVal->mIsAnimated = false;
170 0 : mVal->mAnimVal = mVal->mBaseVal;
171 0 : mSVGElement->DidAnimateNumber(mVal->mAttrEnum);
172 : }
173 0 : }
174 :
175 : nsresult
176 0 : nsSVGNumber2::SMILNumber::SetAnimValue(const nsSMILValue& aValue)
177 : {
178 0 : NS_ASSERTION(aValue.mType == nsSMILFloatType::Singleton(),
179 : "Unexpected type to assign animated value");
180 0 : if (aValue.mType == nsSMILFloatType::Singleton()) {
181 0 : mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
182 : }
183 0 : return NS_OK;
184 : }
|