2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
#ifndef mozilla_dom_SVGUseElement_h
|
|
|
|
#define mozilla_dom_SVGUseElement_h
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2012-01-26 13:57:21 +04:00
|
|
|
#include "mozilla/dom/FromParser.h"
|
2017-09-08 12:02:05 +03:00
|
|
|
#include "mozilla/dom/IDTracker.h"
|
2013-01-17 00:50:58 +04:00
|
|
|
#include "mozilla/dom/SVGGraphicsElement.h"
|
2019-01-25 02:40:25 +03:00
|
|
|
#include "mozilla/RefPtr.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsStubMutationObserver.h"
|
2019-04-09 23:04:33 +03:00
|
|
|
#include "SVGAnimatedLength.h"
|
2019-04-04 20:40:56 +03:00
|
|
|
#include "SVGAnimatedString.h"
|
2007-02-18 20:34:09 +03:00
|
|
|
#include "nsTArray.h"
|
|
|
|
|
|
|
|
class nsIContent;
|
2013-01-17 00:50:59 +04:00
|
|
|
class nsSVGUseFrame;
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2010-07-23 13:49:57 +04:00
|
|
|
nsresult NS_NewSVGSVGElement(
|
2014-06-20 06:01:40 +04:00
|
|
|
nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
2010-10-25 16:17:38 +04:00
|
|
|
mozilla::dom::FromParser aFromParser);
|
2013-01-17 00:50:58 +04:00
|
|
|
nsresult NS_NewSVGUseElement(
|
2014-06-20 06:01:40 +04:00
|
|
|
nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
namespace mozilla {
|
2017-04-06 09:51:29 +03:00
|
|
|
struct URLExtraData;
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
namespace dom {
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
typedef SVGGraphicsElement SVGUseElementBase;
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class SVGUseElement final : public SVGUseElementBase,
|
2015-03-27 21:52:19 +03:00
|
|
|
public nsStubMutationObserver {
|
2013-01-17 00:50:59 +04:00
|
|
|
friend class ::nsSVGUseFrame;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2007-02-18 20:34:09 +03:00
|
|
|
protected:
|
2013-01-17 00:50:58 +04:00
|
|
|
friend nsresult(::NS_NewSVGUseElement(
|
|
|
|
nsIContent** aResult,
|
2014-06-20 06:01:40 +04:00
|
|
|
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
|
2018-09-21 23:45:49 +03:00
|
|
|
explicit SVGUseElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
2013-01-17 00:50:58 +04:00
|
|
|
virtual ~SVGUseElement();
|
2015-03-21 19:28:04 +03:00
|
|
|
virtual JSObject* WrapNode(JSContext* cx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) override;
|
2013-01-17 00:50:58 +04:00
|
|
|
|
2007-02-18 20:34:09 +03:00
|
|
|
public:
|
2018-07-16 17:07:58 +03:00
|
|
|
NS_IMPL_FROMNODE_WITH_TAG(SVGUseElement, kNameSpaceID_SVG, use)
|
|
|
|
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
2019-05-29 01:47:08 +03:00
|
|
|
void UnbindFromTree(bool aNullParent = true) override;
|
2013-01-17 00:50:58 +04:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
// interfaces:
|
2007-02-18 20:34:09 +03:00
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
2013-01-17 00:50:58 +04:00
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGUseElement, SVGUseElementBase)
|
2007-03-10 16:49:43 +03:00
|
|
|
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2018-12-21 11:58:14 +03:00
|
|
|
// SVGElement specializations:
|
2015-12-03 01:36:23 +03:00
|
|
|
virtual gfxMatrix PrependLocalTransformsTo(
|
|
|
|
const gfxMatrix& aMatrix,
|
|
|
|
SVGTransformTypes aWhich = eAllTransforms) const override;
|
2015-03-21 19:28:04 +03:00
|
|
|
virtual bool HasValidDimensions() const override;
|
2007-02-18 20:34:09 +03:00
|
|
|
|
|
|
|
// nsIContent interface
|
2018-08-09 02:58:44 +03:00
|
|
|
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
|
2017-10-03 01:05:19 +03:00
|
|
|
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2013-01-17 00:50:59 +04:00
|
|
|
// WebIDL
|
2019-03-19 03:01:03 +03:00
|
|
|
already_AddRefed<DOMSVGAnimatedString> Href();
|
|
|
|
already_AddRefed<DOMSVGAnimatedLength> X();
|
|
|
|
already_AddRefed<DOMSVGAnimatedLength> Y();
|
|
|
|
already_AddRefed<DOMSVGAnimatedLength> Width();
|
|
|
|
already_AddRefed<DOMSVGAnimatedLength> Height();
|
2013-01-17 00:50:59 +04:00
|
|
|
|
2016-09-20 09:13:13 +03:00
|
|
|
nsIURI* GetSourceDocURI();
|
2017-04-06 09:51:29 +03:00
|
|
|
URLExtraData* GetContentURLData() const { return mContentURLData; }
|
2016-09-20 09:13:13 +03:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
// Updates the internal shadow tree to be an up-to-date clone of the
|
|
|
|
// referenced element.
|
|
|
|
void UpdateShadowTree();
|
|
|
|
|
2018-10-29 02:20:43 +03:00
|
|
|
// Shared code between AfterSetAttr and nsSVGUseFrame::AttributeChanged.
|
|
|
|
//
|
|
|
|
// This is needed because SMIL doesn't go through AfterSetAttr unfortunately.
|
|
|
|
void ProcessAttributeChange(int32_t aNamespaceID, nsAtom* aAttribute);
|
|
|
|
|
|
|
|
nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aAttribute,
|
|
|
|
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
|
|
|
|
nsIPrincipal* aSubjectPrincipal, bool aNotify) final;
|
|
|
|
|
2007-02-18 20:34:09 +03:00
|
|
|
protected:
|
Bug 1579181 - Don't keep <use> shadow trees which we know we'll never render. r=longsonr
This partially addresses the regression, but not fully. With this patch we don't
maintain shadow trees for nodes that we know won't get rendered.
This works fast in WebKit / Blink because of a bug in their implementation which
doesn't synchronize style attributes, introduced in [1].
You can see this clearly if you click on the bug's test-case and inspect the
<use> shadow trees (there's no style="stroke:orange" whatsoever).
They can kinda get away with it because they don't properly implement SVG 2. In
particular, in Blink / WebKit, the style of the element in the <use> shadow tree
is the style of the referenced element, which means that even if the style
attribute isn't properly synced it's ~ok since it doesn't end up mattering for
styling.
Easiest test-case for the behavior difference is:
```
<!doctype html>
<style>
rect:hover {
fill: green;
}
</style>
<svg width=300 height=300>
<g id="canvas">
<rect fill=red width=100 height=100></rect>
</g>
<g>
<use x=200 href="#canvas"></use>
</g>
</svg>
```
Where Firefox will properly update each square independently when hovered, but
Blink / WebKit won't.
This used to work faster because in this particular test-case we have 3 hidden
<use> elements whose href is the #canvas, which is basically everything.
Before moving to shadow trees we'd do it using anonymous content, and since we
never got a frame we'd never clone the subtree in the first case.
This case was faster before bug 1450250, but this approach makes other cases
slow that were fixed by that bug, like bug 1485402.
So I'll try to optimize shadow tree syncing instead, I guess, but there's no
good reason not to land this in the meantime IMHO.
[1]: https://chromium.googlesource.com/chromium/src/+/f4b022e64bbe0c74f07ee9209aa4033bddece145%5E%21/third_party/WebKit/WebCore/svg/SVGElement.cpp
Differential Revision: https://phabricator.services.mozilla.com/D45953
--HG--
extra : moz-landing-system : lando
2019-09-15 19:09:28 +03:00
|
|
|
// Information from walking our ancestors and a given target.
|
|
|
|
enum class ScanResult {
|
|
|
|
// Nothing that should stop us from rendering the shadow tree.
|
|
|
|
Ok,
|
|
|
|
// We're never going to be displayed, so no point in updating the shadow
|
|
|
|
// tree.
|
|
|
|
//
|
|
|
|
// However if we're referenced from another tree that tree may need to be
|
|
|
|
// rendered.
|
|
|
|
Invisible,
|
|
|
|
// We're a cyclic reference to either an ancestor or another shadow tree. We
|
|
|
|
// shouldn't render this <use> element.
|
|
|
|
CyclicReference,
|
|
|
|
};
|
|
|
|
ScanResult ScanAncestors(const Element& aTarget) const;
|
2019-03-23 01:26:53 +03:00
|
|
|
|
2017-09-12 12:43:16 +03:00
|
|
|
/**
|
|
|
|
* Helper that provides a reference to the element with the ID that is
|
|
|
|
* referenced by the 'use' element's 'href' attribute, and that will update
|
|
|
|
* the 'use' element if the element that that ID identifies changes to a
|
|
|
|
* different element (or none).
|
|
|
|
*/
|
|
|
|
class ElementTracker final : public IDTracker {
|
2008-06-26 02:41:04 +04:00
|
|
|
public:
|
2017-09-12 12:43:16 +03:00
|
|
|
explicit ElementTracker(SVGUseElement* aOwningUseElement)
|
|
|
|
: mOwningUseElement(aOwningUseElement) {}
|
2018-07-16 17:07:58 +03:00
|
|
|
|
2018-11-30 13:46:48 +03:00
|
|
|
private:
|
2018-07-16 17:07:58 +03:00
|
|
|
void ElementChanged(Element* aFrom, Element* aTo) override {
|
2017-09-08 12:02:05 +03:00
|
|
|
IDTracker::ElementChanged(aFrom, aTo);
|
2008-07-09 14:50:48 +04:00
|
|
|
if (aFrom) {
|
2017-09-12 12:43:16 +03:00
|
|
|
aFrom->RemoveMutationObserver(mOwningUseElement);
|
2008-07-09 14:50:48 +04:00
|
|
|
}
|
2017-09-12 12:43:16 +03:00
|
|
|
mOwningUseElement->TriggerReclone();
|
2008-06-26 02:41:04 +04:00
|
|
|
}
|
2018-07-16 17:07:58 +03:00
|
|
|
|
2017-09-12 12:43:16 +03:00
|
|
|
SVGUseElement* mOwningUseElement;
|
2008-06-26 02:41:04 +04:00
|
|
|
};
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2017-08-27 21:15:03 +03:00
|
|
|
nsSVGUseFrame* GetFrame() const;
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
virtual LengthAttributesInfo GetLengthInfo() override;
|
|
|
|
virtual StringAttributesInfo GetStringInfo() override;
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2012-06-23 20:36:46 +04:00
|
|
|
/**
|
|
|
|
* Returns true if our width and height should be used, or false if they
|
|
|
|
* should be ignored. As per the spec, this depends on the type of the
|
|
|
|
* element that we're referencing.
|
|
|
|
*/
|
|
|
|
bool OurWidthAndHeightAreUsed() const;
|
2017-10-03 01:05:19 +03:00
|
|
|
void SyncWidthOrHeight(nsAtom* aName);
|
2008-06-26 02:41:04 +04:00
|
|
|
void LookupHref();
|
2007-02-18 20:34:09 +03:00
|
|
|
void TriggerReclone();
|
2008-06-26 02:41:04 +04:00
|
|
|
void UnlinkSource();
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2013-01-17 00:50:59 +04:00
|
|
|
enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
|
2019-04-09 23:04:33 +03:00
|
|
|
SVGAnimatedLength mLengthAttributes[4];
|
2007-02-18 20:34:09 +03:00
|
|
|
static LengthInfo sLengthInfo[4];
|
|
|
|
|
2016-07-05 11:37:17 +03:00
|
|
|
enum { HREF, XLINK_HREF };
|
2019-04-04 20:40:56 +03:00
|
|
|
SVGAnimatedString mStringAttributes[2];
|
2016-07-05 11:37:17 +03:00
|
|
|
static StringInfo sStringInfo[2];
|
2007-02-18 20:34:09 +03:00
|
|
|
|
2019-03-23 01:26:53 +03:00
|
|
|
RefPtr<SVGUseElement> mOriginal; // if we've been cloned, our "real" copy
|
2018-07-16 17:07:58 +03:00
|
|
|
ElementTracker mReferencedElementTracker;
|
2017-04-06 09:51:29 +03:00
|
|
|
RefPtr<URLExtraData> mContentURLData; // URL data for its anonymous content
|
2007-02-18 20:34:09 +03:00
|
|
|
};
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|
2007-02-19 22:40:38 +03:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
#endif // mozilla_dom_SVGUseElement_h
|