Line data Source code
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 MOZILLA_DOMSVGLENGTH_H__
8 : #define MOZILLA_DOMSVGLENGTH_H__
9 :
10 : #include "DOMSVGLengthList.h"
11 : #include "nsCycleCollectionParticipant.h"
12 : #include "nsDebug.h"
13 : #include "nsIDOMSVGLength.h"
14 : #include "nsTArray.h"
15 : #include "SVGLength.h"
16 : #include "mozilla/Attributes.h"
17 : #include "nsWrapperCache.h"
18 :
19 : class nsSVGElement;
20 :
21 : // We make DOMSVGLength a pseudo-interface to allow us to QI to it in order to
22 : // check that the objects that scripts pass to DOMSVGLengthList methods are our
23 : // *native* length objects.
24 : //
25 : // {A8468350-7F7B-4976-9A7E-3765A1DADF9A}
26 : #define MOZILLA_DOMSVGLENGTH_IID \
27 : { 0xA8468350, 0x7F7B, 0x4976, { 0x9A, 0x7E, 0x37, 0x65, 0xA1, 0xDA, 0xDF, 0x9A } }
28 :
29 : #define MOZ_SVG_LIST_INDEX_BIT_COUNT 22 // supports > 4 million list items
30 :
31 : namespace mozilla {
32 :
33 : class ErrorResult;
34 :
35 : /**
36 : * Class DOMSVGLength
37 : *
38 : * This class creates the DOM objects that wrap internal SVGLength objects that
39 : * are in an SVGLengthList. It is also used to create the objects returned by
40 : * SVGSVGElement.createSVGLength().
41 : *
42 : * For the DOM wrapper classes for non-list SVGLength, see nsSVGLength2.h.
43 : *
44 : * See the architecture comment in DOMSVGAnimatedLengthList.h.
45 : *
46 : * This class is strongly intertwined with DOMSVGAnimatedLengthList and
47 : * DOMSVGLengthList. We are a friend of DOMSVGLengthList, and are responsible
48 : * for nulling out our DOMSVGLengthList's pointer to us when we die, making it
49 : * a real weak pointer.
50 : *
51 : * When objects of this type are in a DOMSVGLengthList they belong to an
52 : * attribute. While they belong to an attribute, the objects' values come from
53 : * their corresponding internal SVGLength objects in the internal SVGLengthList
54 : * objects for the attribute. Getting and setting values of a DOMSVGLength
55 : * requires reading and writing to its internal SVGLength. However, if the
56 : * DOMSVGLength is detached from its DOMSVGLengthList then it first makes a
57 : * copy of its internal SVGLength's value and unit so that it doesn't appear to
58 : * "lose" its value from script's perspective on being removed from the list.
59 : * This means that these DOM tearoffs have space to store these values, even
60 : * though they're not used in the common case.
61 : *
62 : * Objects of this type are also used to reflect the baseVal and animVal of
63 : * a single, non-list SVGLength attribute. Getting and settings values of the
64 : * DOMSVGLength in this case requires reading and writing to the corresponding
65 : * nsSVGLength2 object.
66 : *
67 : * This class also stores its current list index, attribute enum, and whether
68 : * it belongs to a baseVal or animVal list. This is so that objects of this
69 : * type can find their corresponding internal SVGLength.
70 : *
71 : * To use these classes for <length> attributes as well as <list-of-length>
72 : * attributes, we would need to take a bit from mListIndex and use that to
73 : * indicate whether the object belongs to a list or non-list attribute, then
74 : * if-else as appropriate. The bug for doing that work is:
75 : * https://bugzilla.mozilla.org/show_bug.cgi?id=571734
76 : */
77 : class DOMSVGLength final : public nsIDOMSVGLength,
78 : public nsWrapperCache
79 : {
80 : friend class AutoChangeLengthNotifier;
81 :
82 : /**
83 : * Ctor for creating the object returned by nsSVGLength2::ToDOMBaseVal/ToDOMAnimVal
84 : */
85 : DOMSVGLength(nsSVGLength2* aVal, nsSVGElement* aSVGElement, bool aAnimVal);
86 :
87 : ~DOMSVGLength();
88 :
89 : public:
90 : NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGLENGTH_IID)
91 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
92 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGLength)
93 : NS_DECL_NSIDOMSVGLENGTH
94 :
95 : /**
96 : * Generic ctor for DOMSVGLength objects that are created for an attribute.
97 : */
98 : DOMSVGLength(DOMSVGLengthList *aList,
99 : uint8_t aAttrEnum,
100 : uint32_t aListIndex,
101 : bool aIsAnimValItem);
102 :
103 : /**
104 : * Ctor for creating the objects returned by SVGSVGElement.createSVGLength(),
105 : * which do not initially belong to an attribute.
106 : */
107 : DOMSVGLength();
108 :
109 : static already_AddRefed<DOMSVGLength> GetTearOff(nsSVGLength2* aVal,
110 : nsSVGElement* aSVGElement,
111 : bool aAnimVal);
112 :
113 : /**
114 : * Create an unowned copy of a length that is owned or is reflecting a single
115 : * attribute. The caller is responsible for the first AddRef().
116 : */
117 : DOMSVGLength* Copy();
118 :
119 : bool IsInList() const {
120 : return !!mList;
121 : }
122 :
123 : /**
124 : * In future, if this class is used for non-list lengths, this will be
125 : * different to IsInList().
126 : */
127 0 : bool HasOwner() const {
128 0 : return !!mList;
129 : }
130 :
131 : /**
132 : * Returns whether this length object is reflecting a single SVG element
133 : * attribute. This includes the baseVal or animVal of SVGRectElement.x, for
134 : * example, but not an item in an SVGLengthList, such as those in the
135 : * baseVal or animVal of SVGTextElement.x.
136 : */
137 0 : bool IsReflectingAttribute() const {
138 0 : return mVal;
139 : }
140 :
141 : /**
142 : * This method is called to notify this DOM object that it is being inserted
143 : * into a list, and give it the information it needs as a result.
144 : *
145 : * This object MUST NOT already belong to a list when this method is called.
146 : * That's not to say that script can't move these DOM objects between
147 : * lists - it can - it's just that the logic to handle that (and send out
148 : * the necessary notifications) is located elsewhere (in DOMSVGLengthList).)
149 : */
150 : void InsertingIntoList(DOMSVGLengthList *aList,
151 : uint8_t aAttrEnum,
152 : uint32_t aListIndex,
153 : bool aIsAnimValItem);
154 :
155 0 : static uint32_t MaxListIndex() {
156 0 : return (1U << MOZ_SVG_LIST_INDEX_BIT_COUNT) - 1;
157 : }
158 :
159 : /// This method is called to notify this object that its list index changed.
160 0 : void UpdateListIndex(uint32_t aListIndex) {
161 0 : mListIndex = aListIndex;
162 0 : }
163 :
164 : /**
165 : * This method is called to notify this DOM object that it is about to be
166 : * removed from its current DOM list so that it can first make a copy of its
167 : * internal counterpart's values. (If it didn't do this, then it would
168 : * "lose" its value on being removed.)
169 : */
170 : void RemovingFromList();
171 :
172 : SVGLength ToSVGLength();
173 :
174 : // WebIDL
175 : uint16_t UnitType();
176 : float GetValue(ErrorResult& aRv);
177 : void SetValue(float aValue, ErrorResult& aRv);
178 : float ValueInSpecifiedUnits();
179 : void SetValueInSpecifiedUnits(float aValue, ErrorResult& aRv);
180 : // The XPCOM GetValueAsString is good
181 : void SetValueAsString(const nsAString& aValue, ErrorResult& aRv);
182 : void NewValueSpecifiedUnits(uint16_t aUnit, float aValue,
183 : ErrorResult& aRv);
184 : void ConvertToSpecifiedUnits(uint16_t aUnit, ErrorResult& aRv);
185 :
186 0 : nsISupports* GetParentObject() const {
187 0 : auto svgElement = mList ? Element() : mSVGElement.get();
188 0 : return static_cast<nsIDOMSVGElement*> (svgElement);
189 : }
190 :
191 : JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
192 :
193 : private:
194 :
195 0 : nsSVGElement* Element() const {
196 0 : return mList->Element();
197 : }
198 :
199 : uint8_t AttrEnum() const {
200 : return mAttrEnum;
201 : }
202 :
203 : /**
204 : * Get the axis that this length lies along. This method must only be called
205 : * when this object is associated with an element (HasOwner() returns true).
206 : */
207 0 : uint8_t Axis() const {
208 0 : return mList->Axis();
209 : }
210 :
211 : /**
212 : * Get a reference to the internal SVGLength list item that this DOM wrapper
213 : * object currently wraps.
214 : *
215 : * To simplify the code we just have this one method for obtaining both
216 : * baseVal and animVal internal items. This means that animVal items don't
217 : * get const protection, but then our setter methods guard against changing
218 : * animVal items.
219 : */
220 : SVGLength& InternalItem();
221 :
222 : #ifdef DEBUG
223 : bool IndexIsValid();
224 : #endif
225 :
226 : /**
227 : * Clears soon-to-be-invalid weak references in external objects that were
228 : * set up during the creation of this object. This should be called during
229 : * destruction and during cycle collection.
230 : */
231 : void CleanupWeakRefs();
232 :
233 : RefPtr<DOMSVGLengthList> mList;
234 :
235 : // Bounds for the following are checked in the ctor, so be sure to update
236 : // that if you change the capacity of any of the following.
237 :
238 : uint32_t mListIndex:MOZ_SVG_LIST_INDEX_BIT_COUNT;
239 : uint32_t mAttrEnum:4; // supports up to 16 attributes
240 : uint32_t mIsAnimValItem:1;
241 :
242 : // The following members are only used when we're not in a list:
243 : uint32_t mUnit:5; // can handle 31 units (the 10 SVG 1.1 units + rem, vw, vh, wm, calc + future additions)
244 : float mValue;
245 :
246 : // The following members are only used when we have an nsSVGLength2
247 : nsSVGLength2* mVal; // kept alive because it belongs to mSVGElement
248 : RefPtr<nsSVGElement> mSVGElement;
249 : };
250 :
251 : NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGLength, MOZILLA_DOMSVGLENGTH_IID)
252 :
253 : } // namespace mozilla
254 :
255 : #undef MOZ_SVG_LIST_INDEX_BIT_COUNT
256 :
257 : #endif // MOZILLA_DOMSVGLENGTH_H__
|