1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_dom_SVGSVGElement_h
7 #define mozilla_dom_SVGSVGElement_h
9 #include "mozilla/dom/FromParser.h"
10 #include "nsISVGPoint.h"
11 #include "nsSVGEnum.h"
12 #include "nsSVGLength2.h"
13 #include "SVGGraphicsElement.h"
14 #include "SVGImageContext.h"
15 #include "nsSVGViewBox.h"
16 #include "SVGPreserveAspectRatio.h"
17 #include "SVGAnimatedPreserveAspectRatio.h"
18 #include "mozilla/Attributes.h"
20 nsresult
NS_NewSVGSVGElement(nsIContent
**aResult
,
21 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
22 mozilla::dom::FromParser aFromParser
);
24 class nsSMILTimeContainer
;
25 class nsSVGOuterSVGFrame
;
26 class nsSVGInnerSVGFrame
;
27 class nsSVGImageFrame
;
30 class AutoSVGRenderingState
;
31 class DOMSVGAnimatedPreserveAspectRatio
;
34 class EventChainPreVisitor
;
35 class SVGFragmentIdentifier
;
39 class SVGAnimatedRect
;
47 class DOMSVGTranslatePoint MOZ_FINAL
: public nsISVGPoint
{
49 DOMSVGTranslatePoint(SVGPoint
* aPt
, SVGSVGElement
*aElement
)
50 : nsISVGPoint(aPt
, true), mElement(aElement
) {}
52 explicit DOMSVGTranslatePoint(DOMSVGTranslatePoint
* aPt
)
53 : nsISVGPoint(&aPt
->mPt
, true), mElement(aPt
->mElement
) {}
55 NS_DECL_ISUPPORTS_INHERITED
56 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMSVGTranslatePoint
, nsISVGPoint
)
58 virtual DOMSVGPoint
* Copy() MOZ_OVERRIDE
;
61 virtual float X() MOZ_OVERRIDE
{ return mPt
.GetX(); }
62 virtual float Y() MOZ_OVERRIDE
{ return mPt
.GetY(); }
63 virtual void SetX(float aValue
, ErrorResult
& rv
) MOZ_OVERRIDE
;
64 virtual void SetY(float aValue
, ErrorResult
& rv
) MOZ_OVERRIDE
;
65 virtual already_AddRefed
<nsISVGPoint
> MatrixTransform(SVGMatrix
& matrix
) MOZ_OVERRIDE
;
67 virtual nsISupports
* GetParentObject() MOZ_OVERRIDE
;
69 nsRefPtr
<SVGSVGElement
> mElement
;
72 ~DOMSVGTranslatePoint() {}
77 svgFloatSize(float aWidth
, float aHeight
)
81 bool operator!=(const svgFloatSize
& rhs
) {
82 return width
!= rhs
.width
|| height
!= rhs
.height
;
88 typedef SVGGraphicsElement SVGSVGElementBase
;
90 class SVGSVGElement MOZ_FINAL
: public SVGSVGElementBase
92 friend class ::nsSVGOuterSVGFrame
;
93 friend class ::nsSVGInnerSVGFrame
;
94 friend class mozilla::SVGFragmentIdentifier
;
95 friend class mozilla::AutoSVGRenderingState
;
97 SVGSVGElement(already_AddRefed
<mozilla::dom::NodeInfo
>& aNodeInfo
,
98 FromParser aFromParser
);
99 virtual JSObject
* WrapNode(JSContext
*aCx
) MOZ_OVERRIDE
;
101 friend nsresult (::NS_NewSVGSVGElement(nsIContent
**aResult
,
102 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
103 mozilla::dom::FromParser aFromParser
));
109 NS_DECL_ISUPPORTS_INHERITED
110 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement
, SVGSVGElementBase
)
113 * For use by zoom controls to allow currentScale, currentTranslate.x and
114 * currentTranslate.y to be set by a single operation that dispatches a
115 * single SVGZoom event (instead of one SVGZoom and two SVGScroll events).
117 void SetCurrentScaleTranslate(float s
, float x
, float y
);
120 * Retrieve the value of currentScale and currentTranslate.
122 const SVGPoint
& GetCurrentTranslate() { return mCurrentTranslate
; }
123 float GetCurrentScale() { return mCurrentScale
; }
126 * Retrieve the value of currentScale, currentTranslate.x or
127 * currentTranslate.y prior to the last change made to any one of them.
129 const SVGPoint
& GetPreviousTranslate() { return mPreviousTranslate
; }
130 float GetPreviousScale() { return mPreviousScale
; }
132 nsSMILTimeContainer
* GetTimedDocumentRoot();
134 // nsIContent interface
135 NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom
* aAttribute
) const MOZ_OVERRIDE
;
136 virtual nsresult
PreHandleEvent(EventChainPreVisitor
& aVisitor
) MOZ_OVERRIDE
;
138 virtual bool IsEventAttributeName(nsIAtom
* aName
) MOZ_OVERRIDE
;
140 // nsSVGElement specializations:
141 virtual gfxMatrix
PrependLocalTransformsTo(const gfxMatrix
&aMatrix
,
142 TransformTypes aWhich
= eAllTransforms
) const MOZ_OVERRIDE
;
143 virtual bool HasValidDimensions() const MOZ_OVERRIDE
;
145 // SVGSVGElement methods:
146 float GetLength(uint8_t mCtxType
);
151 * Returns true if this element has a base/anim value for its "viewBox"
152 * attribute that defines a viewBox rectangle with finite values, or
153 * if there is a view element overriding this element's viewBox and it
154 * has a valid viewBox.
156 * Note that this does not check whether we need to synthesize a viewBox,
157 * so you must call ShouldSynthesizeViewBox() if you need to check that too.
159 * Note also that this method does not pay attention to whether the width or
160 * height values of the viewBox rect are positive!
162 bool HasViewBoxRect() const;
165 * Returns true if we should synthesize a viewBox for ourselves (that is, if
166 * we're the root element in an image document, and we're not currently being
167 * painted for an <svg:image> element).
169 * Only call this method if HasViewBoxRect() returns false.
171 bool ShouldSynthesizeViewBox() const;
173 bool HasViewBoxOrSyntheticViewBox() const {
174 return HasViewBoxRect() || ShouldSynthesizeViewBox();
177 gfx::Matrix
GetViewBoxTransform() const;
179 bool HasChildrenOnlyTransform() const {
180 return mHasChildrenOnlyTransform
;
183 void UpdateHasChildrenOnlyTransform();
185 enum ChildrenOnlyTransformChangedFlags
{
190 * This method notifies the style system that the overflow rects of our
191 * immediate childrens' frames need to be updated. It is called by our own
192 * frame when changes (e.g. to currentScale) cause our children-only
193 * transform to change.
195 * The reason we have this method instead of overriding
196 * GetAttributeChangeHint is because we need to act on non-attribute (e.g.
197 * currentScale) changes in addition to attribute (e.g. viewBox) changes.
199 void ChildrenOnlyTransformChanged(uint32_t aFlags
= 0);
201 // This services any pending notifications for the transform on on this root
202 // <svg> node needing to be recalculated. (Only applicable in
203 // SVG-as-an-image documents.)
204 virtual void FlushImageTransformInvalidation();
206 virtual nsresult
Clone(mozilla::dom::NodeInfo
*aNodeInfo
, nsINode
**aResult
) const MOZ_OVERRIDE
;
208 // Returns true IFF our attributes are currently overridden by a <view>
209 // element and that element's ID matches the passed-in string.
210 bool IsOverriddenBy(const nsAString
&aViewID
) const {
211 return mCurrentViewID
&& mCurrentViewID
->Equals(aViewID
);
214 svgFloatSize
GetViewportSize() const {
215 return svgFloatSize(mViewportWidth
, mViewportHeight
);
218 void SetViewportSize(const svgFloatSize
& aSize
) {
219 mViewportWidth
= aSize
.width
;
220 mViewportHeight
= aSize
.height
;
224 already_AddRefed
<SVGAnimatedLength
> X();
225 already_AddRefed
<SVGAnimatedLength
> Y();
226 already_AddRefed
<SVGAnimatedLength
> Width();
227 already_AddRefed
<SVGAnimatedLength
> Height();
228 float PixelUnitToMillimeterX();
229 float PixelUnitToMillimeterY();
230 float ScreenPixelToMillimeterX();
231 float ScreenPixelToMillimeterY();
232 bool UseCurrentView();
233 float CurrentScale();
234 void SetCurrentScale(float aCurrentScale
);
235 already_AddRefed
<nsISVGPoint
> CurrentTranslate();
236 void SetCurrentTranslate(float x
, float y
);
237 uint32_t SuspendRedraw(uint32_t max_wait_milliseconds
);
238 void UnsuspendRedraw(uint32_t suspend_handle_id
);
239 void UnsuspendRedrawAll();
240 void ForceRedraw(ErrorResult
& rv
);
241 void PauseAnimations();
242 void UnpauseAnimations();
243 bool AnimationsPaused();
244 float GetCurrentTime();
245 void SetCurrentTime(float seconds
);
247 already_AddRefed
<DOMSVGNumber
> CreateSVGNumber();
248 already_AddRefed
<DOMSVGLength
> CreateSVGLength();
249 already_AddRefed
<SVGAngle
> CreateSVGAngle();
250 already_AddRefed
<nsISVGPoint
> CreateSVGPoint();
251 already_AddRefed
<SVGMatrix
> CreateSVGMatrix();
252 already_AddRefed
<SVGIRect
> CreateSVGRect();
253 already_AddRefed
<SVGTransform
> CreateSVGTransform();
254 already_AddRefed
<SVGTransform
> CreateSVGTransformFromMatrix(SVGMatrix
& matrix
);
255 using nsINode::GetElementById
; // This does what we want
256 already_AddRefed
<SVGAnimatedRect
> ViewBox();
257 already_AddRefed
<DOMSVGAnimatedPreserveAspectRatio
> PreserveAspectRatio();
258 uint16_t ZoomAndPan();
259 void SetZoomAndPan(uint16_t aZoomAndPan
, ErrorResult
& rv
);
262 // nsSVGElement overrides
264 virtual nsresult
BindToTree(nsIDocument
* aDocument
, nsIContent
* aParent
,
265 nsIContent
* aBindingParent
,
266 bool aCompileEventHandlers
) MOZ_OVERRIDE
;
267 virtual void UnbindFromTree(bool aDeep
, bool aNullParent
) MOZ_OVERRIDE
;
269 // implementation helpers:
271 SVGViewElement
* GetCurrentViewElement() const;
273 // Methods for <image> elements to override my "PreserveAspectRatio" value.
274 // These are private so that only our friends (AutoSVGRenderingState in
275 // particular) have access.
276 void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio
& aPAR
);
277 void ClearImageOverridePreserveAspectRatio();
279 // Set/Clear properties to hold old or override versions of attributes
280 bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio
& aPAR
);
281 const SVGPreserveAspectRatio
* GetPreserveAspectRatioProperty() const;
282 bool ClearPreserveAspectRatioProperty();
283 bool SetViewBoxProperty(const nsSVGViewBoxRect
& aViewBox
);
284 const nsSVGViewBoxRect
* GetViewBoxProperty() const;
285 bool ClearViewBoxProperty();
286 bool SetZoomAndPanProperty(uint16_t aValue
);
287 uint16_t GetZoomAndPanProperty() const;
288 bool ClearZoomAndPanProperty();
289 bool SetTransformProperty(const SVGTransformList
& aValue
);
290 const SVGTransformList
* GetTransformProperty() const;
291 bool ClearTransformProperty();
293 bool IsRoot() const {
294 NS_ASSERTION((IsInDoc() && !GetParent()) ==
295 (OwnerDoc() && (OwnerDoc()->GetRootElement() == this)),
296 "Can't determine if we're root");
297 return IsInDoc() && !GetParent();
301 * Returns true if this is an SVG <svg> element that is the child of
302 * another non-foreignObject SVG element.
304 bool IsInner() const {
305 const nsIContent
*parent
= GetFlattenedTreeParent();
306 return parent
&& parent
->IsSVG() &&
307 parent
->Tag() != nsGkAtoms::foreignObject
;
311 * While binding to the tree we need to determine if we will be the outermost
312 * <svg> element _before_ the children are bound (as they want to know what
313 * timed document root to register with) and therefore _before_ our parent is
314 * set (both actions are performed by Element::BindToTree) so we
315 * can't use GetOwnerSVGElement() as it relies on GetParent(). This code is
316 * basically a simplified version of GetOwnerSVGElement that uses the parent
317 * parameters passed in instead.
319 bool WillBeOutermostSVG(nsIContent
* aParent
,
320 nsIContent
* aBindingParent
) const;
322 // invalidate viewbox -> viewport xform & inform frames
323 void InvalidateTransformNotifyFrame();
325 // Returns true if we have at least one of the following:
326 // - a (valid or invalid) value for the preserveAspectRatio attribute
327 // - a SMIL-animated value for the preserveAspectRatio attribute
328 bool HasPreserveAspectRatio();
331 * Returns the explicit viewBox rect, if specified, or else a synthesized
332 * viewBox, if appropriate, or else a viewBox matching the dimensions of the
335 nsSVGViewBoxRect
GetViewBoxWithSynthesis(
336 float aViewportWidth
, float aViewportHeight
) const;
338 * Returns the explicit or default preserveAspectRatio, unless we're
339 * synthesizing a viewBox, in which case it returns the "none" value.
341 SVGPreserveAspectRatio
GetPreserveAspectRatioWithOverride() const;
343 virtual LengthAttributesInfo
GetLengthInfo() MOZ_OVERRIDE
;
345 enum { ATTR_X
, ATTR_Y
, ATTR_WIDTH
, ATTR_HEIGHT
};
346 nsSVGLength2 mLengthAttributes
[4];
347 static LengthInfo sLengthInfo
[4];
349 virtual EnumAttributesInfo
GetEnumInfo() MOZ_OVERRIDE
;
352 nsSVGEnum mEnumAttributes
[1];
353 static nsSVGEnumMapping sZoomAndPanMap
[];
354 static EnumInfo sEnumInfo
[1];
356 virtual nsSVGViewBox
*GetViewBox() MOZ_OVERRIDE
;
357 virtual SVGAnimatedPreserveAspectRatio
*GetPreserveAspectRatio() MOZ_OVERRIDE
;
359 nsSVGViewBox mViewBox
;
360 SVGAnimatedPreserveAspectRatio mPreserveAspectRatio
;
362 nsAutoPtr
<nsString
> mCurrentViewID
;
364 // The size of the rectangular SVG viewport into which we render. This is
365 // not (necessarily) the same as the content area. See:
367 // http://www.w3.org/TR/SVG11/coords.html#ViewportSpace
369 // XXXjwatt Currently only used for outer <svg>, but maybe we could use -1 to
370 // flag this as an inner <svg> to save the overhead of GetCtx calls?
371 // XXXjwatt our frame should probably reset these when it's destroyed.
372 float mViewportWidth
, mViewportHeight
;
374 // The time container for animations within this SVG document fragment. Set
375 // for all outermost <svg> elements (not nested <svg> elements).
376 nsAutoPtr
<nsSMILTimeContainer
> mTimedDocumentRoot
;
379 // IMPORTANT: see the comment in RecordCurrentScaleTranslate before writing
380 // code to change any of these!
381 SVGPoint mCurrentTranslate
;
383 SVGPoint mPreviousTranslate
;
384 float mPreviousScale
;
386 // For outermost <svg> elements created from parsing, animation is started by
387 // the onload event in accordance with the SVG spec, but for <svg> elements
388 // created by script or promoted from inner <svg> to outermost <svg> we need
389 // to manually kick off animation when they are bound to the tree.
390 bool mStartAnimationOnBindToTree
;
391 bool mImageNeedsTransformInvalidation
;
392 bool mIsPaintingSVGImageElement
;
393 bool mHasChildrenOnlyTransform
;
394 bool mUseCurrentView
;
399 // Helper class to automatically manage temporary changes to an SVG document's
400 // state for rendering purposes.
401 class MOZ_STACK_CLASS AutoSVGRenderingState
404 AutoSVGRenderingState(const Maybe
<SVGImageContext
>& aSVGContext
,
406 dom::SVGSVGElement
* aRootElem
407 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
408 : mHaveOverrides(aSVGContext
.isSome() &&
409 aSVGContext
->GetPreserveAspectRatio().isSome())
410 , mRootElem(aRootElem
)
412 MOZ_GUARD_OBJECT_NOTIFIER_INIT
;
413 MOZ_ASSERT(mRootElem
, "No SVG node to manage?");
414 if (mHaveOverrides
) {
415 // Override preserveAspectRatio in our helper document.
416 // XXXdholbert We should technically be overriding the helper doc's clip
417 // and overflow properties here, too. See bug 272288 comment 36.
418 mRootElem
->SetImageOverridePreserveAspectRatio(
419 *aSVGContext
->GetPreserveAspectRatio());
422 mOriginalTime
= mRootElem
->GetCurrentTime();
423 mRootElem
->SetCurrentTime(aFrameTime
); // Does nothing if there's no change.
426 ~AutoSVGRenderingState()
428 mRootElem
->SetCurrentTime(mOriginalTime
);
429 if (mHaveOverrides
) {
430 mRootElem
->ClearImageOverridePreserveAspectRatio();
435 const bool mHaveOverrides
;
437 const nsRefPtr
<dom::SVGSVGElement
> mRootElem
;
438 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
441 } // namespace mozilla
443 #endif // SVGSVGElement_h