Bug 265894 - Part 5. Move svg-view back to SVGSVGElement. draft
authorcku <cku@mozilla.com>
Mon, 19 Jun 2017 16:00:00 +0800
changeset 597085 df17db5fd05fae2ca8641b3c9fb8ef9aa940c127
parent 597084 cea9fd53a8b1d93aab987c89f7d7745e4e74c44e
child 597086 5fddcc9c9f77b8a9ff59328d1125e480596c0fed
push id64828
push userbmo:cku@mozilla.com
push dateTue, 20 Jun 2017 04:17:06 +0000
bugs265894
milestone56.0a1
Bug 265894 - Part 5. Move svg-view back to SVGSVGElement. MozReview-Commit-ID: ESHLDHxsqps
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
dom/svg/SVGViewportElement.cpp
dom/svg/SVGViewportElement.h
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -123,16 +123,24 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_ADDREF_INHERITED(SVGSVGElement,SVGSVGElementBase)
 NS_IMPL_RELEASE_INHERITED(SVGSVGElement,SVGSVGElementBase)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGSVGElement)
   NS_INTERFACE_TABLE_INHERITED(SVGSVGElement, nsIDOMNode, nsIDOMElement,
                                nsIDOMSVGElement)
 NS_INTERFACE_TABLE_TAIL_INHERITING(SVGSVGElementBase)
 
+SVGView::SVGView()
+{
+  mZoomAndPan.Init(SVGSVGElement::ZOOMANDPAN,
+                   SVG_ZOOMANDPAN_MAGNIFY);
+  mViewBox.Init();
+  mPreserveAspectRatio.Init();
+}
+
 //----------------------------------------------------------------------
 // Implementation
 
 SVGSVGElement::SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
                              FromParser aFromParser)
   : SVGSVGElementBase(aNodeInfo),
     mCurrentTranslate(0.0f, 0.0f),
     mCurrentScale(1.0f),
