Bug 1805294 [wpt PR 37463] - WebKit export of https://bugs.webkit.org/show_bug.cgi...
[gecko.git] / dom / svg / SVGAnimatedLength.h
blob1cabfba0400c344c105ec080202ddfdfb38a03e1
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"
17 #include "nsCoord.h"
18 #include "nsCycleCollectionParticipant.h"
19 #include "nsError.h"
20 #include "nsMathUtils.h"
22 class mozAutoDocUpdate;
23 class nsIFrame;
25 namespace mozilla {
27 class AutoChangeLengthNotifier;
28 class SMILValue;
30 namespace dom {
31 class DOMSVGAnimatedLength;
32 class DOMSVGLength;
33 class SVGAnimationElement;
34 class SVGViewportElement;
36 class UserSpaceMetrics {
37 public:
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 {
47 public:
48 virtual gfx::Size GetSize() const = 0;
49 float GetAxisLength(uint8_t aCtxType) const override;
52 class SVGElementMetrics : public UserSpaceMetrics {
53 public:
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;
61 private:
62 bool EnsureCtx() const;
64 SVGElement* mSVGElement;
65 mutable SVGViewportElement* mCtx;
68 class NonSVGFrameUserSpaceMetrics : public UserSpaceMetricsWithSize {
69 public:
70 explicit NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame);
72 float GetEmLength() const override;
73 float GetExLength() const override;
74 gfx::Size GetSize() const override;
76 private:
77 nsIFrame* mFrame;
80 } // namespace dom
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;
91 public:
92 void Init(uint8_t aCtxType = SVGContentUtils::XY, uint8_t aAttrEnum = 0xff,
93 float aValue = 0,
94 uint8_t aUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {
95 mAnimVal = mBaseVal = aValue;
96 mSpecifiedUnitType = aUnitType;
97 mAttrEnum = aAttrEnum;
98 mCtxType = aCtxType;
99 mIsAnimated = false;
100 mIsBaseSet = false;
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;
109 return *this;
112 nsresult SetBaseValueString(const nsAString& aValue, SVGElement* aSVGElement,
113 bool aDoSetAttr);
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);
162 private:
163 float mAnimVal;
164 float mBaseVal;
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;
169 bool mIsBaseSet : 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
181 // font-size is 0.
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,
186 bool aDoSetAttr);
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);
196 public:
197 struct SMILLength : public SMILAttr {
198 public:
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
204 // die during that.
205 SVGAnimatedLength* mVal;
206 SVGElement* mSVGElement;
208 // SMILAttr methods
209 nsresult ValueFromString(const nsAString& aStr,
210 const dom::SVGAnimationElement* aSrcElement,
211 SMILValue& aValue,
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_