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_dom_SVGSVGElement_h
8 : #define mozilla_dom_SVGSVGElement_h
9 :
10 : #include "SVGViewportElement.h"
11 :
12 : nsresult NS_NewSVGSVGElement(nsIContent **aResult,
13 : already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
14 : mozilla::dom::FromParser aFromParser);
15 :
16 : class nsSMILTimeContainer;
17 :
18 : namespace mozilla {
19 : class AutoSVGViewHandler;
20 : class SVGFragmentIdentifier;
21 : class EventChainPreVisitor;
22 : class DOMSVGLength;
23 : class DOMSVGNumber;
24 :
25 : namespace dom {
26 : class SVGAngle;
27 : class SVGMatrix;
28 : class SVGIRect;
29 : class SVGSVGElement;
30 :
31 : // Stores svgView arguments of SVG fragment identifiers.
32 0 : class SVGView {
33 : public:
34 : SVGView();
35 :
36 : nsSVGEnum mZoomAndPan;
37 : nsSVGViewBox mViewBox;
38 : SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
39 : nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
40 : };
41 :
42 : class DOMSVGTranslatePoint final : public nsISVGPoint {
43 : public:
44 0 : DOMSVGTranslatePoint(SVGPoint* aPt, SVGSVGElement* aElement)
45 0 : : nsISVGPoint(aPt, true), mElement(aElement) {}
46 :
47 : explicit DOMSVGTranslatePoint(DOMSVGTranslatePoint* aPt)
48 : : nsISVGPoint(&aPt->mPt, true), mElement(aPt->mElement) {}
49 :
50 : NS_DECL_ISUPPORTS_INHERITED
51 0 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMSVGTranslatePoint, nsISVGPoint)
52 :
53 : virtual DOMSVGPoint* Copy() override;
54 :
55 : // WebIDL
56 0 : virtual float X() override { return mPt.GetX(); }
57 0 : virtual float Y() override { return mPt.GetY(); }
58 : virtual void SetX(float aValue, ErrorResult& rv) override;
59 : virtual void SetY(float aValue, ErrorResult& rv) override;
60 : virtual already_AddRefed<nsISVGPoint> MatrixTransform(SVGMatrix& matrix) override;
61 :
62 : virtual nsISupports* GetParentObject() override;
63 :
64 : RefPtr<SVGSVGElement> mElement;
65 :
66 : private:
67 0 : ~DOMSVGTranslatePoint() {}
68 : };
69 :
70 : typedef SVGViewportElement SVGSVGElementBase;
71 :
72 : class SVGSVGElement final : public SVGSVGElementBase
73 : {
74 : friend class ::nsSVGOuterSVGFrame;
75 : friend class mozilla::SVGFragmentIdentifier;
76 : friend class mozilla::AutoSVGViewHandler;
77 : friend class mozilla::AutoPreserveAspectRatioOverride;
78 : friend class mozilla::dom::SVGView;
79 :
80 : protected:
81 : SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
82 : FromParser aFromParser);
83 : virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
84 :
85 : friend nsresult (::NS_NewSVGSVGElement(nsIContent **aResult,
86 : already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
87 : mozilla::dom::FromParser aFromParser));
88 :
89 : ~SVGSVGElement();
90 :
91 : public:
92 : // interfaces:
93 : NS_DECL_ISUPPORTS_INHERITED
94 22 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement, SVGSVGElementBase)
95 :
96 : /**
97 : * For use by zoom controls to allow currentScale, currentTranslate.x and
98 : * currentTranslate.y to be set by a single operation that dispatches a
99 : * single SVGZoom event (instead of one SVGZoom and two SVGScroll events).
100 : *
101 : * XXX SVGZoomEvent is no more, is this needed?
102 : */
103 : void SetCurrentScaleTranslate(float s, float x, float y);
104 :
105 : // nsIContent interface
106 : virtual nsresult GetEventTargetParent(
107 : EventChainPreVisitor& aVisitor) override;
108 : virtual bool IsEventAttributeNameInternal(nsIAtom* aName) override;
109 :
110 : // nsINode methods:
111 : virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
112 : bool aPreallocateChildren) const override;
113 :
114 : // WebIDL
115 : already_AddRefed<SVGAnimatedLength> X();
116 : already_AddRefed<SVGAnimatedLength> Y();
117 : already_AddRefed<SVGAnimatedLength> Width();
118 : already_AddRefed<SVGAnimatedLength> Height();
119 : float PixelUnitToMillimeterX();
120 : float PixelUnitToMillimeterY();
121 : float ScreenPixelToMillimeterX();
122 : float ScreenPixelToMillimeterY();
123 : bool UseCurrentView();
124 : float CurrentScale();
125 : void SetCurrentScale(float aCurrentScale);
126 : already_AddRefed<nsISVGPoint> CurrentTranslate();
127 : void SetCurrentTranslate(float x, float y);
128 : uint32_t SuspendRedraw(uint32_t max_wait_milliseconds);
129 : void UnsuspendRedraw(uint32_t suspend_handle_id);
130 : void UnsuspendRedrawAll();
131 : void ForceRedraw();
132 : void PauseAnimations();
133 : void UnpauseAnimations();
134 : bool AnimationsPaused();
135 : float GetCurrentTime();
136 : void SetCurrentTime(float seconds);
137 : void DeselectAll();
138 : already_AddRefed<DOMSVGNumber> CreateSVGNumber();
139 : already_AddRefed<DOMSVGLength> CreateSVGLength();
140 : already_AddRefed<SVGAngle> CreateSVGAngle();
141 : already_AddRefed<nsISVGPoint> CreateSVGPoint();
142 : already_AddRefed<SVGMatrix> CreateSVGMatrix();
143 : already_AddRefed<SVGIRect> CreateSVGRect();
144 : already_AddRefed<SVGTransform> CreateSVGTransform();
145 : already_AddRefed<SVGTransform> CreateSVGTransformFromMatrix(SVGMatrix& matrix);
146 : using nsINode::GetElementById; // This does what we want
147 : uint16_t ZoomAndPan();
148 : void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
149 :
150 : // nsSVGElement overrides
151 :
152 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
153 : nsIContent* aBindingParent,
154 : bool aCompileEventHandlers) override;
155 : virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
156 : virtual nsSVGAnimatedTransformList*
157 : GetAnimatedTransformList(uint32_t aFlags = 0) override;
158 :
159 : // SVGSVGElement methods:
160 :
161 : // Returns true IFF our attributes are currently overridden by a <view>
162 : // element and that element's ID matches the passed-in string.
163 0 : bool IsOverriddenBy(const nsAString &aViewID) const {
164 0 : return mCurrentViewID && mCurrentViewID->Equals(aViewID);
165 : }
166 :
167 : nsSMILTimeContainer* GetTimedDocumentRoot();
168 :
169 : // public helpers:
170 :
171 : /**
172 : * Returns -1 if the width/height is a percentage, else returns the user unit
173 : * length clamped to fit in a int32_t.
174 : * XXX see bug 1112533 comment 3 - we should fix drawImage so that we can
175 : * change these methods to make zero the error flag for percentages.
176 : */
177 : int32_t GetIntrinsicWidth();
178 : int32_t GetIntrinsicHeight();
179 :
180 : // This services any pending notifications for the transform on on this root
181 : // <svg> node needing to be recalculated. (Only applicable in
182 : // SVG-as-an-image documents.)
183 : virtual void FlushImageTransformInvalidation();
184 :
185 43 : svgFloatSize GetViewportSize() const {
186 43 : return svgFloatSize(mViewportWidth, mViewportHeight);
187 : }
188 :
189 22 : void SetViewportSize(const svgFloatSize& aSize) {
190 22 : mViewportWidth = aSize.width;
191 22 : mViewportHeight = aSize.height;
192 22 : }
193 :
194 : private:
195 : // SVGViewportElement methods:
196 :
197 : virtual SVGViewElement* GetCurrentViewElement() const;
198 : virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const override;
199 :
200 : // implementation helpers:
201 :
202 : /*
203 : * While binding to the tree we need to determine if we will be the outermost
204 : * <svg> element _before_ the children are bound (as they want to know what
205 : * timed document root to register with) and therefore _before_ our parent is
206 : * set (both actions are performed by Element::BindToTree) so we
207 : * can't use GetOwnerSVGElement() as it relies on GetParent(). This code is
208 : * basically a simplified version of GetOwnerSVGElement that uses the parent
209 : * parameters passed in instead.
210 : */
211 : bool WillBeOutermostSVG(nsIContent* aParent,
212 : nsIContent* aBindingParent) const;
213 :
214 : // invalidate viewbox -> viewport xform & inform frames
215 : void InvalidateTransformNotifyFrame();
216 :
217 : // Methods for <image> elements to override my "PreserveAspectRatio" value.
218 : // These are private so that only our friends
219 : // (AutoPreserveAspectRatioOverride in particular) have access.
220 : void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
221 : void ClearImageOverridePreserveAspectRatio();
222 :
223 : // Set/Clear properties to hold old version of preserveAspectRatio
224 : // when it's being overridden by an <image> element that we are inside of.
225 : bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR);
226 : const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
227 : bool ClearPreserveAspectRatioProperty();
228 :
229 770 : virtual SVGPoint GetCurrentTranslate() const override
230 770 : { return mCurrentTranslate; }
231 770 : virtual float GetCurrentScale() const override
232 770 : { return mCurrentScale; }
233 :
234 : virtual const nsSVGViewBox& GetViewBoxInternal() const override;
235 : virtual nsSVGAnimatedTransformList* GetTransformInternal() const override;
236 :
237 : virtual EnumAttributesInfo GetEnumInfo() override;
238 :
239 : enum { ZOOMANDPAN };
240 : nsSVGEnum mEnumAttributes[1];
241 : static nsSVGEnumMapping sZoomAndPanMap[];
242 : static EnumInfo sEnumInfo[1];
243 :
244 : // The time container for animations within this SVG document fragment. Set
245 : // for all outermost <svg> elements (not nested <svg> elements).
246 : nsAutoPtr<nsSMILTimeContainer> mTimedDocumentRoot;
247 :
248 : // zoom and pan
249 : // IMPORTANT: see the comment in RecordCurrentScaleTranslate before writing
250 : // code to change any of these!
251 : SVGPoint mCurrentTranslate;
252 : float mCurrentScale;
253 : SVGPoint mPreviousTranslate;
254 : float mPreviousScale;
255 :
256 : // For outermost <svg> elements created from parsing, animation is started by
257 : // the onload event in accordance with the SVG spec, but for <svg> elements
258 : // created by script or promoted from inner <svg> to outermost <svg> we need
259 : // to manually kick off animation when they are bound to the tree.
260 : bool mStartAnimationOnBindToTree;
261 :
262 : bool mImageNeedsTransformInvalidation;
263 :
264 : // mCurrentViewID and mSVGView are mutually exclusive; we can have
265 : // at most one non-null.
266 : nsAutoPtr<nsString> mCurrentViewID;
267 : nsAutoPtr<SVGView> mSVGView;
268 : };
269 :
270 : } // namespace dom
271 :
272 : class MOZ_RAII AutoSVGTimeSetRestore
273 : {
274 : public:
275 18 : AutoSVGTimeSetRestore(dom::SVGSVGElement* aRootElem,
276 : float aFrameTime
277 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
278 18 : : mRootElem(aRootElem)
279 18 : , mOriginalTime(mRootElem->GetCurrentTime())
280 : {
281 18 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
282 18 : mRootElem->SetCurrentTime(aFrameTime); // Does nothing if there's no change.
283 18 : }
284 :
285 18 : ~AutoSVGTimeSetRestore()
286 18 : {
287 18 : mRootElem->SetCurrentTime(mOriginalTime);
288 18 : }
289 :
290 : private:
291 : const RefPtr<dom::SVGSVGElement> mRootElem;
292 : const float mOriginalTime;
293 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
294 : };
295 :
296 : class MOZ_RAII AutoPreserveAspectRatioOverride
297 : {
298 : public:
299 18 : AutoPreserveAspectRatioOverride(const Maybe<SVGImageContext>& aSVGContext,
300 : dom::SVGSVGElement* aRootElem
301 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
302 18 : : mRootElem(aRootElem)
303 18 : , mDidOverride(false)
304 : {
305 18 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
306 18 : MOZ_ASSERT(mRootElem, "No SVG/Symbol node to manage?");
307 :
308 36 : if (aSVGContext.isSome() &&
309 18 : aSVGContext->GetPreserveAspectRatio().isSome()) {
310 : // Override preserveAspectRatio in our helper document.
311 : // XXXdholbert We should technically be overriding the helper doc's clip
312 : // and overflow properties here, too. See bug 272288 comment 36.
313 0 : mRootElem->SetImageOverridePreserveAspectRatio(
314 0 : *aSVGContext->GetPreserveAspectRatio());
315 0 : mDidOverride = true;
316 : }
317 18 : }
318 :
319 18 : ~AutoPreserveAspectRatioOverride()
320 18 : {
321 18 : if (mDidOverride) {
322 0 : mRootElem->ClearImageOverridePreserveAspectRatio();
323 : }
324 18 : }
325 :
326 : private:
327 : const RefPtr<dom::SVGSVGElement> mRootElem;
328 : bool mDidOverride;
329 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
330 : };
331 :
332 : } // namespace mozilla
333 :
334 : #endif // SVGSVGElement_h
|