@@ -536,16 +544,25 @@ SVGSVGElement::UnbindFromTree(bool aDeep
 {
   if (mTimedDocumentRoot) {
     mTimedDocumentRoot->SetParent(nullptr);
   }
 
   SVGGraphicsElement::UnbindFromTree(aDeep, aNullParent);
 }
 
+nsSVGAnimatedTransformList*
+SVGSVGElement::GetAnimatedTransformList(uint32_t aFlags)
+{
+  if (!(aFlags & DO_ALLOCATE) && mSVGView && mSVGView->mTransforms) {
+    return mSVGView->mTransforms;
+  }
+  return SVGGraphicsElement::GetAnimatedTransformList(aFlags);
+}
+
 nsresult
 SVGSVGElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
 {
   if (aVisitor.mEvent->mMessage == eSVGLoad) {
     if (mTimedDocumentRoot) {
       mTimedDocumentRoot->Begin();
       // Set 'resample needed' flag, so that if any script calls a DOM method
       // that requires up-to-date animations before our first sample callback,
@@ -760,10 +777,47 @@ SVGSVGElement::GetPreserveAspectRatioWit
     return viewElement->mPreserveAspectRatio.GetAnimValue();
   }
   if (mSVGView && mSVGView->mPreserveAspectRatio.IsExplicitlySet()) {
     return mSVGView->mPreserveAspectRatio.GetAnimValue();
   }
   return mPreserveAspectRatio.GetAnimValue();
 }
 
+SVGViewElement*
+SVGSVGElement::GetCurrentViewElement() const
+{
+  if (mCurrentViewID) {
+    //XXXsmaug It is unclear how this should work in case we're in Shadow DOM.
+    nsIDocument* doc = GetUncomposedDoc();
+    if (doc) {
+      Element *element = doc->GetElementById(*mCurrentViewID);
+      if (element && element->IsSVGElement(nsGkAtoms::view)) {
+        return static_cast<SVGViewElement*>(element);
+      }
+    }
+  }
+  return nullptr;
+}
+
+const nsSVGViewBox&
+SVGSVGElement::GetViewBoxInternal() const
+{
+  SVGViewElement* viewElement = GetCurrentViewElement();
+
+  if (viewElement && viewElement->mViewBox.HasRect()) {
+    return viewElement->mViewBox;
+  } else if (mSVGView && mSVGView->mViewBox.HasRect()) {
+    return mSVGView->mViewBox;
+  }
+
+  return mViewBox;
+}
+
+nsSVGAnimatedTransformList*
+SVGSVGElement::GetTransformInternal() const
+{
+  return (mSVGView && mSVGView->mTransforms)
+         ? mSVGView->mTransforms: mTransforms;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -23,16 +23,27 @@ class DOMSVGLength;
 class DOMSVGNumber;
 
 namespace dom {
 class SVGAngle;
 class SVGMatrix;
 class SVGIRect;
 class SVGSVGElement;
 
+// Stores svgView arguments of SVG fragment identifiers.
+class SVGView {
+public:
+  SVGView();
+
+  nsSVGEnum                             mZoomAndPan;
+  nsSVGViewBox                          mViewBox;
+  SVGAnimatedPreserveAspectRatio        mPreserveAspectRatio;
+  nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
+};
+
 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) {}
 
@@ -59,16 +70,17 @@ private:
 typedef SVGViewportElement SVGSVGElementBase;
 
 class SVGSVGElement final : public SVGSVGElementBase
 {
   friend class ::nsSVGOuterSVGFrame;
   friend class mozilla::SVGFragmentIdentifier;
   friend class mozilla::AutoSVGViewHandler;
   friend class mozilla::AutoPreserveAspectRatioOverride;
+  friend class mozilla::dom::SVGView;
 
 protected:
   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,
@@ -135,16 +147,18 @@ public:
   void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
 
   // nsSVGElement overrides
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
+  virtual nsSVGAnimatedTransformList*
+    GetAnimatedTransformList(uint32_t aFlags = 0) override;
 
   // SVGSVGElement methods:
 
   // 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);
   }
@@ -174,16 +188,17 @@ public:
   void SetViewportSize(const svgFloatSize& aSize) {
     mViewportWidth  = aSize.width;
     mViewportHeight = aSize.height;
   }
 
 private:
   // SVGViewportElement methods:
 
+  virtual SVGViewElement* GetCurrentViewElement() const;
   virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const override;
 
   // implementation helpers:
 
   /*
    * 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
@@ -215,18 +230,23 @@ private:
   const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
   bool ClearPreserveAspectRatioProperty();
 
   virtual SVGPoint GetCurrentTranslate() const override
   { return mCurrentTranslate; }
   virtual float GetCurrentScale() const override
   { return mCurrentScale; }
 
+  virtual const nsSVGViewBox& GetViewBoxInternal() const override;
+  virtual nsSVGAnimatedTransformList* GetTransformInternal() const override;
+
+
   virtual EnumAttributesInfo GetEnumInfo() override;
 
+  enum { ZOOMANDPAN };
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sZoomAndPanMap[];
   static EnumInfo sEnumInfo[1];
 
   // The time container for animations within this SVG document fragment. Set
   // for all outermost <svg> elements (not nested <svg> elements).
   nsAutoPtr<nsSMILTimeContainer> mTimedDocumentRoot;
 
@@ -240,16 +260,21 @@ private:
 
   // 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;
+
+  // mCurrentViewID and mSVGView are mutually exclusive; we can have
+  // at most one non-null.
+  nsAutoPtr<nsString>            mCurrentViewID;
+  nsAutoPtr<SVGView>             mSVGView;
 };
 
 } // namespace dom
 
 class MOZ_RAII AutoSVGTimeSetRestore
 {
 public:
   AutoSVGTimeSetRestore(dom::SVGSVGElement* aRootElem,
--- a/dom/svg/SVGViewportElement.cpp
+++ b/dom/svg/SVGViewportElement.cpp
@@ -40,24 +40,16 @@ namespace dom {
 nsSVGElement::LengthInfo SVGViewportElement::sLengthInfo[4] =
 {
   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
   { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
   { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
 };
 
-SVGView::SVGView()
-{
-  mZoomAndPan.Init(SVGViewportElement::ZOOMANDPAN,
-                   SVG_ZOOMANDPAN_MAGNIFY);
-  mViewBox.Init();
-  mPreserveAspectRatio.Init();
-}
-
 //----------------------------------------------------------------------
 // Implementation
 
 SVGViewportElement::SVGViewportElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : SVGGraphicsElement(aNodeInfo),
     mViewportWidth(0),
     mViewportHeight(0),
     mHasChildrenOnlyTransform(false)
@@ -232,30 +224,21 @@ SVGViewportElement::GetViewBoxTransform(
                                               GetPreserveAspectRatioWithOverride());
 }
 //----------------------------------------------------------------------
 // SVGViewportElement
 
 float
 SVGViewportElement::GetLength(uint8_t aCtxType)
 {
-  float h, w;
-
-  SVGViewElement* viewElement = GetCurrentViewElement();
-  const nsSVGViewBoxRect* viewbox = nullptr;
+  const nsSVGViewBoxRect* viewbox =
+    GetViewBoxInternal().HasRect() ? &GetViewBoxInternal().GetAnimValue()
+                                   : nullptr;
 
-  // The logic here should match HasViewBoxRect().
-  if (viewElement && viewElement->mViewBox.HasRect()) {
-    viewbox = &viewElement->mViewBox.GetAnimValue();
-  } else if (mSVGView && mSVGView->mViewBox.HasRect()) {
-    viewbox = &mSVGView->mViewBox.GetAnimValue();
-  } else if (mViewBox.HasRect()) {
-    viewbox = &mViewBox.GetAnimValue();
-  }
-
+  float h, w;
   if (viewbox) {
     w = viewbox->width;
     h = viewbox->height;
   } else if (IsInner()) {
     SVGViewportElement *ctx = GetCtx();
     w = mLengthAttributes[ATTR_WIDTH].GetAnimValue(ctx);
     h = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(ctx);
   } else if (ShouldSynthesizeViewBox()) {
@@ -289,19 +272,17 @@ SVGViewportElement::GetLength(uint8_t aC
 SVGViewportElement::PrependLocalTransformsTo(const gfxMatrix& aMatrix,
                                         SVGTransformTypes aWhich) const
 {
   // 'transform' attribute (or an override from a fragment identifier):
   gfxMatrix userToParent;
 
   if (aWhich == eUserSpaceToParent || aWhich == eAllTransforms) {
     userToParent = GetUserToParentTransform(mAnimateMotionTransform,
-                                            mSVGView && mSVGView->mTransforms
-                                              ? mSVGView->mTransforms
-                                              : mTransforms);
+                                            GetTransformInternal());
     if (aWhich == eUserSpaceToParent) {
       return userToParent * aMatrix;
     }
   }
 
   gfxMatrix childToUser;
 
   if (IsInner()) {
@@ -331,25 +312,16 @@ SVGViewportElement::PrependLocalTransfor
   // transform between the two wouldn't make sense.  We don't expect that to
   // ever happen though.  We get here either when the identity matrix has been
   // passed because our caller just wants our eChildToUserSpace transform, or
   // when our eUserSpaceToParent transform has already been multiplied into the
   // matrix that our caller passes (such as when we're called from PaintSVG).
   return childToUser * aMatrix;
 }
 
-nsSVGAnimatedTransformList*
-SVGViewportElement::GetAnimatedTransformList(uint32_t aFlags)
-{
-  if (!(aFlags & DO_ALLOCATE) && mSVGView && mSVGView->mTransforms) {
-    return mSVGView->mTransforms;
-  }
-  return SVGGraphicsElement::GetAnimatedTransformList(aFlags);
-}
-
 /* virtual */ bool
 SVGViewportElement::HasValidDimensions() const
 {
   return !IsInner() ||
     ((!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() ||
        mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
      (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() ||
        mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0));
@@ -365,67 +337,32 @@ SVGViewportElement::GetViewBox()
 
 SVGAnimatedPreserveAspectRatio *
 SVGViewportElement::GetPreserveAspectRatio()
 {
   return &mPreserveAspectRatio;
 }
 
 bool
-SVGViewportElement::HasViewBoxRect() const
-{
-  SVGViewElement* viewElement = GetCurrentViewElement();
-  if ((viewElement && viewElement->mViewBox.HasRect()) ||
-      (mSVGView && mSVGView->mViewBox.HasRect())) {
-    return true;
-  }
-  return mViewBox.HasRect();
-}
-
-bool
 SVGViewportElement::ShouldSynthesizeViewBox() const
 {
   MOZ_ASSERT(!HasViewBoxRect(), "Should only be called if we lack a viewBox");
 
   return IsRoot() && OwnerDoc()->IsBeingUsedAsImage();
 }
 
 //----------------------------------------------------------------------
 // implementation helpers
 
-SVGViewElement*
-SVGViewportElement::GetCurrentViewElement() const
-{
-  if (mCurrentViewID) {
-    //XXXsmaug It is unclear how this should work in case we're in Shadow DOM.
-    nsIDocument* doc = GetUncomposedDoc();
-    if (doc) {
-      Element *element = doc->GetElementById(*mCurrentViewID);
-      if (element && element->IsSVGElement(nsGkAtoms::view)) {
-        return static_cast<SVGViewElement*>(element);
-      }
-    }
-  }
-  return nullptr;
-}
-
 nsSVGViewBoxRect
 SVGViewportElement::GetViewBoxWithSynthesis(
   float aViewportWidth, float aViewportHeight) const
 {
-  // The logic here should match HasViewBoxRect().
-  SVGViewElement* viewElement = GetCurrentViewElement();
-  if (viewElement && viewElement->mViewBox.HasRect()) {
-    return viewElement->mViewBox.GetAnimValue();
-  }
-  if (mSVGView && mSVGView->mViewBox.HasRect()) {
-    return mSVGView->mViewBox.GetAnimValue();
-  }
-  if (mViewBox.HasRect()) {
-    return mViewBox.GetAnimValue();
+  if (GetViewBoxInternal().HasRect()) {
+    return GetViewBoxInternal().GetAnimValue();
   }
 
   if (ShouldSynthesizeViewBox()) {
     // Special case -- fake a viewBox, using height & width attrs.
     // (Use |this| as context, since if we get here, we're outermost <svg>.)
     return nsSVGViewBoxRect(0, 0,
               ComputeSynthesizedViewBoxDimension(mLengthAttributes[ATTR_WIDTH],
                                                  mViewportWidth, this),
--- a/dom/svg/SVGViewportElement.h
+++ b/dom/svg/SVGViewportElement.h
@@ -41,50 +41,37 @@ public:
   {}
   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 {
-public:
-  SVGView();
-
-  nsSVGEnum                             mZoomAndPan;
-  nsSVGViewBox                          mViewBox;
-  SVGAnimatedPreserveAspectRatio        mPreserveAspectRatio;
-  nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
-};
-
 class SVGViewportElement : public SVGGraphicsElement
 {
   friend class ::nsSVGOuterSVGFrame;
   friend class ::nsSVGInnerSVGFrame;
-  friend class mozilla::dom::SVGView;
 
 protected:
 
   SVGViewportElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   ~SVGViewportElement();
 
 public:
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const 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;
 
   // SVGViewportElement methods:
   float GetLength(uint8_t mCtxType);
 
   // public helpers:
 
   /**
@@ -94,17 +81,19 @@ public:
    * 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 chck 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;
+  bool HasViewBoxRect() const {
+    return GetViewBoxInternal().HasRect();
+  }
 
   /**
    * 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.
    */
@@ -160,18 +149,16 @@ protected:
    * this is the root of a use-element shadow tree.
    */
   bool IsInner() const {
     const nsIContent *parent = GetFlattenedTreeParent();
     return parent && parent->IsSVGElement() &&
            !parent->IsSVGElement(nsGkAtoms::foreignObject);
   }
 
-  SVGViewElement* GetCurrentViewElement() const;
-
   /**
    * Returns the explicit or default preserveAspectRatio, unless we're
    * synthesizing a viewBox, in which case it returns the "none" value.
    */
   virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const {
     return mPreserveAspectRatio.GetAnimValue();
   }
 
@@ -191,28 +178,25 @@ protected:
   virtual float GetCurrentScale() const
   { return 1.0f; }
 
   enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
   virtual LengthAttributesInfo GetLengthInfo() override;
 
-  enum { ZOOMANDPAN };
-
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
 
+  virtual const nsSVGViewBox& GetViewBoxInternal() const { return mViewBox; }
+  virtual nsSVGAnimatedTransformList* GetTransformInternal() const {
+    return mTransforms;
+  }
   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.