SVGElementFactory.cpp (3848B)
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 #include "SVGElementFactory.h" 8 9 #include "mozilla/StaticPtr.h" 10 #include "mozilla/dom/Element.h" 11 #include "mozilla/dom/FromParser.h" 12 #include "mozilla/dom/NodeInfo.h" 13 #include "nsGkAtoms.h" 14 #include "nsHashKeys.h" 15 #include "nsIContent.h" 16 #include "nsTHashMap.h" 17 18 using namespace mozilla; 19 using namespace mozilla::dom; 20 21 // Hash table that maps nsAtom* SVG tags to a SVGContentCreatorFunction. 22 using TagAtomTable = 23 nsTHashMap<nsPtrHashKey<nsAtom>, SVGContentCreatorFunction>; 24 StaticAutoPtr<TagAtomTable> sTagAtomTable; 25 26 #define SVG_TAG(_tag, _classname) \ 27 nsresult NS_NewSVG##_classname##Element( \ 28 nsIContent** aResult, \ 29 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); \ 30 \ 31 nsresult NS_NewSVG##_classname##Element( \ 32 nsIContent** aResult, \ 33 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ 34 FromParser aFromParser) { \ 35 return NS_NewSVG##_classname##Element(aResult, std::move(aNodeInfo)); \ 36 } 37 38 #define SVG_FROM_PARSER_TAG(_tag, _classname) 39 40 #include "SVGTagList.h" 41 #undef SVG_TAG 42 #undef SVG_FROM_PARSER_TAG 43 44 nsresult NS_NewSVGElement(Element** aResult, 45 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); 46 47 enum SVGTag { 48 #define SVG_TAG(_tag, _classname) eSVGTag_##_tag, 49 #define SVG_FROM_PARSER_TAG(_tag, _classname) eSVGTag_##_tag, 50 #include "SVGTagList.h" 51 #undef SVG_TAG 52 #undef SVG_FROM_PARSER_TAG 53 eSVGTag_Count 54 }; 55 56 void SVGElementFactory::Init() { 57 sTagAtomTable = new TagAtomTable(64); 58 59 #define SVG_TAG(_tag, _classname) \ 60 sTagAtomTable->InsertOrUpdate( \ 61 nsGkAtoms::_tag, \ 62 SVGContentCreatorFunction(NS_NewSVG##_classname##Element)); 63 #define SVG_FROM_PARSER_TAG(_tag, _classname) \ 64 sTagAtomTable->InsertOrUpdate( \ 65 nsGkAtoms::_tag, \ 66 SVGContentCreatorFunction(NS_NewSVG##_classname##Element)); 67 #include "SVGTagList.h" 68 #undef SVG_TAG 69 #undef SVG_FROM_PARSER_TAG 70 } 71 72 void SVGElementFactory::Shutdown() { sTagAtomTable = nullptr; } 73 74 nsresult NS_NewSVGElement(Element** aResult, 75 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 76 FromParser aFromParser) { 77 NS_ASSERTION(sTagAtomTable, "no lookup table, needs SVGElementFactory::Init"); 78 79 RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo; 80 nsAtom* name = ni->NameAtom(); 81 82 NS_ASSERTION( 83 ni->NamespaceEquals(kNameSpaceID_SVG), 84 "Trying to create SVG elements that aren't in the SVG namespace"); 85 86 SVGContentCreatorFunction cb = sTagAtomTable->Get(name); 87 if (cb) { 88 nsCOMPtr<nsIContent> content; 89 nsresult rv = cb(getter_AddRefs(content), ni.forget(), aFromParser); 90 *aResult = content.forget().take()->AsElement(); 91 return rv; 92 } 93 94 // if we don't know what to create, just create a standard svg element: 95 return NS_NewSVGElement(aResult, ni.forget()); 96 } 97 98 nsresult NS_NewSVGUnknownElement( 99 nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 100 FromParser aFromParser) { 101 RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo; 102 nsCOMPtr<Element> element; 103 nsresult rv = NS_NewSVGElement(getter_AddRefs(element), ni.forget()); 104 element.forget(aResult); 105 return rv; 106 }