summaryrefslogtreecommitdiffstats
path: root/dom/svg/SVGSVGElement.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/svg/SVGSVGElement.h')
-rw-r--r--dom/svg/SVGSVGElement.h473
1 files changed, 473 insertions, 0 deletions
diff --git a/dom/svg/SVGSVGElement.h b/dom/svg/SVGSVGElement.h
new file mode 100644
index 000000000..da08ad770
--- /dev/null
+++ b/dom/svg/SVGSVGElement.h
@@ -0,0 +1,473 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SVGSVGElement_h
+#define mozilla_dom_SVGSVGElement_h
+
+#include "mozilla/dom/FromParser.h"
+#include "nsAutoPtr.h"
+#include "nsIContentInlines.h"
+#include "nsISVGPoint.h"
+#include "nsSVGEnum.h"
+#include "nsSVGLength2.h"
+#include "SVGGraphicsElement.h"
+#include "SVGImageContext.h"
+#include "nsSVGViewBox.h"
+#include "SVGPreserveAspectRatio.h"
+#include "SVGAnimatedPreserveAspectRatio.h"
+#include "mozilla/Attributes.h"
+
+nsresult NS_NewSVGSVGElement(nsIContent **aResult,
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser);
+
+class nsSMILTimeContainer;
+class nsSVGOuterSVGFrame;
+class nsSVGInnerSVGFrame;
+
+namespace mozilla {
+class AutoSVGRenderingState;
+class DOMSVGAnimatedPreserveAspectRatio;
+class DOMSVGLength;
+class DOMSVGNumber;
+class EventChainPreVisitor;
+class SVGFragmentIdentifier;
+class AutoSVGViewHandler;
+
+namespace dom {
+class SVGAngle;
+class SVGAnimatedRect;
+class SVGMatrix;
+class SVGTransform;
+class SVGViewElement;
+class SVGIRect;
+
+class SVGSVGElement;
+
+class DOMSVGTranslatePoint final : public nsISVGPoint {
+public:
+ DOMSVGTranslatePoint(SVGPoint* aPt, SVGSVGElement *aElement)
+ : nsISVGPoint(aPt, true), mElement(aElement) {}
+
+ explicit DOMSVGTranslatePoint(DOMSVGTranslatePoint* aPt)
+ : nsISVGPoint(&aPt->mPt, true), mElement(aPt->mElement) {}
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMSVGTranslatePoint, nsISVGPoint)
+
+ virtual DOMSVGPoint* Copy() override;
+
+ // WebIDL
+ virtual float X() override { return mPt.GetX(); }
+ virtual float Y() override { return mPt.GetY(); }
+ virtual void SetX(float aValue, ErrorResult& rv) override;
+ virtual void SetY(float aValue, ErrorResult& rv) override;
+ virtual already_AddRefed<nsISVGPoint> MatrixTransform(SVGMatrix& matrix) override;
+
+ virtual nsISupports* GetParentObject() override;
+
+ RefPtr<SVGSVGElement> mElement;
+
+private:
+ ~DOMSVGTranslatePoint() {}
+};
+
+class svgFloatSize {
+public:
+ svgFloatSize(float aWidth, float aHeight)
+ : width(aWidth)
+ , height(aHeight)
+ {}
+ bool operator!=(const svgFloatSize& rhs) {
+ return width != rhs.width || height != rhs.height;
+ }
+ float width;
+ float height;
+};
+
+// Stores svgView arguments of SVG fragment identifiers.
+class SVGView {
+ friend class mozilla::AutoSVGViewHandler;
+ friend class mozilla::dom::SVGSVGElement;
+public:
+ SVGView();
+
+private:
+ nsSVGEnum mZoomAndPan;
+ nsSVGViewBox mViewBox;
+ SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
+ nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
+};
+
+typedef SVGGraphicsElement SVGSVGElementBase;
+
+class SVGSVGElement final : public SVGSVGElementBase
+{
+ friend class ::nsSVGOuterSVGFrame;
+ friend class ::nsSVGInnerSVGFrame;
+ friend class mozilla::dom::SVGView;
+ friend class mozilla::SVGFragmentIdentifier;
+ friend class mozilla::AutoSVGViewHandler;
+ friend class mozilla::AutoSVGRenderingState;
+
+ SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
+ FromParser aFromParser);
+ virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ friend nsresult (::NS_NewSVGSVGElement(nsIContent **aResult,
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser));
+
+ ~SVGSVGElement();
+
+public:
+ // interfaces:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement, SVGSVGElementBase)
+
+ /**
+ * For use by zoom controls to allow currentScale, currentTranslate.x and
+ * currentTranslate.y to be set by a single operation that dispatches a
+ * single SVGZoom event (instead of one SVGZoom and two SVGScroll events).
+ */
+ void SetCurrentScaleTranslate(float s, float x, float y);
+
+ /**
+ * Retrieve the value of currentScale and currentTranslate.
+ */
+ const SVGPoint& GetCurrentTranslate() { return mCurrentTranslate; }
+ float GetCurrentScale() { return mCurrentScale; }
+
+ /**
+ * Retrieve the value of currentScale, currentTranslate.x or
+ * currentTranslate.y prior to the last change made to any one of them.
+ */
+ const SVGPoint& GetPreviousTranslate() { return mPreviousTranslate; }
+ float GetPreviousScale() { return mPreviousScale; }
+
+ nsSMILTimeContainer* GetTimedDocumentRoot();
+
+ // nsIContent interface
+ NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
+ virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
+
+ virtual bool IsEventAttributeName(nsIAtom* aName) override;
+
+ // nsSVGElement specializations:
+ virtual gfxMatrix PrependLocalTransformsTo(
+ const gfxMatrix &aMatrix,
+ SVGTransformTypes aWhich = eAllTransforms) const override;
+ virtual nsSVGAnimatedTransformList*
+ GetAnimatedTransformList(uint32_t aFlags = 0) override;
+ virtual bool HasValidDimensions() const override;
+
+ // SVGSVGElement methods:
+ float GetLength(uint8_t mCtxType);
+
+ // public helpers:
+
+ /**
+ * Returns -1 if the width/height is a percentage, else returns the user unit
+ * length clamped to fit in a int32_t.
+ * XXX see bug 1112533 comment 3 - we should fix drawImage so that we can
+ * change these methods to make zero the error flag for percentages.
+ */
+ int32_t GetIntrinsicWidth();
+ int32_t GetIntrinsicHeight();
+
+ /**
+ * Returns true if this element has a base/anim value for its "viewBox"
+ * attribute that defines a viewBox rectangle with finite values, or
+ * if there is a view element overriding this element's viewBox and it
+ * has a valid viewBox.
+ *
+ * Note that this does not check whether we need to synthesize a viewBox,
+ * so you must call ShouldSynthesizeViewBox() if you need to check that too.
+ *
+ * Note also that this method does not pay attention to whether the width or
+ * height values of the viewBox rect are positive!
+ */
+ bool HasViewBoxRect() const;
+
+ /**
+ * Returns true if we should synthesize a viewBox for ourselves (that is, if
+ * we're the root element in an image document, and we're not currently being
+ * painted for an <svg:image> element).
+ *
+ * Only call this method if HasViewBoxRect() returns false.
+ */
+ bool ShouldSynthesizeViewBox() const;
+
+ bool HasViewBoxOrSyntheticViewBox() const {
+ return HasViewBoxRect() || ShouldSynthesizeViewBox();
+ }
+
+ gfx::Matrix GetViewBoxTransform() const;
+
+ bool HasChildrenOnlyTransform() const {
+ return mHasChildrenOnlyTransform;
+ }
+
+ void UpdateHasChildrenOnlyTransform();
+
+ enum ChildrenOnlyTransformChangedFlags {
+ eDuringReflow = 1
+ };
+
+ /**
+ * This method notifies the style system that the overflow rects of our
+ * immediate childrens' frames need to be updated. It is called by our own
+ * frame when changes (e.g. to currentScale) cause our children-only
+ * transform to change.
+ *
+ * The reason we have this method instead of overriding
+ * GetAttributeChangeHint is because we need to act on non-attribute (e.g.
+ * currentScale) changes in addition to attribute (e.g. viewBox) changes.
+ */
+ void ChildrenOnlyTransformChanged(uint32_t aFlags = 0);
+
+ // This services any pending notifications for the transform on on this root
+ // <svg> node needing to be recalculated. (Only applicable in
+ // SVG-as-an-image documents.)
+ virtual void FlushImageTransformInvalidation();
+
+ virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+
+ // Returns true IFF our attributes are currently overridden by a <view>
+ // element and that element's ID matches the passed-in string.
+ bool IsOverriddenBy(const nsAString &aViewID) const {
+ return mCurrentViewID && mCurrentViewID->Equals(aViewID);
+ }
+
+ svgFloatSize GetViewportSize() const {
+ return svgFloatSize(mViewportWidth, mViewportHeight);
+ }
+
+ void SetViewportSize(const svgFloatSize& aSize) {
+ mViewportWidth = aSize.width;
+ mViewportHeight = aSize.height;
+ }
+
+ // WebIDL
+ already_AddRefed<SVGAnimatedLength> X();
+ already_AddRefed<SVGAnimatedLength> Y();
+ already_AddRefed<SVGAnimatedLength> Width();
+ already_AddRefed<SVGAnimatedLength> Height();
+ float PixelUnitToMillimeterX();
+ float PixelUnitToMillimeterY();
+ float ScreenPixelToMillimeterX();
+ float ScreenPixelToMillimeterY();
+ bool UseCurrentView();
+ float CurrentScale();
+ void SetCurrentScale(float aCurrentScale);
+ already_AddRefed<nsISVGPoint> CurrentTranslate();
+ void SetCurrentTranslate(float x, float y);
+ uint32_t SuspendRedraw(uint32_t max_wait_milliseconds);
+ void UnsuspendRedraw(uint32_t suspend_handle_id);
+ void UnsuspendRedrawAll();
+ void ForceRedraw();
+ void PauseAnimations();
+ void UnpauseAnimations();
+ bool AnimationsPaused();
+ float GetCurrentTime();
+ void SetCurrentTime(float seconds);
+ void DeselectAll();
+ already_AddRefed<DOMSVGNumber> CreateSVGNumber();
+ already_AddRefed<DOMSVGLength> CreateSVGLength();
+ already_AddRefed<SVGAngle> CreateSVGAngle();
+ already_AddRefed<nsISVGPoint> CreateSVGPoint();
+ already_AddRefed<SVGMatrix> CreateSVGMatrix();
+ already_AddRefed<SVGIRect> CreateSVGRect();
+ already_AddRefed<SVGTransform> CreateSVGTransform();
+ already_AddRefed<SVGTransform> CreateSVGTransformFromMatrix(SVGMatrix& matrix);
+ using nsINode::GetElementById; // This does what we want
+ already_AddRefed<SVGAnimatedRect> ViewBox();
+ already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
+ uint16_t ZoomAndPan();
+ void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
+ virtual nsSVGViewBox* GetViewBox() override;
+
+private:
+ // nsSVGElement overrides
+
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers) override;
+ virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
+
+ // implementation helpers:
+
+ SVGViewElement* GetCurrentViewElement() const;
+
+ // Methods for <image> elements to override my "PreserveAspectRatio" value.
+ // These are private so that only our friends (AutoSVGRenderingState in
+ // particular) have access.
+ void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
+ void ClearImageOverridePreserveAspectRatio();
+
+ // Set/Clear properties to hold old version of preserveAspectRatio
+ // when it's being overridden by an <image> element that we are inside of.
+ bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR);
+ const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
+ bool ClearPreserveAspectRatioProperty();
+
+ void SetIsPaintingForSVGImageElement(bool aIsPaintingSVGImageElement);
+
+ bool IsRoot() const {
+ NS_ASSERTION((IsInUncomposedDoc() && !GetParent()) ==
+ (OwnerDoc() && (OwnerDoc()->GetRootElement() == this)),
+ "Can't determine if we're root");
+ return IsInUncomposedDoc() && !GetParent();
+ }
+
+ /**
+ * Returns true if this is an SVG <svg> element that is the child of
+ * another non-foreignObject SVG element.
+ */
+ bool IsInner() const {
+ const nsIContent *parent = GetFlattenedTreeParent();
+ return parent && parent->IsSVGElement() &&
+ !parent->IsSVGElement(nsGkAtoms::foreignObject);
+ }
+
+ /*
+ * While binding to the tree we need to determine if we will be the outermost
+ * <svg> element _before_ the children are bound (as they want to know what
+ * timed document root to register with) and therefore _before_ our parent is
+ * set (both actions are performed by Element::BindToTree) so we
+ * can't use GetOwnerSVGElement() as it relies on GetParent(). This code is
+ * basically a simplified version of GetOwnerSVGElement that uses the parent
+ * parameters passed in instead.
+ */
+ bool WillBeOutermostSVG(nsIContent* aParent,
+ nsIContent* aBindingParent) const;
+
+ // invalidate viewbox -> viewport xform & inform frames
+ void InvalidateTransformNotifyFrame();
+
+ // Returns true if we have at least one of the following:
+ // - a (valid or invalid) value for the preserveAspectRatio attribute
+ // - a SMIL-animated value for the preserveAspectRatio attribute
+ bool HasPreserveAspectRatio();
+
+ /**
+ * Returns the explicit viewBox rect, if specified, or else a synthesized
+ * viewBox, if appropriate, or else a viewBox matching the dimensions of the
+ * SVG viewport.
+ */
+ nsSVGViewBoxRect GetViewBoxWithSynthesis(
+ float aViewportWidth, float aViewportHeight) const;
+ /**
+ * Returns the explicit or default preserveAspectRatio, unless we're
+ * synthesizing a viewBox, in which case it returns the "none" value.
+ */
+ SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const;
+
+ virtual LengthAttributesInfo GetLengthInfo() override;
+
+ enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
+ nsSVGLength2 mLengthAttributes[4];
+ static LengthInfo sLengthInfo[4];
+
+ virtual EnumAttributesInfo GetEnumInfo() override;
+
+ enum { ZOOMANDPAN };
+ nsSVGEnum mEnumAttributes[1];
+ static nsSVGEnumMapping sZoomAndPanMap[];
+ static EnumInfo sEnumInfo[1];
+
+ virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
+
+ nsSVGViewBox mViewBox;
+ SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
+
+ // mCurrentViewID and mSVGView are mutually exclusive; we can have
+ // at most one non-null.
+ nsAutoPtr<nsString> mCurrentViewID;
+ nsAutoPtr<SVGView> mSVGView;
+
+ // The size of the rectangular SVG viewport into which we render. This is
+ // not (necessarily) the same as the content area. See:
+ //
+ // http://www.w3.org/TR/SVG11/coords.html#ViewportSpace
+ //
+ // XXXjwatt Currently only used for outer <svg>, but maybe we could use -1 to
+ // flag this as an inner <svg> to save the overhead of GetCtx calls?
+ // XXXjwatt our frame should probably reset these when it's destroyed.
+ float mViewportWidth, mViewportHeight;
+
+ // The time container for animations within this SVG document fragment. Set
+ // for all outermost <svg> elements (not nested <svg> elements).
+ nsAutoPtr<nsSMILTimeContainer> mTimedDocumentRoot;
+
+ // zoom and pan
+ // IMPORTANT: see the comment in RecordCurrentScaleTranslate before writing
+ // code to change any of these!
+ SVGPoint mCurrentTranslate;
+ float mCurrentScale;
+ SVGPoint mPreviousTranslate;
+ float mPreviousScale;
+
+ // For outermost <svg> elements created from parsing, animation is started by
+ // the onload event in accordance with the SVG spec, but for <svg> elements
+ // created by script or promoted from inner <svg> to outermost <svg> we need
+ // to manually kick off animation when they are bound to the tree.
+ bool mStartAnimationOnBindToTree;
+ bool mImageNeedsTransformInvalidation;
+ bool mIsPaintingSVGImageElement;
+ bool mHasChildrenOnlyTransform;
+};
+
+} // namespace dom
+
+// Helper class to automatically manage temporary changes to an SVG document's
+// state for rendering purposes.
+class MOZ_RAII AutoSVGRenderingState
+{
+public:
+ AutoSVGRenderingState(const Maybe<SVGImageContext>& aSVGContext,
+ float aFrameTime,
+ dom::SVGSVGElement* aRootElem
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mHaveOverrides(aSVGContext.isSome() &&
+ aSVGContext->GetPreserveAspectRatio().isSome())
+ , mRootElem(aRootElem)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ MOZ_ASSERT(mRootElem, "No SVG node to manage?");
+ if (mHaveOverrides) {
+ // Override preserveAspectRatio in our helper document.
+ // XXXdholbert We should technically be overriding the helper doc's clip
+ // and overflow properties here, too. See bug 272288 comment 36.
+ mRootElem->SetImageOverridePreserveAspectRatio(
+ *aSVGContext->GetPreserveAspectRatio());
+ mRootElem->SetIsPaintingForSVGImageElement(
+ aSVGContext->IsPaintingForSVGImageElement());
+ }
+
+ mOriginalTime = mRootElem->GetCurrentTime();
+ mRootElem->SetCurrentTime(aFrameTime); // Does nothing if there's no change.
+ }
+
+ ~AutoSVGRenderingState()
+ {
+ mRootElem->SetCurrentTime(mOriginalTime);
+ if (mHaveOverrides) {
+ mRootElem->ClearImageOverridePreserveAspectRatio();
+ mRootElem->SetIsPaintingForSVGImageElement(false);
+ }
+ }
+
+private:
+ const bool mHaveOverrides;
+ float mOriginalTime;
+ const RefPtr<dom::SVGSVGElement> mRootElem;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+} // namespace mozilla
+
+#endif // SVGSVGElement_h