1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Mozilla SVG project.
16 : *
17 : * The Initial Developer of the Original Code is IBM Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 2006
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPL"), or
25 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 : #include "nsSVGNumber2.h"
38 : #include "nsSVGUtils.h"
39 : #include "nsTextFormatter.h"
40 : #include "prdtoa.h"
41 : #include "nsMathUtils.h"
42 : #include "nsContentUtils.h" // NS_ENSURE_FINITE
43 : #include "nsSMILValue.h"
44 : #include "nsSMILFloatType.h"
45 : #include "nsIDOMSVGNumber.h"
46 :
47 : class DOMSVGNumber : public nsIDOMSVGNumber
48 : {
49 : public:
50 : NS_DECL_ISUPPORTS
51 :
52 : DOMSVGNumber()
53 : : mVal(0) {}
54 :
55 0 : NS_IMETHOD GetValue(float* aResult)
56 0 : { *aResult = mVal; return NS_OK; }
57 0 : NS_IMETHOD SetValue(float aValue)
58 0 : { NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
59 0 : mVal = aValue;
60 0 : return NS_OK; }
61 :
62 : private:
63 : float mVal;
64 : };
65 :
66 1464 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber, mSVGElement)
67 :
68 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGNumber2::DOMAnimatedNumber)
69 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGNumber2::DOMAnimatedNumber)
70 :
71 0 : NS_IMPL_ADDREF(DOMSVGNumber)
72 0 : NS_IMPL_RELEASE(DOMSVGNumber)
73 :
74 : DOMCI_DATA(SVGAnimatedNumber, nsSVGNumber2::DOMAnimatedNumber)
75 :
76 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber)
77 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumber)
78 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
79 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedNumber)
80 0 : NS_INTERFACE_MAP_END
81 :
82 0 : NS_INTERFACE_MAP_BEGIN(DOMSVGNumber)
83 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumber)
84 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
85 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumber)
86 0 : NS_INTERFACE_MAP_END
87 :
88 : /* Implementation */
89 :
90 : static nsresult
91 0 : GetValueFromString(const nsAString &aValueAsString,
92 : bool aPercentagesAllowed,
93 : float *aValue)
94 : {
95 0 : NS_ConvertUTF16toUTF8 value(aValueAsString);
96 0 : const char *str = value.get();
97 :
98 0 : if (NS_IsAsciiWhitespace(*str))
99 0 : return NS_ERROR_DOM_SYNTAX_ERR;
100 :
101 : char *rest;
102 0 : *aValue = float(PR_strtod(str, &rest));
103 0 : if (rest == str || !NS_finite(*aValue)) {
104 0 : return NS_ERROR_DOM_SYNTAX_ERR;
105 : }
106 0 : if (*rest == '%' && aPercentagesAllowed) {
107 0 : *aValue /= 100;
108 0 : ++rest;
109 : }
110 0 : if (*rest == '\0') {
111 0 : return NS_OK;
112 : }
113 0 : return NS_ERROR_DOM_SYNTAX_ERR;
114 : }
115 :
116 : nsresult
117 0 : nsSVGNumber2::SetBaseValueString(const nsAString &aValueAsString,
118 : nsSVGElement *aSVGElement)
119 : {
120 : float val;
121 :
122 : nsresult rv = GetValueFromString(
123 0 : aValueAsString, aSVGElement->NumberAttrAllowsPercentage(mAttrEnum), &val);
124 :
125 0 : if (NS_FAILED(rv)) {
126 0 : return rv;
127 : }
128 :
129 0 : mBaseVal = val;
130 0 : mIsBaseSet = true;
131 0 : if (!mIsAnimated) {
132 0 : mAnimVal = mBaseVal;
133 : }
134 : else {
135 0 : aSVGElement->AnimationNeedsResample();
136 : }
137 :
138 : // We don't need to call DidChange* here - we're only called by
139 : // nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
140 : // which takes care of notifying.
141 0 : return NS_OK;
142 : }
143 :
144 : void
145 0 : nsSVGNumber2::GetBaseValueString(nsAString & aValueAsString)
146 : {
147 0 : aValueAsString.Truncate();
148 0 : aValueAsString.AppendFloat(mBaseVal);
149 0 : }
150 :
151 : void
152 0 : nsSVGNumber2::SetBaseValue(float aValue, nsSVGElement *aSVGElement)
153 : {
154 0 : if (mIsBaseSet && aValue == mBaseVal) {
155 0 : return;
156 : }
157 :
158 0 : mBaseVal = aValue;
159 0 : mIsBaseSet = true;
160 0 : if (!mIsAnimated) {
161 0 : mAnimVal = mBaseVal;
162 : }
163 : else {
164 0 : aSVGElement->AnimationNeedsResample();
165 : }
166 0 : aSVGElement->DidChangeNumber(mAttrEnum);
167 : }
168 :
169 : void
170 0 : nsSVGNumber2::SetAnimValue(float aValue, nsSVGElement *aSVGElement)
171 : {
172 0 : mAnimVal = aValue;
173 0 : mIsAnimated = true;
174 0 : aSVGElement->DidAnimateNumber(mAttrEnum);
175 0 : }
176 :
177 : nsresult
178 0 : nsSVGNumber2::ToDOMAnimatedNumber(nsIDOMSVGAnimatedNumber **aResult,
179 : nsSVGElement *aSVGElement)
180 : {
181 0 : *aResult = new DOMAnimatedNumber(this, aSVGElement);
182 0 : if (!*aResult)
183 0 : return NS_ERROR_OUT_OF_MEMORY;
184 :
185 0 : NS_ADDREF(*aResult);
186 0 : return NS_OK;
187 : }
188 :
189 : nsISMILAttr*
190 0 : nsSVGNumber2::ToSMILAttr(nsSVGElement *aSVGElement)
191 : {
192 0 : return new SMILNumber(this, aSVGElement);
193 : }
194 :
195 : nsresult
196 0 : nsSVGNumber2::SMILNumber::ValueFromString(const nsAString& aStr,
197 : const nsISMILAnimationElement* /*aSrcElement*/,
198 : nsSMILValue& aValue,
199 : bool& aPreventCachingOfSandwich) const
200 : {
201 : float value;
202 :
203 : nsresult rv = GetValueFromString(
204 0 : aStr, mSVGElement->NumberAttrAllowsPercentage(mVal->mAttrEnum), &value);
205 :
206 0 : if (NS_FAILED(rv)) {
207 0 : return rv;
208 : }
209 :
210 0 : nsSMILValue val(&nsSMILFloatType::sSingleton);
211 0 : val.mU.mDouble = value;
212 0 : aValue = val;
213 0 : aPreventCachingOfSandwich = false;
214 :
215 0 : return NS_OK;
216 : }
217 :
218 : nsSMILValue
219 0 : nsSVGNumber2::SMILNumber::GetBaseValue() const
220 : {
221 0 : nsSMILValue val(&nsSMILFloatType::sSingleton);
222 0 : val.mU.mDouble = mVal->mBaseVal;
223 : return val;
224 : }
225 :
226 : void
227 0 : nsSVGNumber2::SMILNumber::ClearAnimValue()
228 : {
229 0 : if (mVal->mIsAnimated) {
230 0 : mVal->mIsAnimated = false;
231 0 : mVal->mAnimVal = mVal->mBaseVal;
232 0 : mSVGElement->DidAnimateNumber(mVal->mAttrEnum);
233 : }
234 0 : }
235 :
236 : nsresult
237 0 : nsSVGNumber2::SMILNumber::SetAnimValue(const nsSMILValue& aValue)
238 : {
239 0 : NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
240 : "Unexpected type to assign animated value");
241 0 : if (aValue.mType == &nsSMILFloatType::sSingleton) {
242 0 : mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
243 : }
244 0 : return NS_OK;
245 4392 : }
|