Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / svg / SVGAnimatedLength.h
blob0c33298b8127bf090c41546948d7f7e1b9ee7744
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 "nsError.h"
18 struct GeckoFontMetrics;
19 class nsPresContext;
20 class nsFontMetrics;
21 class mozAutoDocUpdate;
22 class nsIFrame;
24 namespace mozilla {
26 class AutoChangeLengthNotifier;
27 class SMILValue;
29 namespace dom {
30 class DOMSVGAnimatedLength;
31 class DOMSVGLength;
32 class SVGAnimationElement;
33 class SVGViewportElement;
35 class UserSpaceMetrics {
36 public:
37 enum class Type : uint32_t { This, Root };
38 static GeckoFontMetrics DefaultFontMetrics();
39 static GeckoFontMetrics GetFontMetrics(const Element* aElement);
40 static WritingMode GetWritingMode(const Element* aElement);
41 static float GetZoom(const Element* aElement);
42 static CSSSize GetCSSViewportSizeFromContext(const nsPresContext* aContext);
44 virtual ~UserSpaceMetrics() = default;
46 virtual float GetEmLength(Type aType) const = 0;
47 virtual float GetZoom() const = 0;
48 virtual float GetRootZoom() const = 0;
49 float GetExLength(Type aType) const;
50 float GetChSize(Type aType) const;
51 float GetIcWidth(Type aType) const;
52 float GetCapHeight(Type aType) const;
53 virtual float GetAxisLength(uint8_t aCtxType) const = 0;
54 virtual CSSSize GetCSSViewportSize() const = 0;
55 virtual float GetLineHeight(Type aType) const = 0;
57 protected:
58 virtual GeckoFontMetrics GetFontMetricsForType(Type aType) const = 0;
59 virtual WritingMode GetWritingModeForType(Type aType) const = 0;
62 class UserSpaceMetricsWithSize : public UserSpaceMetrics {
63 public:
64 virtual gfx::Size GetSize() const = 0;
65 float GetAxisLength(uint8_t aCtxType) const override;
68 class SVGElementMetrics final : public UserSpaceMetrics {
69 public:
70 explicit SVGElementMetrics(const SVGElement* aSVGElement,
71 const SVGViewportElement* aCtx = nullptr);
73 float GetEmLength(Type aType) const override {
74 return SVGContentUtils::GetFontSize(GetElementForType(aType));
76 float GetAxisLength(uint8_t aCtxType) const override;
77 CSSSize GetCSSViewportSize() const override;
78 float GetLineHeight(Type aType) const override;
79 float GetZoom() const override;
80 float GetRootZoom() const override;
82 private:
83 bool EnsureCtx() const;
84 const Element* GetElementForType(Type aType) const;
85 GeckoFontMetrics GetFontMetricsForType(Type aType) const override;
86 WritingMode GetWritingModeForType(Type aType) const override;
88 const SVGElement* mSVGElement;
89 mutable const SVGViewportElement* mCtx;
92 class NonSVGFrameUserSpaceMetrics final : public UserSpaceMetricsWithSize {
93 public:
94 explicit NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame);
96 float GetEmLength(Type aType) const override;
97 gfx::Size GetSize() const override;
98 CSSSize GetCSSViewportSize() const override;
99 float GetLineHeight(Type aType) const override;
100 float GetZoom() const override;
101 float GetRootZoom() const override;
103 private:
104 GeckoFontMetrics GetFontMetricsForType(Type aType) const override;
105 WritingMode GetWritingModeForType(Type aType) const override;
106 nsIFrame* mFrame;
109 } // namespace dom
111 class SVGAnimatedLength {
112 friend class AutoChangeLengthNotifier;
113 friend class dom::DOMSVGAnimatedLength;
114 friend class dom::DOMSVGLength;
115 using DOMSVGLength = dom::DOMSVGLength;
116 using SVGElement = dom::SVGElement;
117 using SVGViewportElement = dom::SVGViewportElement;
118 using UserSpaceMetrics = dom::UserSpaceMetrics;
120 public:
121 void Init(uint8_t aCtxType = SVGContentUtils::XY, uint8_t aAttrEnum = 0xff,
122 float aValue = 0,
123 uint8_t aUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {
124 mAnimVal = mBaseVal = aValue;
125 mBaseUnitType = mAnimUnitType = aUnitType;
126 mAttrEnum = aAttrEnum;
127 mCtxType = aCtxType;
128 mIsAnimated = false;
129 mIsBaseSet = false;
132 SVGAnimatedLength& operator=(const SVGAnimatedLength& aLength) {
133 mBaseVal = aLength.mBaseVal;
134 mAnimVal = aLength.mAnimVal;
135 mBaseUnitType = aLength.mBaseUnitType;
136 mAnimUnitType = aLength.mAnimUnitType;
137 mIsAnimated = aLength.mIsAnimated;
138 mIsBaseSet = aLength.mIsBaseSet;
139 return *this;
142 nsresult SetBaseValueString(const nsAString& aValue, SVGElement* aSVGElement,
143 bool aDoSetAttr);
144 void GetBaseValueString(nsAString& aValue) const;
145 void GetAnimValueString(nsAString& aValue) const;
147 float GetBaseValue(const SVGElement* aSVGElement) const {
148 return mBaseVal * GetPixelsPerUnit(aSVGElement, mBaseUnitType);
151 float GetAnimValue(const SVGElement* aSVGElement) const {
152 return mAnimVal * GetPixelsPerUnit(aSVGElement, mAnimUnitType);
154 float GetAnimValueWithZoom(const SVGElement* aSVGElement) const {
155 return mAnimVal * GetPixelsPerUnitWithZoom(aSVGElement, mAnimUnitType);
157 float GetAnimValueWithZoom(nsIFrame* aFrame) const {
158 return mAnimVal * GetPixelsPerUnitWithZoom(aFrame, mAnimUnitType);
160 float GetAnimValueWithZoom(const SVGViewportElement* aCtx) const {
161 return mAnimVal * GetPixelsPerUnitWithZoom(aCtx, mAnimUnitType);
163 float GetAnimValueWithZoom(const UserSpaceMetrics& aMetrics) const {
164 return mAnimVal * GetPixelsPerUnitWithZoom(aMetrics, mAnimUnitType);
167 uint8_t GetCtxType() const { return mCtxType; }
168 uint8_t GetBaseUnitType() const { return mBaseUnitType; }
169 uint8_t GetAnimUnitType() const { return mAnimUnitType; }
170 bool IsPercentage() const {
171 return mAnimUnitType == dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
173 float GetAnimValInSpecifiedUnits() const { return mAnimVal; }
174 float GetBaseValInSpecifiedUnits() const { return mBaseVal; }
176 bool HasBaseVal() const { return mIsBaseSet; }
177 // Returns true if the animated value of this length has been explicitly
178 // set (either by animation, or by taking on the base value which has been
179 // explicitly set by markup or a DOM call), false otherwise.
180 // If this returns false, the animated value is still valid, that is,
181 // usable, and represents the default base value of the attribute.
182 bool IsExplicitlySet() const { return mIsAnimated || mIsBaseSet; }
184 bool IsAnimated() const { return mIsAnimated; }
186 already_AddRefed<dom::DOMSVGAnimatedLength> ToDOMAnimatedLength(
187 SVGElement* aSVGElement);
189 UniquePtr<SMILAttr> ToSMILAttr(SVGElement* aSVGElement);
191 private:
192 float mAnimVal;
193 float mBaseVal;
194 uint8_t mBaseUnitType;
195 uint8_t mAnimUnitType;
196 uint8_t mAttrEnum : 6; // element specified tracking for attribute
197 uint8_t mCtxType : 2; // X, Y or Unspecified
198 bool mIsAnimated : 1;
199 bool mIsBaseSet : 1;
201 // These APIs returns the number of user-unit pixels per unit of the
202 // given type, in a given context (frame/element/etc).
203 float GetPixelsPerUnit(const SVGElement* aSVGElement,
204 uint8_t aUnitType) const;
205 float GetPixelsPerUnitWithZoom(nsIFrame* aFrame, uint8_t aUnitType) const;
206 float GetPixelsPerUnitWithZoom(const UserSpaceMetrics& aMetrics,
207 uint8_t aUnitType) const;
208 float GetPixelsPerUnitWithZoom(const SVGElement* aSVGElement,
209 uint8_t aUnitType) const;
210 float GetPixelsPerUnitWithZoom(const SVGViewportElement* aCtx,
211 uint8_t aUnitType) const;
213 // SetBaseValue and SetAnimValue set the value in user units. This may fail
214 // if unit conversion fails e.g. conversion to ex or em units where the
215 // font-size is 0.
216 // SetBaseValueInSpecifiedUnits and SetAnimValueInSpecifiedUnits do not
217 // perform unit conversion and are therefore infallible.
218 nsresult SetBaseValue(float aValue, SVGElement* aSVGElement, bool aDoSetAttr);
219 void SetBaseValueInSpecifiedUnits(float aValue, SVGElement* aSVGElement,
220 bool aDoSetAttr);
221 void SetAnimValue(float aValue, uint16_t aUnitType, SVGElement* aSVGElement);
222 void SetAnimValueInSpecifiedUnits(float aValue, SVGElement* aSVGElement);
223 nsresult NewValueSpecifiedUnits(uint16_t aUnitType,
224 float aValueInSpecifiedUnits,
225 SVGElement* aSVGElement);
226 nsresult ConvertToSpecifiedUnits(uint16_t aUnitType, SVGElement* aSVGElement);
227 already_AddRefed<DOMSVGLength> ToDOMBaseVal(SVGElement* aSVGElement);
228 already_AddRefed<DOMSVGLength> ToDOMAnimVal(SVGElement* aSVGElement);
230 public:
231 struct SMILLength : public SMILAttr {
232 public:
233 SMILLength(SVGAnimatedLength* aVal, SVGElement* aSVGElement)
234 : mVal(aVal), mSVGElement(aSVGElement) {}
236 // These will stay alive because a SMILAttr only lives as long
237 // as the Compositing step, and DOM elements don't get a chance to
238 // die during that.
239 SVGAnimatedLength* mVal;
240 SVGElement* mSVGElement;
242 // SMILAttr methods
243 nsresult ValueFromString(const nsAString& aStr,
244 const dom::SVGAnimationElement* aSrcElement,
245 SMILValue& aValue,
246 bool& aPreventCachingOfSandwich) const override;
247 SMILValue GetBaseValue() const override;
248 void ClearAnimValue() override;
249 nsresult SetAnimValue(const SMILValue& aValue) override;
254 * This class is used by the SMIL code when a length is to be stored in a
255 * SMILValue instance. Since SMILValue objects may be cached, it is necessary
256 * for us to hold a strong reference to our element so that it doesn't
257 * disappear out from under us if, say, the element is removed from the DOM
258 * tree.
260 class SVGLengthAndInfo {
261 public:
262 SVGLengthAndInfo() = default;
264 explicit SVGLengthAndInfo(dom::SVGElement* aElement)
265 : mElement(do_GetWeakReference(aElement->AsNode())) {}
267 void SetInfo(dom::SVGElement* aElement) {
268 mElement = do_GetWeakReference(aElement->AsNode());
271 dom::SVGElement* Element() const {
272 nsCOMPtr<nsIContent> e = do_QueryReferent(mElement);
273 return static_cast<dom::SVGElement*>(e.get());
276 bool operator==(const SVGLengthAndInfo& rhs) const {
277 return mValue == rhs.mValue && mUnitType == rhs.mUnitType &&
278 mCtxType == rhs.mCtxType;
281 float Value() const { return mValue; }
283 uint8_t UnitType() const { return mUnitType; }
285 void CopyFrom(const SVGLengthAndInfo& rhs) {
286 mElement = rhs.mElement;
287 mValue = rhs.mValue;
288 mUnitType = rhs.mUnitType;
289 mCtxType = rhs.mCtxType;
292 float ConvertUnits(const SVGLengthAndInfo& aTo) const;
294 float ValueInPixels(const dom::UserSpaceMetrics& aMetrics) const;
296 void Add(const SVGLengthAndInfo& aValueToAdd, uint32_t aCount);
298 static void Interpolate(const SVGLengthAndInfo& aStart,
299 const SVGLengthAndInfo& aEnd, double aUnitDistance,
300 SVGLengthAndInfo& aResult);
303 * Enables SVGAnimatedLength values to be copied into SVGLengthAndInfo
304 * objects. Note that callers should also call SetInfo() when using this
305 * method!
307 void CopyBaseFrom(const SVGAnimatedLength& rhs) {
308 mValue = rhs.GetBaseValInSpecifiedUnits();
309 mUnitType = rhs.GetBaseUnitType();
310 mCtxType = rhs.GetCtxType();
313 void Set(float aValue, uint8_t aUnitType, uint8_t aCtxType) {
314 mValue = aValue;
315 mUnitType = aUnitType;
316 mCtxType = aCtxType;
319 private:
320 // We must keep a weak reference to our element because we may belong to a
321 // cached baseVal SMILValue. See the comments starting at:
322 // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
323 // See also https://bugzilla.mozilla.org/show_bug.cgi?id=653497
324 nsWeakPtr mElement;
325 float mValue = 0.0f;
326 uint8_t mUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER;
327 uint8_t mCtxType = SVGContentUtils::XY;
330 } // namespace mozilla
332 #endif // DOM_SVG_SVGANIMATEDLENGTH_H_