SVGAnimatedTransformList.h (5872B)
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_SVGANIMATEDTRANSFORMLIST_H_ 8 #define DOM_SVG_SVGANIMATEDTRANSFORMLIST_H_ 9 10 #include "mozilla/SMILAttr.h" 11 #include "mozilla/UniquePtr.h" 12 #include "mozilla/dom/SVGTransformList.h" 13 14 class nsAtom; 15 16 namespace mozilla { 17 18 class SMILValue; 19 20 namespace dom { 21 class SVGAnimationElement; 22 class SVGElement; 23 class DOMSVGTransform; 24 } // namespace dom 25 26 /** 27 * Class SVGAnimatedTransformList 28 * 29 * This class is very different to the SVG DOM interface of the same name found 30 * in the SVG specification. This is a lightweight internal class - see 31 * DOMSVGAnimatedTransformList for the heavier DOM class that wraps instances of 32 * this class and implements the SVG specification's SVGAnimatedTransformList 33 * DOM interface. 34 * 35 * Except where noted otherwise, this class' methods take care of keeping the 36 * appropriate DOM wrappers in sync (see the comment in 37 * DOMSVGAnimatedTransformList::InternalBaseValListWillChangeTo) so that their 38 * consumers don't need to concern themselves with that. 39 */ 40 class SVGAnimatedTransformList { 41 // friends so that they can get write access to mBaseVal 42 friend class dom::DOMSVGTransform; 43 friend class dom::DOMSVGTransformList; 44 45 public: 46 SVGAnimatedTransformList() 47 : mIsBaseSet(false), mCreatedOrRemovedOnLastChange(true) {} 48 49 SVGAnimatedTransformList& operator=(const SVGAnimatedTransformList& aOther) { 50 mBaseVal = aOther.mBaseVal; 51 if (aOther.mAnimVal) { 52 mAnimVal = MakeUnique<SVGTransformList>(*aOther.mAnimVal); 53 } 54 mIsBaseSet = aOther.mIsBaseSet; 55 mCreatedOrRemovedOnLastChange = aOther.mCreatedOrRemovedOnLastChange; 56 return *this; 57 } 58 59 /** 60 * Because it's so important that mBaseVal and its DOMSVGTransformList wrapper 61 * (if any) be kept in sync (see the comment in 62 * DOMSVGAnimatedTransformList::InternalBaseValListWillChangeTo), this method 63 * returns a const reference. Only our friend classes may get mutable 64 * references to mBaseVal. 65 */ 66 const SVGTransformList& GetBaseValue() const { return mBaseVal; } 67 68 nsresult SetBaseValue(const SVGTransformList& aValue, 69 dom::SVGElement* aSVGElement); 70 71 nsresult SetBaseValueString(const nsAString& aValue, 72 dom::SVGElement* aSVGElement); 73 74 void ClearBaseValue(); 75 76 const SVGTransformList& GetAnimValue() const { 77 return mAnimVal ? *mAnimVal : mBaseVal; 78 } 79 80 nsresult SetAnimValue(const SVGTransformList& aValue, 81 dom::SVGElement* aElement); 82 83 void ClearAnimValue(dom::SVGElement* aElement); 84 85 /** 86 * Returns true if the corresponding transform attribute is set (or animated) 87 * to a valid value. Unlike HasTransform it will return true for an empty 88 * transform. 89 */ 90 bool IsExplicitlySet() const; 91 92 /** 93 * Returns true if the corresponding transform attribute is set (or animated) 94 * to a valid value, such that we have at least one transform in our list. 95 * Returns false otherwise (e.g. if the transform attribute is missing or 96 * empty or invalid). 97 */ 98 bool HasTransform() const { 99 return (mAnimVal && !mAnimVal->IsEmpty()) || !mBaseVal.IsEmpty(); 100 } 101 102 bool IsAnimating() const { return !!mAnimVal; } 103 104 /** 105 * Returns true if the last change of this transform went from having to not 106 * having a transform or vice versa. 107 * 108 * (This is used as part of an optimization in 109 * SVGTransformableElement::GetAttributeChangeHint. That function reports an 110 * inexpensive nsChangeHint when a transform has just modified -- but this 111 * accessor lets it detect cases where the "modification" is actually creating 112 * a transform where we previously had none. These cases require a more 113 * thorough nsChangeHint.) 114 */ 115 bool CreatedOrRemovedOnLastChange() const { 116 return mCreatedOrRemovedOnLastChange; 117 } 118 119 UniquePtr<SMILAttr> ToSMILAttr(dom::SVGElement* aSVGElement); 120 121 private: 122 // mAnimVal is a pointer to allow us to determine if we're being animated or 123 // not. Making it a non-pointer member and using mAnimVal.IsEmpty() to check 124 // if we're animating is not an option, since that would break animation *to* 125 // the empty string (<set to="">). 126 127 SVGTransformList mBaseVal; 128 UniquePtr<SVGTransformList> mAnimVal; 129 bool mIsBaseSet; 130 // See documentation for accessor. 131 bool mCreatedOrRemovedOnLastChange; 132 133 struct SMILAnimatedTransformList : public SMILAttr { 134 public: 135 SMILAnimatedTransformList(SVGAnimatedTransformList* aVal, 136 dom::SVGElement* aSVGElement) 137 : mVal(aVal), mElement(aSVGElement) {} 138 139 // SMILAttr methods 140 nsresult ValueFromString(const nsAString& aStr, 141 const dom::SVGAnimationElement* aSrcElement, 142 SMILValue& aValue, 143 bool& aPreventCachingOfSandwich) const override; 144 SMILValue GetBaseValue() const override; 145 void ClearAnimValue() override; 146 nsresult SetAnimValue(const SMILValue& aNewAnimValue) override; 147 148 protected: 149 static void ParseValue(const nsAString& aSpec, const nsAtom* aTransformType, 150 SMILValue& aResult); 151 static int32_t ParseParameterList(const nsAString& aSpec, float* aVars, 152 int32_t aNVars); 153 154 // These will stay alive because a SMILAttr only lives as long 155 // as the Compositing step, and DOM elements don't get a chance to 156 // die during that. 157 SVGAnimatedTransformList* mVal; 158 dom::SVGElement* mElement; 159 }; 160 }; 161 162 } // namespace mozilla 163 164 #endif // DOM_SVG_SVGANIMATEDTRANSFORMLIST_H_