SVGAnimatedViewBox.h (5381B)
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/. */ 6 7 #ifndef DOM_SVG_SVGANIMATEDVIEWBOX_H_ 8 #define DOM_SVG_SVGANIMATEDVIEWBOX_H_ 9 10 #include "SVGAttrTearoffTable.h" 11 #include "mozilla/SMILAttr.h" 12 #include "mozilla/UniquePtr.h" 13 #include "mozilla/dom/SVGAnimatedRect.h" 14 #include "nsCycleCollectionParticipant.h" 15 #include "nsError.h" 16 17 namespace mozilla { 18 19 class SMILValue; 20 21 namespace dom { 22 class SVGRect; 23 class SVGAnimationElement; 24 class SVGElement; 25 } // namespace dom 26 27 struct SVGViewBox { 28 float x, y; 29 float width, height; 30 bool none; 31 32 SVGViewBox() : x(0.0), y(0.0), width(0.0), height(0.0), none(true) {} 33 SVGViewBox(float aX, float aY, float aWidth, float aHeight) 34 : x(aX), y(aY), width(aWidth), height(aHeight), none(false) {} 35 bool operator==(const SVGViewBox& aOther) const; 36 SVGViewBox operator*(const float m) const { 37 return SVGViewBox(x * m, y * m, width * m, height * m); 38 } 39 40 bool IsFinite() const { 41 if (none) { 42 return true; 43 } 44 return std::isfinite(x) && std::isfinite(y) && std::isfinite(width) && 45 std::isfinite(height); 46 } 47 48 bool IsEmpty() const { return !none && (width <= .0f || height <= .0f); } 49 50 bool IsValid() const { return IsFinite() && !IsEmpty(); } 51 52 friend std::ostream& operator<<(std::ostream& stream, 53 const SVGViewBox& aViewBox) { 54 if (aViewBox.none) { 55 return stream << "(none)"; 56 } 57 return stream << "(x=" << aViewBox.x << ", y=" << aViewBox.y 58 << ", w=" << aViewBox.width << ", h=" << aViewBox.height 59 << ')'; 60 } 61 62 static nsresult FromString(const nsAString& aStr, SVGViewBox* aViewBox); 63 }; 64 65 class SVGAnimatedViewBox { 66 public: 67 friend class AutoChangeViewBoxNotifier; 68 using SVGElement = dom::SVGElement; 69 70 SVGAnimatedViewBox& operator=(const SVGAnimatedViewBox& aOther) { 71 mBaseVal = aOther.mBaseVal; 72 if (aOther.mAnimVal) { 73 mAnimVal = MakeUnique<SVGViewBox>(*aOther.mAnimVal); 74 } 75 mHasBaseVal = aOther.mHasBaseVal; 76 return *this; 77 } 78 79 void Init(); 80 81 /** 82 * Returns true if the corresponding "viewBox" attribute defined a rectangle 83 * with finite values and nonnegative width/height. 84 * Returns false if the viewBox was set to an invalid 85 * string, or if any of the four rect values were too big to store in a 86 * float, or the width/height are negative. 87 */ 88 bool HasRect() const; 89 90 /** 91 * Returns true if the corresponding "viewBox" attribute either defined a 92 * rectangle with finite values or the special "none" value. 93 */ 94 bool IsExplicitlySet() const { 95 if (mAnimVal || mHasBaseVal) { 96 return GetAnimValue().IsValid(); 97 } 98 return false; 99 } 100 101 const SVGViewBox& GetBaseValue() const { return mBaseVal; } 102 void SetBaseX(float aX, SVGElement* aSVGElement) { 103 SetBaseField(aX, aSVGElement, mBaseVal.x); 104 } 105 void SetBaseY(float aY, SVGElement* aSVGElement) { 106 SetBaseField(aY, aSVGElement, mBaseVal.y); 107 } 108 void SetBaseWidth(float aWidth, SVGElement* aSVGElement) { 109 SetBaseField(aWidth, aSVGElement, mBaseVal.width); 110 } 111 void SetBaseHeight(float aHeight, SVGElement* aSVGElement) { 112 SetBaseField(aHeight, aSVGElement, mBaseVal.height); 113 } 114 void SetBaseValue(const SVGViewBox& aRect, SVGElement* aSVGElement, 115 bool aDoSetAttr); 116 const SVGViewBox& GetAnimValue() const { 117 return mAnimVal ? *mAnimVal : mBaseVal; 118 } 119 void SetAnimValue(const SVGViewBox& aRect, SVGElement* aSVGElement); 120 121 nsresult SetBaseValueString(const nsAString& aValue, SVGElement* aSVGElement, 122 bool aDoSetAttr); 123 void GetBaseValueString(nsAString& aValue) const; 124 125 already_AddRefed<dom::SVGAnimatedRect> ToSVGAnimatedRect( 126 SVGElement* aSVGElement); 127 128 already_AddRefed<dom::SVGRect> ToDOMBaseVal(SVGElement* aSVGElement); 129 130 already_AddRefed<dom::SVGRect> ToDOMAnimVal(SVGElement* aSVGElement); 131 132 UniquePtr<SMILAttr> ToSMILAttr(SVGElement* aSVGElement); 133 134 private: 135 void SetBaseField(float aHeight, SVGElement* aSVGElement, float& aElement); 136 137 SVGViewBox mBaseVal; 138 UniquePtr<SVGViewBox> mAnimVal; 139 bool mHasBaseVal; 140 141 public: 142 struct SMILViewBox : public SMILAttr { 143 public: 144 SMILViewBox(SVGAnimatedViewBox* aVal, SVGElement* aSVGElement) 145 : mVal(aVal), mSVGElement(aSVGElement) {} 146 147 // These will stay alive because a SMILAttr only lives as long 148 // as the Compositing step, and DOM elements don't get a chance to 149 // die during that. 150 SVGAnimatedViewBox* mVal; 151 SVGElement* mSVGElement; 152 153 // SMILAttr methods 154 nsresult ValueFromString(const nsAString& aStr, 155 const dom::SVGAnimationElement* aSrcElement, 156 SMILValue& aValue, 157 bool& aPreventCachingOfSandwich) const override; 158 SMILValue GetBaseValue() const override; 159 void ClearAnimValue() override; 160 nsresult SetAnimValue(const SMILValue& aValue) override; 161 }; 162 163 static SVGAttrTearoffTable<SVGAnimatedViewBox, dom::SVGAnimatedRect> 164 sSVGAnimatedRectTearoffTable; 165 }; 166 167 } // namespace mozilla 168 169 #endif // DOM_SVG_SVGANIMATEDVIEWBOX_H_