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 #ifndef DOM_SVG_SVGANIMATEDLENGTH_H_
8 #define DOM_SVG_SVGANIMATEDLENGTH_H_
10 #include "mozilla/Attributes.h"
11 #include "mozilla/SMILAttr.h"
12 #include "mozilla/SVGContentUtils.h"
13 #include "mozilla/UniquePtr.h"
14 #include "mozilla/dom/SVGLengthBinding.h"
15 #include "mozilla/dom/SVGElement.h"
16 #include "mozilla/gfx/Rect.h"
18 #include "nsCycleCollectionParticipant.h"
20 #include "nsMathUtils.h"
22 class mozAutoDocUpdate
;
27 class AutoChangeLengthNotifier
;
31 class DOMSVGAnimatedLength
;
33 class SVGAnimationElement
;
34 class SVGViewportElement
;
36 class UserSpaceMetrics
{
38 static bool ResolveAbsoluteUnit(uint8_t aUnitType
, float& aRes
);
39 virtual ~UserSpaceMetrics() = default;
41 virtual float GetEmLength() const = 0;
42 virtual float GetExLength() const = 0;
43 virtual float GetAxisLength(uint8_t aCtxType
) const = 0;
46 class UserSpaceMetricsWithSize
: public UserSpaceMetrics
{
48 virtual gfx::Size
GetSize() const = 0;
49 float GetAxisLength(uint8_t aCtxType
) const override
;
52 class SVGElementMetrics
: public UserSpaceMetrics
{
54 explicit SVGElementMetrics(SVGElement
* aSVGElement
,
55 SVGViewportElement
* aCtx
= nullptr);
57 float GetEmLength() const override
;
58 float GetExLength() const override
;
59 float GetAxisLength(uint8_t aCtxType
) const override
;
62 bool EnsureCtx() const;
64 SVGElement
* mSVGElement
;
65 mutable SVGViewportElement
* mCtx
;
68 class NonSVGFrameUserSpaceMetrics
: public UserSpaceMetricsWithSize
{
70 explicit NonSVGFrameUserSpaceMetrics(nsIFrame
* aFrame
);
72 float GetEmLength() const override
;
73 float GetExLength() const override
;
74 gfx::Size
GetSize() const override
;
82 class SVGAnimatedLength
{
83 friend class AutoChangeLengthNotifier
;
84 friend class dom::DOMSVGAnimatedLength
;
85 friend class dom::DOMSVGLength
;
86 using DOMSVGLength
= dom::DOMSVGLength
;
87 using SVGElement
= dom::SVGElement
;
88 using SVGViewportElement
= dom::SVGViewportElement
;
89 using UserSpaceMetrics
= dom::UserSpaceMetrics
;
92 void Init(uint8_t aCtxType
= SVGContentUtils::XY
, uint8_t aAttrEnum
= 0xff,
94 uint8_t aUnitType
= dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER
) {
95 mAnimVal
= mBaseVal
= aValue
;
96 mSpecifiedUnitType
= aUnitType
;
97 mAttrEnum
= aAttrEnum
;
103 SVGAnimatedLength
& operator=(const SVGAnimatedLength
& aLength
) {
104 mBaseVal
= aLength
.mBaseVal
;
105 mAnimVal
= aLength
.mAnimVal
;
106 mSpecifiedUnitType
= aLength
.mSpecifiedUnitType
;
107 mIsAnimated
= aLength
.mIsAnimated
;
108 mIsBaseSet
= aLength
.mIsBaseSet
;
112 nsresult
SetBaseValueString(const nsAString
& aValue
, SVGElement
* aSVGElement
,
114 void GetBaseValueString(nsAString
& aValue
) const;
115 void GetAnimValueString(nsAString
& aValue
) const;
117 float GetBaseValue(SVGElement
* aSVGElement
) const {
118 return mBaseVal
* GetPixelsPerUnit(aSVGElement
, mSpecifiedUnitType
);
121 float GetAnimValue(SVGElement
* aSVGElement
) const {
122 return mAnimVal
* GetPixelsPerUnit(aSVGElement
, mSpecifiedUnitType
);
124 float GetAnimValue(nsIFrame
* aFrame
) const {
125 return mAnimVal
* GetPixelsPerUnit(aFrame
, mSpecifiedUnitType
);
127 float GetAnimValue(SVGViewportElement
* aCtx
) const {
128 return mAnimVal
* GetPixelsPerUnit(aCtx
, mSpecifiedUnitType
);
130 float GetAnimValue(const UserSpaceMetrics
& aMetrics
) const {
131 return mAnimVal
* GetPixelsPerUnit(aMetrics
, mSpecifiedUnitType
);
134 uint8_t GetCtxType() const { return mCtxType
; }
135 uint8_t GetSpecifiedUnitType() const { return mSpecifiedUnitType
; }
136 bool IsPercentage() const {
137 return mSpecifiedUnitType
==
138 dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE
;
140 float GetAnimValInSpecifiedUnits() const { return mAnimVal
; }
141 float GetBaseValInSpecifiedUnits() const { return mBaseVal
; }
143 float GetBaseValue(SVGViewportElement
* aCtx
) const {
144 return mBaseVal
* GetPixelsPerUnit(aCtx
, mSpecifiedUnitType
);
147 bool HasBaseVal() const { return mIsBaseSet
; }
148 // Returns true if the animated value of this length has been explicitly
149 // set (either by animation, or by taking on the base value which has been
150 // explicitly set by markup or a DOM call), false otherwise.
151 // If this returns false, the animated value is still valid, that is,
152 // usable, and represents the default base value of the attribute.
153 bool IsExplicitlySet() const { return mIsAnimated
|| mIsBaseSet
; }
155 bool IsAnimated() const { return mIsAnimated
; }
157 already_AddRefed
<dom::DOMSVGAnimatedLength
> ToDOMAnimatedLength(
158 SVGElement
* aSVGElement
);
160 UniquePtr
<SMILAttr
> ToSMILAttr(SVGElement
* aSVGElement
);
165 uint8_t mSpecifiedUnitType
;
166 uint8_t mAttrEnum
; // element specified tracking for attribute
167 uint8_t mCtxType
; // X, Y or Unspecified
168 bool mIsAnimated
: 1;
171 // These APIs returns the number of user-unit pixels per unit of the
172 // given type, in a given context (frame/element/etc).
173 float GetPixelsPerUnit(nsIFrame
* aFrame
, uint8_t aUnitType
) const;
174 float GetPixelsPerUnit(const UserSpaceMetrics
& aMetrics
,
175 uint8_t aUnitType
) const;
176 float GetPixelsPerUnit(SVGElement
* aSVGElement
, uint8_t aUnitType
) const;
177 float GetPixelsPerUnit(SVGViewportElement
* aCtx
, uint8_t aUnitType
) const;
179 // SetBaseValue and SetAnimValue set the value in user units. This may fail
180 // if unit conversion fails e.g. conversion to ex or em units where the
182 // SetBaseValueInSpecifiedUnits and SetAnimValueInSpecifiedUnits do not
183 // perform unit conversion and are therefore infallible.
184 nsresult
SetBaseValue(float aValue
, SVGElement
* aSVGElement
, bool aDoSetAttr
);
185 void SetBaseValueInSpecifiedUnits(float aValue
, SVGElement
* aSVGElement
,
187 nsresult
SetAnimValue(float aValue
, SVGElement
* aSVGElement
);
188 void SetAnimValueInSpecifiedUnits(float aValue
, SVGElement
* aSVGElement
);
189 nsresult
NewValueSpecifiedUnits(uint16_t aUnitType
,
190 float aValueInSpecifiedUnits
,
191 SVGElement
* aSVGElement
);
192 nsresult
ConvertToSpecifiedUnits(uint16_t aUnitType
, SVGElement
* aSVGElement
);
193 already_AddRefed
<DOMSVGLength
> ToDOMBaseVal(SVGElement
* aSVGElement
);
194 already_AddRefed
<DOMSVGLength
> ToDOMAnimVal(SVGElement
* aSVGElement
);
197 struct SMILLength
: public SMILAttr
{
199 SMILLength(SVGAnimatedLength
* aVal
, SVGElement
* aSVGElement
)
200 : mVal(aVal
), mSVGElement(aSVGElement
) {}
202 // These will stay alive because a SMILAttr only lives as long
203 // as the Compositing step, and DOM elements don't get a chance to
205 SVGAnimatedLength
* mVal
;
206 SVGElement
* mSVGElement
;
209 nsresult
ValueFromString(const nsAString
& aStr
,
210 const dom::SVGAnimationElement
* aSrcElement
,
212 bool& aPreventCachingOfSandwich
) const override
;
213 SMILValue
GetBaseValue() const override
;
214 void ClearAnimValue() override
;
215 nsresult
SetAnimValue(const SMILValue
& aValue
) override
;
219 } // namespace mozilla
221 #endif // DOM_SVG_SVGANIMATEDLENGTH_H_