DOMSVGLength.h (8442B)
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_DOMSVGLENGTH_H_ 8 #define DOM_SVG_DOMSVGLENGTH_H_ 9 10 #include "DOMSVGLengthList.h" 11 #include "SVGLength.h" 12 #include "nsCycleCollectionParticipant.h" 13 #include "nsDebug.h" 14 #include "nsTArray.h" 15 #include "nsWrapperCache.h" 16 17 #define MOZ_SVG_LIST_INDEX_BIT_COUNT 21 // supports > 2 million list items 18 19 namespace mozilla { 20 21 class ErrorResult; 22 23 namespace dom { 24 class SVGElement; 25 26 /** 27 * Class DOMSVGLength 28 * 29 * This class creates the DOM objects that wrap internal SVGLength objects that 30 * are in an SVGLengthList. It is also used to create the objects returned by 31 * SVGSVGElement.createSVGLength(). 32 * 33 * For the DOM wrapper classes for non-list SVGLength, see SVGAnimatedLength.h. 34 * 35 * See the architecture comment in DOMSVGAnimatedLengthList.h. 36 * 37 * This class is strongly intertwined with DOMSVGAnimatedLengthList and 38 * DOMSVGLengthList. We are a friend of DOMSVGLengthList, and are responsible 39 * for nulling out our DOMSVGLengthList's pointer to us when we die, making it 40 * a real weak pointer. 41 * 42 * When objects of this type are in a DOMSVGLengthList they belong to an 43 * attribute. While they belong to an attribute, the objects' values come from 44 * their corresponding internal SVGLength objects in the internal SVGLengthList 45 * objects for the attribute. Getting and setting values of a DOMSVGLength 46 * requires reading and writing to its internal SVGLength. However, if the 47 * DOMSVGLength is detached from its DOMSVGLengthList then it first makes a 48 * copy of its internal SVGLength's value and unit so that it doesn't appear to 49 * "lose" its value from script's perspective on being removed from the list. 50 * This means that these DOM tearoffs have space to store these values, even 51 * though they're not used in the common case. 52 * 53 * Objects of this type are also used to reflect the baseVal and animVal of 54 * a single, non-list SVGLength attribute. Getting and settings values of the 55 * DOMSVGLength in this case requires reading and writing to the corresponding 56 * SVGAnimatedLength object. 57 * 58 * This class also stores its current list index, attribute enum, and whether 59 * it belongs to a baseVal or animVal list. This is so that objects of this 60 * type can find their corresponding internal SVGLength. 61 * 62 * To use these classes for <length> attributes as well as <list-of-length> 63 * attributes, we would need to take a bit from mListIndex and use that to 64 * indicate whether the object belongs to a list or non-list attribute, then 65 * if-else as appropriate. The bug for doing that work is: 66 * https://bugzilla.mozilla.org/show_bug.cgi?id=571734 67 */ 68 class DOMSVGLength final : public nsWrapperCache { 69 template <class T> 70 friend class AutoChangeLengthListNotifier; 71 72 /** 73 * Ctor for creating the object returned by 74 * SVGAnimatedLength::ToDOMBaseVal/ToDOMAnimVal 75 */ 76 DOMSVGLength(SVGAnimatedLength* aVal, dom::SVGElement* aSVGElement, 77 bool aAnimVal); 78 79 ~DOMSVGLength() { CleanupWeakRefs(); } 80 81 public: 82 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMSVGLength) 83 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMSVGLength) 84 85 /** 86 * Generic ctor for DOMSVGLength objects that are created for an attribute. 87 */ 88 DOMSVGLength(DOMSVGLengthList* aList, uint8_t aAttrEnum, uint32_t aListIndex, 89 bool aIsAnimValItem); 90 91 /** 92 * Ctor for creating the objects returned by SVGSVGElement.createSVGLength(), 93 * which do not initially belong to an attribute. 94 */ 95 DOMSVGLength(); 96 97 static already_AddRefed<DOMSVGLength> GetTearOff(SVGAnimatedLength* aVal, 98 dom::SVGElement* aSVGElement, 99 bool aAnimVal); 100 101 /** 102 * Create an unowned copy of a length that is owned or is reflecting a single 103 * attribute. The caller is responsible for the first AddRef(). 104 */ 105 DOMSVGLength* Copy(); 106 107 /** 108 * Returns true if our attribute is animating. 109 */ 110 bool IsAnimating() const; 111 112 /** 113 * In future, if this class is used for non-list lengths, this will be 114 * different to IsInList(). 115 */ 116 bool HasOwner() const { return !!mOwner; } 117 118 /** 119 * This method is called to notify this DOM object that it is being inserted 120 * into a list, and give it the information it needs as a result. 121 * 122 * This object MUST NOT already belong to a list when this method is called. 123 * That's not to say that script can't move these DOM objects between 124 * lists - it can - it's just that the logic to handle that (and send out 125 * the necessary notifications) is located elsewhere (in DOMSVGLengthList).) 126 */ 127 void InsertingIntoList(DOMSVGLengthList* aList, uint8_t aAttrEnum, 128 uint32_t aListIndex, bool aIsAnimValItem); 129 130 static uint32_t MaxListIndex() { 131 return (1U << MOZ_SVG_LIST_INDEX_BIT_COUNT) - 1; 132 } 133 134 /// This method is called to notify this object that its list index changed. 135 void UpdateListIndex(uint32_t aListIndex) { mListIndex = aListIndex; } 136 137 /** 138 * This method is called to notify this DOM object that it is about to be 139 * removed from its current DOM list so that it can first make a copy of its 140 * internal counterpart's values. (If it didn't do this, then it would 141 * "lose" its value on being removed.) 142 */ 143 void RemovingFromList(); 144 145 SVGLength ToSVGLength(); 146 147 // WebIDL 148 uint16_t UnitType(); 149 float GetValue(ErrorResult& aRv); 150 void SetValue(float aUserUnitValue, ErrorResult& aRv); 151 float ValueInSpecifiedUnits(); 152 void SetValueInSpecifiedUnits(float aValue, ErrorResult& aRv); 153 void GetValueAsString(nsAString& aValue); 154 void SetValueAsString(const nsAString& aValue, ErrorResult& aRv); 155 void NewValueSpecifiedUnits(uint16_t aUnit, float aValue, ErrorResult& aRv); 156 void ConvertToSpecifiedUnits(uint16_t aUnit, ErrorResult& aRv); 157 158 nsISupports* GetParentObject() { return mOwner; } 159 160 JSObject* WrapObject(JSContext* aCx, 161 JS::Handle<JSObject*> aGivenProto) override; 162 163 private: 164 dom::SVGElement* Element(); 165 166 uint8_t AttrEnum() const { return mAttrEnum; } 167 168 /** 169 * Get a reference to the internal SVGLength list item that this DOM wrapper 170 * object currently wraps. 171 * 172 * To simplify the code we just have this one method for obtaining both 173 * baseVal and animVal internal items. This means that animVal items don't 174 * get const protection, but then our setter methods guard against changing 175 * animVal items. 176 */ 177 SVGLength& InternalItem(); 178 179 /** 180 * Some values have units that depend on style or layout so we may need to 181 * flush to ensure we get or set the right value in pixels. 182 */ 183 void FlushIfNeeded(); 184 185 #ifdef DEBUG 186 bool IndexIsValid(); 187 #endif 188 189 /** 190 * Clears soon-to-be-invalid weak references in external objects that were 191 * set up during the creation of this object. This should be called during 192 * destruction and during cycle collection. 193 */ 194 void CleanupWeakRefs(); 195 196 RefPtr<nsISupports> mOwner; // Either a DOMSVGLengthList if we're in a list, 197 // an SVGElement if we're an attribute or null 198 199 // Bounds for the following are checked in the ctor, so be sure to update 200 // that if you change the capacity of any of the following. 201 202 uint32_t mListIndex : MOZ_SVG_LIST_INDEX_BIT_COUNT; 203 uint32_t mAttrEnum : 4; // supports up to 16 attributes 204 uint32_t mIsAnimValItem : 1; 205 206 // Tracks whether we're in the tearoff table. Initialized to false in the 207 // ctor, but then immediately set to true after we're added to the table 208 // (unless we're an instance created via 'Copy()'; those never get added to 209 // the table). Updated to false when we're removed from the table (at which 210 // point we're being destructed or soon-to-be destructed). 211 uint32_t mIsInTearoffTable : 1; 212 213 // The following members are only used when we're not in a list: 214 uint32_t mUnit : 5; // can handle 31 units (the 10 SVG 1.1 units + rem, vw, 215 // vh, wm, calc + future additions) 216 float mValue = 0.0f; 217 }; 218 219 } // namespace dom 220 } // namespace mozilla 221 222 #undef MOZ_SVG_LIST_INDEX_BIT_COUNT 223 224 #endif // DOM_SVG_DOMSVGLENGTH_H_