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/. */
7 #ifndef DOM_SVG_SVGUSEELEMENT_H_
8 #define DOM_SVG_SVGUSEELEMENT_H_
10 #include "mozilla/dom/FromParser.h"
11 #include "mozilla/dom/IDTracker.h"
12 #include "mozilla/dom/SVGGraphicsElement.h"
13 #include "mozilla/RefPtr.h"
15 #include "nsStubMutationObserver.h"
16 #include "SVGAnimatedLength.h"
17 #include "SVGAnimatedString.h"
22 nsresult
NS_NewSVGSVGElement(
23 nsIContent
** aResult
, already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
24 mozilla::dom::FromParser aFromParser
);
25 nsresult
NS_NewSVGUseElement(
26 nsIContent
** aResult
, already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
);
35 using SVGUseElementBase
= SVGGraphicsElement
;
37 class SVGUseElement final
: public SVGUseElementBase
,
38 public nsStubMutationObserver
{
39 friend class mozilla::SVGUseFrame
;
42 friend nsresult(::NS_NewSVGUseElement(
44 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
));
45 explicit SVGUseElement(already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
);
46 virtual ~SVGUseElement();
47 JSObject
* WrapNode(JSContext
* cx
, JS::Handle
<JSObject
*> aGivenProto
) override
;
50 NS_IMPL_FROMNODE_WITH_TAG(SVGUseElement
, kNameSpaceID_SVG
, use
)
52 nsresult
BindToTree(BindContext
&, nsINode
& aParent
) override
;
53 void UnbindFromTree(UnbindContext
&) override
;
56 NS_DECL_ISUPPORTS_INHERITED
57 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGUseElement
, SVGUseElementBase
)
59 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
60 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
61 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
62 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
63 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
64 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
66 // SVGElement specializations:
67 gfxMatrix
PrependLocalTransformsTo(
68 const gfxMatrix
& aMatrix
,
69 SVGTransformTypes aWhich
= eAllTransforms
) const override
;
70 bool HasValidDimensions() const override
;
72 // nsIContent interface
73 nsresult
Clone(dom::NodeInfo
*, nsINode
** aResult
) const override
;
74 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom
* aAttribute
) const override
;
76 static nsCSSPropertyID
GetCSSPropertyIdForAttrEnum(uint8_t aAttrEnum
);
79 already_AddRefed
<DOMSVGAnimatedString
> Href();
80 already_AddRefed
<DOMSVGAnimatedLength
> X();
81 already_AddRefed
<DOMSVGAnimatedLength
> Y();
82 already_AddRefed
<DOMSVGAnimatedLength
> Width();
83 already_AddRefed
<DOMSVGAnimatedLength
> Height();
85 nsIURI
* GetSourceDocURI();
86 const Encoding
* GetSourceDocCharacterSet();
87 URLExtraData
* GetContentURLData() const { return mContentURLData
; }
89 // Updates the internal shadow tree to be an up-to-date clone of the
90 // referenced element.
91 void UpdateShadowTree();
93 // Shared code between AfterSetAttr and SVGUseFrame::AttributeChanged.
95 // This is needed because SMIL doesn't go through AfterSetAttr unfortunately.
96 void ProcessAttributeChange(int32_t aNamespaceID
, nsAtom
* aAttribute
);
98 void AfterSetAttr(int32_t aNamespaceID
, nsAtom
* aAttribute
,
99 const nsAttrValue
* aValue
, const nsAttrValue
* aOldValue
,
100 nsIPrincipal
* aSubjectPrincipal
, bool aNotify
) final
;
103 // Information from walking our ancestors and a given target.
104 enum class ScanResult
{
105 // Nothing that should stop us from rendering the shadow tree.
107 // We're never going to be displayed, so no point in updating the shadow
110 // However if we're referenced from another tree that tree may need to be
113 // We're a cyclic reference to either an ancestor or another shadow tree. We
114 // shouldn't render this <use> element.
116 // We're too deep in our clone chain, we shouldn't be rendered.
119 ScanResult
ScanAncestors(const Element
& aTarget
) const;
120 ScanResult
ScanAncestorsInternal(const Element
& aTarget
,
121 uint32_t& aCount
) const;
124 * Helper that provides a reference to the element with the ID that is
125 * referenced by the 'use' element's 'href' attribute, and that will update
126 * the 'use' element if the element that that ID identifies changes to a
127 * different element (or none).
129 class ElementTracker final
: public IDTracker
{
131 explicit ElementTracker(SVGUseElement
* aOwningUseElement
)
132 : mOwningUseElement(aOwningUseElement
) {}
135 void ElementChanged(Element
* aFrom
, Element
* aTo
) override
{
136 IDTracker::ElementChanged(aFrom
, aTo
);
138 aFrom
->RemoveMutationObserver(mOwningUseElement
);
140 mOwningUseElement
->TriggerReclone();
143 SVGUseElement
* mOwningUseElement
;
146 SVGUseFrame
* GetFrame() const;
148 LengthAttributesInfo
GetLengthInfo() override
;
149 StringAttributesInfo
GetStringInfo() override
;
152 * Returns true if our width and height should be used, or false if they
153 * should be ignored. As per the spec, this depends on the type of the
154 * element that we're referencing.
156 bool OurWidthAndHeightAreUsed() const;
157 void SyncWidthOrHeight(nsAtom
* aName
);
159 void TriggerReclone();
162 enum { ATTR_X
, ATTR_Y
, ATTR_WIDTH
, ATTR_HEIGHT
};
163 SVGAnimatedLength mLengthAttributes
[4];
164 static LengthInfo sLengthInfo
[4];
166 enum { HREF
, XLINK_HREF
};
167 SVGAnimatedString mStringAttributes
[2];
168 static StringInfo sStringInfo
[2];
170 RefPtr
<SVGUseElement
> mOriginal
; // if we've been cloned, our "real" copy
171 ElementTracker mReferencedElementTracker
;
172 RefPtr
<URLExtraData
> mContentURLData
; // URL data for its anonymous content
176 } // namespace mozilla
178 #endif // DOM_SVG_SVGUSEELEMENT_H_