Bug 265894 - Part 1. Implement SVGSVGElement::CloneFromSymbol. draft
authorcku <cku@mozilla.com>
Fri, 09 Jun 2017 23:21:14 +0800
changeset 593185 be0da3b45640edcb27bf73c962e177e25d5b88dd
parent 586973 7b8937970f9ca85db88cb2496f2112175fd847c8
child 593186 9bcbb570344b04ac4ee434d8b8161a89d99bdd2b
child 593192 edd913d0ca7b8f71094f77079d1a46c0e8b214bd
push id63624
push userbmo:cku@mozilla.com
push dateTue, 13 Jun 2017 09:20:36 +0000
bugs265894
milestone55.0a1
Bug 265894 - Part 1. Implement SVGSVGElement::CloneFromSymbol. 1. Move clone-svg-from-symbol logic out of SVGUseElement::CreateAnonymousContent. 2. Since we move the clone logic into SVGSVGElement::CloneFromSymbol, it's easier to setup SVGSVGElement::mCloneFromSymbol just inside this new function in next patch. MozReview-Commit-ID: 6nxhz3AGV5t
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
dom/svg/SVGUseElement.cpp
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -1185,10 +1185,62 @@ SVGSVGElement::GetIntrinsicHeight()
   // Passing |this| as a SVGSVGElement* invokes the variant of GetAnimValue
   // that uses the passed argument as the context, but that's fine since we
   // know the length isn't a percentage so the context won't be used (and we
   // need to pass the element to be able to resolve em/ex units).
   float height = mLengthAttributes[ATTR_HEIGHT].GetAnimValue(this);
   return nsSVGUtils::ClampToInt(height);
 }
 
+/* static */
+already_AddRefed<nsIContent>
+SVGSVGElement::CloneFromSymbol(Element* aShadowHost, nsIContent* aSymbol)
+{
+  MOZ_ASSERT(aSymbol->IsSVGElement(nsGkAtoms::symbol));
+  nsIDocument *document = aShadowHost->GetComposedDoc();
+  if (!document) {
+    return nullptr;
+  }
+
+  nsNodeInfoManager *nodeInfoManager = document->NodeInfoManager();
+  if (!nodeInfoManager) {
+    return nullptr;
+  }
+
+  RefPtr<mozilla::dom::NodeInfo> nodeInfo;
+  nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::svg, nullptr,
+                                          kNameSpaceID_SVG,
+                                          nsIDOMNode::ELEMENT_NODE);
+
+  nsCOMPtr<nsIContent> svgNode;
+  NS_NewSVGSVGElement(getter_AddRefs(svgNode), nodeInfo.forget(),
+                      NOT_FROM_PARSER);
+
+  if (!svgNode) {
+    return nullptr;
+  }
+
+  // copy attributes
+  BorrowedAttrInfo info;
+  uint32_t i;
+  for (i = 0; (info = aSymbol->GetAttrInfoAt(i)); i++) {
+    nsAutoString value;
+    int32_t nsID = info.mName->NamespaceID();
+    nsIAtom* lname = info.mName->LocalName();
+
+    info.mValue->ToString(value);
+
+    svgNode->SetAttr(nsID, lname, info.mName->GetPrefix(), value, false);
+  }
+
+  // move the children over
+  uint32_t num = aSymbol->GetChildCount();
+  for (i = 0; i < num; i++) {
+    nsCOMPtr<nsIContent> child = aSymbol->GetFirstChild();
+    aSymbol->RemoveChildAt(0, false);
+    svgNode->InsertChildAt(child, i, true);
+  }
+
+  return svgNode.forget();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -252,16 +252,18 @@ public:
     return svgFloatSize(mViewportWidth, mViewportHeight);
   }
 
   void SetViewportSize(const svgFloatSize& aSize) {
     mViewportWidth  = aSize.width;
     mViewportHeight = aSize.height;
   }
 
+  static already_AddRefed<nsIContent> CloneFromSymbol(Element* aShadowHost,
+                                                      nsIContent* aSymbol);
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
   float PixelUnitToMillimeterX();
   float PixelUnitToMillimeterY();
   float ScreenPixelToMillimeterX();
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -271,58 +271,20 @@ SVGUseElement::CreateAnonymousContent()
                      getter_AddRefs(newnode));
 
   nsCOMPtr<nsIContent> newcontent = do_QueryInterface(newnode);
 
   if (!newcontent)
     return nullptr;
 
   if (newcontent->IsSVGElement(nsGkAtoms::symbol)) {
-    nsIDocument *document = GetComposedDoc();
-    if (!document)
-      return nullptr;
-
-    nsNodeInfoManager *nodeInfoManager = document->NodeInfoManager();
-    if (!nodeInfoManager)
-      return nullptr;
-
-    RefPtr<mozilla::dom::NodeInfo> nodeInfo;
-    nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::svg, nullptr,
-                                            kNameSpaceID_SVG,
-                                            nsIDOMNode::ELEMENT_NODE);
-
-    nsCOMPtr<nsIContent> svgNode;
-    NS_NewSVGSVGElement(getter_AddRefs(svgNode), nodeInfo.forget(),
-                        NOT_FROM_PARSER);
-
-    if (!svgNode)
+    newcontent = SVGSVGElement::CloneFromSymbol(this, newcontent);
+    if (!newcontent) {
       return nullptr;
-
-    // copy attributes
-    BorrowedAttrInfo info;
-    uint32_t i;
-    for (i = 0; (info = newcontent->GetAttrInfoAt(i)); i++) {
-      nsAutoString value;
-      int32_t nsID = info.mName->NamespaceID();
-      nsIAtom* lname = info.mName->LocalName();
-
-      info.mValue->ToString(value);
-
-      svgNode->SetAttr(nsID, lname, info.mName->GetPrefix(), value, false);
     }
-
-    // move the children over
-    uint32_t num = newcontent->GetChildCount();
-    for (i = 0; i < num; i++) {
-      nsCOMPtr<nsIContent> child = newcontent->GetFirstChild();
-      newcontent->RemoveChildAt(0, false);
-      svgNode->InsertChildAt(child, i, true);
-    }
-
-    newcontent = svgNode;
   }
 
   if (newcontent->IsAnyOfSVGElements(nsGkAtoms::svg, nsGkAtoms::symbol)) {
     nsSVGElement *newElement = static_cast<nsSVGElement*>(newcontent.get());
 
     if (mLengthAttributes[ATTR_WIDTH].IsExplicitlySet())
       newElement->SetLength(nsGkAtoms::width, mLengthAttributes[ATTR_WIDTH]);
     if (mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet())