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 "SVGOrientSMILType.h"
8 #include "nsSMILValue.h"
9 #include "nsSVGAngle.h"
11 #include "mozilla/dom/SVGMarkerElement.h"
16 using namespace dom::SVGAngleBinding
;
17 using namespace dom::SVGMarkerElementBinding
;
19 /*static*/ SVGOrientSMILType
SVGOrientSMILType::sSingleton
;
22 SVGOrientSMILType::Init(nsSMILValue
& aValue
) const
24 MOZ_ASSERT(aValue
.IsNull(), "Unexpected value type");
26 aValue
.mU
.mOrient
.mAngle
= 0.0f
;
27 aValue
.mU
.mOrient
.mUnit
= SVG_ANGLETYPE_UNSPECIFIED
;
28 aValue
.mU
.mOrient
.mOrientType
= SVG_MARKER_ORIENT_ANGLE
;
33 SVGOrientSMILType::Destroy(nsSMILValue
& aValue
) const
35 NS_PRECONDITION(aValue
.mType
== this, "Unexpected SMIL value.");
36 aValue
.mU
.mPtr
= nullptr;
37 aValue
.mType
= nsSMILNullType::Singleton();
41 SVGOrientSMILType::Assign(nsSMILValue
& aDest
, const nsSMILValue
& aSrc
) const
43 NS_PRECONDITION(aDest
.mType
== aSrc
.mType
, "Incompatible SMIL types.");
44 NS_PRECONDITION(aDest
.mType
== this, "Unexpected SMIL value.");
46 aDest
.mU
.mOrient
.mAngle
= aSrc
.mU
.mOrient
.mAngle
;
47 aDest
.mU
.mOrient
.mUnit
= aSrc
.mU
.mOrient
.mUnit
;
48 aDest
.mU
.mOrient
.mOrientType
= aSrc
.mU
.mOrient
.mOrientType
;
53 SVGOrientSMILType::IsEqual(const nsSMILValue
& aLeft
,
54 const nsSMILValue
& aRight
) const
56 NS_PRECONDITION(aLeft
.mType
== aRight
.mType
, "Incompatible SMIL types");
57 NS_PRECONDITION(aLeft
.mType
== this, "Unexpected type for SMIL value");
60 aLeft
.mU
.mOrient
.mAngle
== aRight
.mU
.mOrient
.mAngle
&&
61 aLeft
.mU
.mOrient
.mUnit
== aRight
.mU
.mOrient
.mUnit
&&
62 aLeft
.mU
.mOrient
.mOrientType
== aRight
.mU
.mOrient
.mOrientType
;
66 SVGOrientSMILType::Add(nsSMILValue
& aDest
, const nsSMILValue
& aValueToAdd
,
67 uint32_t aCount
) const
69 NS_PRECONDITION(aValueToAdd
.mType
== aDest
.mType
,
70 "Trying to add invalid types");
71 NS_PRECONDITION(aValueToAdd
.mType
== this, "Unexpected source type");
73 if (aDest
.mU
.mOrient
.mOrientType
!= SVG_MARKER_ORIENT_ANGLE
||
74 aValueToAdd
.mU
.mOrient
.mOrientType
!= SVG_MARKER_ORIENT_ANGLE
) {
75 // TODO: it would be nice to be able to add to auto angles
76 return NS_ERROR_FAILURE
;
79 // We may be dealing with two different angle units, so we normalize to
80 // degrees for the add:
81 float currentAngle
= aDest
.mU
.mOrient
.mAngle
*
82 nsSVGAngle::GetDegreesPerUnit(aDest
.mU
.mOrient
.mUnit
);
83 float angleToAdd
= aValueToAdd
.mU
.mOrient
.mAngle
*
84 nsSVGAngle::GetDegreesPerUnit(aValueToAdd
.mU
.mOrient
.mUnit
) *
87 // And then we give the resulting animated value the same units as the value
88 // that we're animating to/by (i.e. the same as aValueToAdd):
89 aDest
.mU
.mOrient
.mAngle
= (currentAngle
+ angleToAdd
) /
90 nsSVGAngle::GetDegreesPerUnit(aValueToAdd
.mU
.mOrient
.mUnit
);
91 aDest
.mU
.mOrient
.mUnit
= aValueToAdd
.mU
.mOrient
.mUnit
;
97 SVGOrientSMILType::ComputeDistance(const nsSMILValue
& aFrom
,
98 const nsSMILValue
& aTo
,
99 double& aDistance
) const
101 NS_PRECONDITION(aFrom
.mType
== aTo
.mType
,"Trying to compare different types");
102 NS_PRECONDITION(aFrom
.mType
== this, "Unexpected source type");
104 if (aFrom
.mU
.mOrient
.mOrientType
!= SVG_MARKER_ORIENT_ANGLE
||
105 aTo
.mU
.mOrient
.mOrientType
!= SVG_MARKER_ORIENT_ANGLE
) {
106 // TODO: it would be nice to be able to compute distance with auto angles
107 return NS_ERROR_FAILURE
;
110 // Normalize both to degrees in case they're different angle units:
111 double from
= aFrom
.mU
.mOrient
.mAngle
*
112 nsSVGAngle::GetDegreesPerUnit(aFrom
.mU
.mOrient
.mUnit
);
113 double to
= aTo
.mU
.mOrient
.mAngle
*
114 nsSVGAngle::GetDegreesPerUnit(aTo
.mU
.mOrient
.mUnit
);
116 aDistance
= fabs(to
- from
);
122 SVGOrientSMILType::Interpolate(const nsSMILValue
& aStartVal
,
123 const nsSMILValue
& aEndVal
,
124 double aUnitDistance
,
125 nsSMILValue
& aResult
) const
127 NS_PRECONDITION(aStartVal
.mType
== aEndVal
.mType
,
128 "Trying to interpolate different types");
129 NS_PRECONDITION(aStartVal
.mType
== this,
130 "Unexpected types for interpolation.");
131 NS_PRECONDITION(aResult
.mType
== this, "Unexpected result type.");
133 if (aStartVal
.mU
.mOrient
.mOrientType
!= SVG_MARKER_ORIENT_ANGLE
||
134 aEndVal
.mU
.mOrient
.mOrientType
!= SVG_MARKER_ORIENT_ANGLE
) {
135 // TODO: it would be nice to be able to handle auto angles too.
136 return NS_ERROR_FAILURE
;
139 float start
= aStartVal
.mU
.mOrient
.mAngle
*
140 nsSVGAngle::GetDegreesPerUnit(aStartVal
.mU
.mOrient
.mUnit
);
141 float end
= aEndVal
.mU
.mOrient
.mAngle
*
142 nsSVGAngle::GetDegreesPerUnit(aEndVal
.mU
.mOrient
.mUnit
);
143 float result
= (start
+ (end
- start
) * aUnitDistance
);
145 // Again, we use the unit of the to/by value for the result:
146 aResult
.mU
.mOrient
.mAngle
= result
/
147 nsSVGAngle::GetDegreesPerUnit(aEndVal
.mU
.mOrient
.mUnit
);
148 aResult
.mU
.mOrient
.mUnit
= aEndVal
.mU
.mOrient
.mUnit
;
153 } // namespace mozilla