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 Crocodile Clips Ltd..
18 : * Portions created by the Initial Developer are Copyright (C) 2001
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
23 : * Jonathan Watt <jonathan.watt@strath.ac.uk>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "mozilla/Util.h"
40 :
41 : #include "nsSVGLength2.h"
42 : #include "prdtoa.h"
43 : #include "nsTextFormatter.h"
44 : #include "nsSVGSVGElement.h"
45 : #include "nsIFrame.h"
46 : #include "nsSVGIntegrationUtils.h"
47 : #include "nsSVGAttrTearoffTable.h"
48 : #include "nsContentUtils.h" // NS_ENSURE_FINITE
49 : #include "nsSMILValue.h"
50 : #include "nsSMILFloatType.h"
51 :
52 : using namespace mozilla;
53 :
54 1464 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal, mSVGElement)
55 :
56 1464 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal, mSVGElement)
57 :
58 1464 : NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength, mSVGElement)
59 :
60 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMBaseVal)
61 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMBaseVal)
62 :
63 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimVal)
64 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimVal)
65 :
66 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimatedLength)
67 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimatedLength)
68 :
69 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal)
70 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
71 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
72 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLength)
73 0 : NS_INTERFACE_MAP_END
74 :
75 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal)
76 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
77 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
78 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLength)
79 0 : NS_INTERFACE_MAP_END
80 :
81 : DOMCI_DATA(SVGAnimatedLength, nsSVGLength2::DOMAnimatedLength)
82 :
83 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength)
84 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedLength)
85 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
86 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedLength)
87 0 : NS_INTERFACE_MAP_END
88 :
89 : static nsIAtom** const unitMap[] =
90 : {
91 : nsnull, /* SVG_LENGTHTYPE_UNKNOWN */
92 : nsnull, /* SVG_LENGTHTYPE_NUMBER */
93 : &nsGkAtoms::percentage,
94 : &nsGkAtoms::em,
95 : &nsGkAtoms::ex,
96 : &nsGkAtoms::px,
97 : &nsGkAtoms::cm,
98 : &nsGkAtoms::mm,
99 : &nsGkAtoms::in,
100 : &nsGkAtoms::pt,
101 : &nsGkAtoms::pc
102 : };
103 :
104 : static nsSVGAttrTearoffTable<nsSVGLength2, nsIDOMSVGAnimatedLength>
105 1464 : sSVGAnimatedLengthTearoffTable;
106 : static nsSVGAttrTearoffTable<nsSVGLength2, nsIDOMSVGLength>
107 1464 : sBaseSVGLengthTearoffTable;
108 : static nsSVGAttrTearoffTable<nsSVGLength2, nsIDOMSVGLength>
109 1464 : sAnimSVGLengthTearoffTable;
110 :
111 : /* Helper functions */
112 :
113 : static bool
114 0 : IsValidUnitType(PRUint16 unit)
115 : {
116 0 : if (unit > nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN &&
117 : unit <= nsIDOMSVGLength::SVG_LENGTHTYPE_PC)
118 0 : return true;
119 :
120 0 : return false;
121 : }
122 :
123 : static void
124 0 : GetUnitString(nsAString& unit, PRUint16 unitType)
125 : {
126 0 : if (IsValidUnitType(unitType)) {
127 0 : if (unitMap[unitType]) {
128 0 : (*unitMap[unitType])->ToString(unit);
129 : }
130 0 : return;
131 : }
132 :
133 0 : NS_NOTREACHED("Unknown unit type");
134 0 : return;
135 : }
136 :
137 : static PRUint16
138 0 : GetUnitTypeForString(const char* unitStr)
139 : {
140 0 : if (!unitStr || *unitStr == '\0')
141 0 : return nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER;
142 :
143 0 : nsCOMPtr<nsIAtom> unitAtom = do_GetAtom(unitStr);
144 :
145 0 : for (PRUint32 i = 0 ; i < ArrayLength(unitMap) ; i++) {
146 0 : if (unitMap[i] && *unitMap[i] == unitAtom) {
147 0 : return i;
148 : }
149 : }
150 :
151 0 : return nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN;
152 : }
153 :
154 : static void
155 0 : GetValueString(nsAString &aValueAsString, float aValue, PRUint16 aUnitType)
156 : {
157 : PRUnichar buf[24];
158 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
159 0 : NS_LITERAL_STRING("%g").get(),
160 0 : (double)aValue);
161 0 : aValueAsString.Assign(buf);
162 :
163 0 : nsAutoString unitString;
164 0 : GetUnitString(unitString, aUnitType);
165 0 : aValueAsString.Append(unitString);
166 0 : }
167 :
168 : static nsresult
169 0 : GetValueFromString(const nsAString &aValueAsString,
170 : float *aValue,
171 : PRUint16 *aUnitType)
172 : {
173 0 : NS_ConvertUTF16toUTF8 value(aValueAsString);
174 0 : const char *str = value.get();
175 :
176 0 : if (NS_IsAsciiWhitespace(*str))
177 0 : return NS_ERROR_DOM_SYNTAX_ERR;
178 :
179 : char *rest;
180 0 : *aValue = float(PR_strtod(str, &rest));
181 0 : if (rest != str && NS_finite(*aValue)) {
182 0 : *aUnitType = GetUnitTypeForString(rest);
183 0 : if (IsValidUnitType(*aUnitType)) {
184 0 : return NS_OK;
185 : }
186 : }
187 :
188 0 : return NS_ERROR_DOM_SYNTAX_ERR;
189 : }
190 :
191 : static float
192 0 : FixAxisLength(float aLength)
193 : {
194 0 : if (aLength == 0.0f) {
195 0 : NS_WARNING("zero axis length");
196 0 : return 1e-20f;
197 : }
198 0 : return aLength;
199 : }
200 :
201 : float
202 0 : nsSVGLength2::GetAxisLength(nsSVGSVGElement *aCtx) const
203 : {
204 0 : if (!aCtx)
205 0 : return 1;
206 :
207 0 : return FixAxisLength(aCtx->GetLength(mCtxType));
208 : }
209 :
210 : float
211 0 : nsSVGLength2::GetAxisLength(nsIFrame *aNonSVGFrame) const
212 : {
213 0 : gfxRect rect = nsSVGIntegrationUtils::GetSVGRectForNonSVGFrame(aNonSVGFrame);
214 : float length;
215 0 : switch (mCtxType) {
216 0 : case nsSVGUtils::X: length = rect.Width(); break;
217 0 : case nsSVGUtils::Y: length = rect.Height(); break;
218 : case nsSVGUtils::XY:
219 0 : length = nsSVGUtils::ComputeNormalizedHypotenuse(rect.Width(), rect.Height());
220 0 : break;
221 : default:
222 0 : NS_NOTREACHED("Unknown axis type");
223 0 : length = 1;
224 0 : break;
225 : }
226 0 : return FixAxisLength(length);
227 : }
228 :
229 : float
230 0 : nsSVGLength2::GetUnitScaleFactor(nsSVGElement *aSVGElement,
231 : PRUint8 aUnitType) const
232 : {
233 0 : switch (aUnitType) {
234 : case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
235 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
236 0 : return 1;
237 : case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
238 0 : return 1 / GetEmLength(aSVGElement);
239 : case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
240 0 : return 1 / GetExLength(aSVGElement);
241 : }
242 :
243 0 : return GetUnitScaleFactor(aSVGElement->GetCtx(), aUnitType);
244 : }
245 :
246 : float
247 0 : nsSVGLength2::GetUnitScaleFactor(nsSVGSVGElement *aCtx, PRUint8 aUnitType) const
248 : {
249 0 : switch (aUnitType) {
250 : case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
251 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
252 0 : return 1;
253 : case nsIDOMSVGLength::SVG_LENGTHTYPE_MM:
254 0 : return GetMMPerPixel();
255 : case nsIDOMSVGLength::SVG_LENGTHTYPE_CM:
256 0 : return GetMMPerPixel() / 10.0f;
257 : case nsIDOMSVGLength::SVG_LENGTHTYPE_IN:
258 0 : return GetMMPerPixel() / MM_PER_INCH_FLOAT;
259 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PT:
260 0 : return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT;
261 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PC:
262 0 : return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT / 12.0f;
263 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE:
264 0 : return 100.0f / GetAxisLength(aCtx);
265 : case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
266 0 : return 1 / GetEmLength(aCtx);
267 : case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
268 0 : return 1 / GetExLength(aCtx);
269 : default:
270 0 : NS_NOTREACHED("Unknown unit type");
271 0 : return 0;
272 : }
273 : }
274 :
275 : float
276 0 : nsSVGLength2::GetUnitScaleFactor(nsIFrame *aFrame, PRUint8 aUnitType) const
277 : {
278 0 : nsIContent* content = aFrame->GetContent();
279 0 : if (content->IsSVG())
280 0 : return GetUnitScaleFactor(static_cast<nsSVGElement*>(content), aUnitType);
281 :
282 0 : switch (aUnitType) {
283 : case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
284 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
285 0 : return 1;
286 : case nsIDOMSVGLength::SVG_LENGTHTYPE_MM:
287 0 : return GetMMPerPixel();
288 : case nsIDOMSVGLength::SVG_LENGTHTYPE_CM:
289 0 : return GetMMPerPixel() / 10.0f;
290 : case nsIDOMSVGLength::SVG_LENGTHTYPE_IN:
291 0 : return GetMMPerPixel() / MM_PER_INCH_FLOAT;
292 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PT:
293 0 : return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT;
294 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PC:
295 0 : return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT / 12.0f;
296 : case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE:
297 0 : return 100.0f / GetAxisLength(aFrame);
298 : case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
299 0 : return 1 / GetEmLength(aFrame);
300 : case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
301 0 : return 1 / GetExLength(aFrame);
302 : default:
303 0 : NS_NOTREACHED("Unknown unit type");
304 0 : return 0;
305 : }
306 : }
307 :
308 : void
309 0 : nsSVGLength2::SetBaseValueInSpecifiedUnits(float aValue,
310 : nsSVGElement *aSVGElement,
311 : bool aDoSetAttr)
312 : {
313 0 : if (mIsBaseSet && mBaseVal == aValue) {
314 0 : return;
315 : }
316 :
317 0 : nsAttrValue emptyOrOldValue;
318 0 : if (aDoSetAttr) {
319 0 : emptyOrOldValue = aSVGElement->WillChangeLength(mAttrEnum);
320 : }
321 0 : mBaseVal = aValue;
322 0 : mIsBaseSet = true;
323 0 : if (!mIsAnimated) {
324 0 : mAnimVal = mBaseVal;
325 : }
326 : else {
327 0 : aSVGElement->AnimationNeedsResample();
328 : }
329 0 : if (aDoSetAttr) {
330 0 : aSVGElement->DidChangeLength(mAttrEnum, emptyOrOldValue);
331 : }
332 : }
333 :
334 : nsresult
335 0 : nsSVGLength2::ConvertToSpecifiedUnits(PRUint16 unitType,
336 : nsSVGElement *aSVGElement)
337 : {
338 0 : if (!IsValidUnitType(unitType))
339 0 : return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
340 :
341 0 : if (mIsBaseSet && mSpecifiedUnitType == PRUint8(unitType))
342 0 : return NS_OK;
343 :
344 : // Even though we're not changing the visual effect this length will have
345 : // on the document, we still need to send out notifications in case we have
346 : // mutation listeners, since the actual string value of the attribute will
347 : // change.
348 0 : nsAttrValue emptyOrOldValue = aSVGElement->WillChangeLength(mAttrEnum);
349 :
350 : float valueInUserUnits =
351 0 : mBaseVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType);
352 0 : mSpecifiedUnitType = PRUint8(unitType);
353 : // Setting aDoSetAttr to false here will ensure we don't call
354 : // Will/DidChangeAngle a second time (and dispatch duplicate notifications).
355 0 : SetBaseValue(valueInUserUnits, aSVGElement, false);
356 :
357 0 : aSVGElement->DidChangeLength(mAttrEnum, emptyOrOldValue);
358 :
359 0 : return NS_OK;
360 : }
361 :
362 : nsresult
363 0 : nsSVGLength2::NewValueSpecifiedUnits(PRUint16 unitType,
364 : float valueInSpecifiedUnits,
365 : nsSVGElement *aSVGElement)
366 : {
367 0 : NS_ENSURE_FINITE(valueInSpecifiedUnits, NS_ERROR_ILLEGAL_VALUE);
368 :
369 0 : if (!IsValidUnitType(unitType))
370 0 : return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
371 :
372 0 : if (mIsBaseSet && mBaseVal == valueInSpecifiedUnits &&
373 : mSpecifiedUnitType == PRUint8(unitType)) {
374 0 : return NS_OK;
375 : }
376 :
377 0 : nsAttrValue emptyOrOldValue = aSVGElement->WillChangeLength(mAttrEnum);
378 0 : mBaseVal = valueInSpecifiedUnits;
379 0 : mIsBaseSet = true;
380 0 : mSpecifiedUnitType = PRUint8(unitType);
381 0 : if (!mIsAnimated) {
382 0 : mAnimVal = mBaseVal;
383 : }
384 : else {
385 0 : aSVGElement->AnimationNeedsResample();
386 : }
387 0 : aSVGElement->DidChangeLength(mAttrEnum, emptyOrOldValue);
388 0 : return NS_OK;
389 : }
390 :
391 : nsresult
392 0 : nsSVGLength2::ToDOMBaseVal(nsIDOMSVGLength **aResult, nsSVGElement *aSVGElement)
393 : {
394 0 : *aResult = sBaseSVGLengthTearoffTable.GetTearoff(this);
395 0 : if (!*aResult) {
396 0 : *aResult = new DOMBaseVal(this, aSVGElement);
397 0 : if (!*aResult)
398 0 : return NS_ERROR_OUT_OF_MEMORY;
399 0 : sBaseSVGLengthTearoffTable.AddTearoff(this, *aResult);
400 : }
401 :
402 0 : NS_ADDREF(*aResult);
403 0 : return NS_OK;
404 : }
405 :
406 0 : nsSVGLength2::DOMBaseVal::~DOMBaseVal()
407 : {
408 0 : sBaseSVGLengthTearoffTable.RemoveTearoff(mVal);
409 0 : }
410 :
411 : nsresult
412 0 : nsSVGLength2::ToDOMAnimVal(nsIDOMSVGLength **aResult, nsSVGElement *aSVGElement)
413 : {
414 0 : *aResult = sAnimSVGLengthTearoffTable.GetTearoff(this);
415 0 : if (!*aResult) {
416 0 : *aResult = new DOMAnimVal(this, aSVGElement);
417 0 : if (!*aResult)
418 0 : return NS_ERROR_OUT_OF_MEMORY;
419 0 : sAnimSVGLengthTearoffTable.AddTearoff(this, *aResult);
420 : }
421 :
422 0 : NS_ADDREF(*aResult);
423 0 : return NS_OK;
424 : }
425 :
426 0 : nsSVGLength2::DOMAnimVal::~DOMAnimVal()
427 : {
428 0 : sAnimSVGLengthTearoffTable.RemoveTearoff(mVal);
429 0 : }
430 :
431 : /* Implementation */
432 :
433 : nsresult
434 0 : nsSVGLength2::SetBaseValueString(const nsAString &aValueAsString,
435 : nsSVGElement *aSVGElement,
436 : bool aDoSetAttr)
437 : {
438 : float value;
439 : PRUint16 unitType;
440 :
441 0 : nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
442 0 : if (NS_FAILED(rv)) {
443 0 : return rv;
444 : }
445 :
446 0 : if (mIsBaseSet && mBaseVal == value &&
447 : mSpecifiedUnitType == PRUint8(unitType)) {
448 0 : return NS_OK;
449 : }
450 :
451 0 : nsAttrValue emptyOrOldValue;
452 0 : if (aDoSetAttr) {
453 0 : emptyOrOldValue = aSVGElement->WillChangeLength(mAttrEnum);
454 : }
455 0 : mBaseVal = value;
456 0 : mIsBaseSet = true;
457 0 : mSpecifiedUnitType = PRUint8(unitType);
458 0 : if (!mIsAnimated) {
459 0 : mAnimVal = mBaseVal;
460 : }
461 : else {
462 0 : aSVGElement->AnimationNeedsResample();
463 : }
464 :
465 0 : if (aDoSetAttr) {
466 0 : aSVGElement->DidChangeLength(mAttrEnum, emptyOrOldValue);
467 : }
468 0 : return NS_OK;
469 : }
470 :
471 : void
472 0 : nsSVGLength2::GetBaseValueString(nsAString & aValueAsString) const
473 : {
474 0 : GetValueString(aValueAsString, mBaseVal, mSpecifiedUnitType);
475 0 : }
476 :
477 : void
478 0 : nsSVGLength2::GetAnimValueString(nsAString & aValueAsString) const
479 : {
480 0 : GetValueString(aValueAsString, mAnimVal, mSpecifiedUnitType);
481 0 : }
482 :
483 : void
484 0 : nsSVGLength2::SetBaseValue(float aValue, nsSVGElement *aSVGElement,
485 : bool aDoSetAttr)
486 : {
487 : SetBaseValueInSpecifiedUnits(aValue * GetUnitScaleFactor(aSVGElement,
488 0 : mSpecifiedUnitType),
489 0 : aSVGElement, aDoSetAttr);
490 0 : }
491 :
492 : void
493 0 : nsSVGLength2::SetAnimValueInSpecifiedUnits(float aValue,
494 : nsSVGElement* aSVGElement)
495 : {
496 0 : mAnimVal = aValue;
497 0 : mIsAnimated = true;
498 0 : aSVGElement->DidAnimateLength(mAttrEnum);
499 0 : }
500 :
501 : void
502 0 : nsSVGLength2::SetAnimValue(float aValue, nsSVGElement *aSVGElement)
503 : {
504 : SetAnimValueInSpecifiedUnits(aValue * GetUnitScaleFactor(aSVGElement,
505 0 : mSpecifiedUnitType),
506 0 : aSVGElement);
507 0 : }
508 :
509 : nsresult
510 0 : nsSVGLength2::ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult,
511 : nsSVGElement *aSVGElement)
512 : {
513 0 : *aResult = sSVGAnimatedLengthTearoffTable.GetTearoff(this);
514 0 : if (!*aResult) {
515 0 : *aResult = new DOMAnimatedLength(this, aSVGElement);
516 0 : if (!*aResult)
517 0 : return NS_ERROR_OUT_OF_MEMORY;
518 0 : sSVGAnimatedLengthTearoffTable.AddTearoff(this, *aResult);
519 : }
520 :
521 0 : NS_ADDREF(*aResult);
522 0 : return NS_OK;
523 : }
524 :
525 0 : nsSVGLength2::DOMAnimatedLength::~DOMAnimatedLength()
526 : {
527 0 : sSVGAnimatedLengthTearoffTable.RemoveTearoff(mVal);
528 0 : }
529 :
530 : nsISMILAttr*
531 0 : nsSVGLength2::ToSMILAttr(nsSVGElement *aSVGElement)
532 : {
533 0 : return new SMILLength(this, aSVGElement);
534 : }
535 :
536 : nsresult
537 0 : nsSVGLength2::SMILLength::ValueFromString(const nsAString& aStr,
538 : const nsISMILAnimationElement* /*aSrcElement*/,
539 : nsSMILValue& aValue,
540 : bool& aPreventCachingOfSandwich) const
541 : {
542 : float value;
543 : PRUint16 unitType;
544 :
545 0 : nsresult rv = GetValueFromString(aStr, &value, &unitType);
546 0 : if (NS_FAILED(rv)) {
547 0 : return rv;
548 : }
549 :
550 0 : nsSMILValue val(&nsSMILFloatType::sSingleton);
551 0 : val.mU.mDouble = value / mVal->GetUnitScaleFactor(mSVGElement, unitType);
552 0 : aValue = val;
553 : aPreventCachingOfSandwich =
554 : (unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE ||
555 : unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_EMS ||
556 0 : unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_EXS);
557 :
558 0 : return NS_OK;
559 : }
560 :
561 : nsSMILValue
562 0 : nsSVGLength2::SMILLength::GetBaseValue() const
563 : {
564 0 : nsSMILValue val(&nsSMILFloatType::sSingleton);
565 0 : val.mU.mDouble = mVal->GetBaseValue(mSVGElement);
566 : return val;
567 : }
568 :
569 : void
570 0 : nsSVGLength2::SMILLength::ClearAnimValue()
571 : {
572 0 : if (mVal->mIsAnimated) {
573 0 : mVal->mIsAnimated = false;
574 0 : mVal->mAnimVal = mVal->mBaseVal;
575 0 : mSVGElement->DidAnimateLength(mVal->mAttrEnum);
576 : }
577 0 : }
578 :
579 : nsresult
580 0 : nsSVGLength2::SMILLength::SetAnimValue(const nsSMILValue& aValue)
581 : {
582 0 : NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
583 : "Unexpected type to assign animated value");
584 0 : if (aValue.mType == &nsSMILFloatType::sSingleton) {
585 0 : mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
586 : }
587 0 : return NS_OK;
588 4392 : }
|