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/. */
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2018-12-28 05:47:10 +03:00
|
|
|
#include "mozilla/dom/SVGUseElement.h"
|
|
|
|
|
2013-12-09 06:52:54 +04:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
2017-09-13 20:34:55 +03:00
|
|
|
#include "mozilla/ErrorResult.h"
|
2018-02-02 16:21:33 +03:00
|
|
|
#include "mozilla/dom/SVGLengthBinding.h"
|
2013-01-17 00:50:59 +04:00
|
|
|
#include "mozilla/dom/SVGUseElementBinding.h"
|
2006-12-26 20:47:52 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2013-01-10 03:02:45 +04:00
|
|
|
#include "mozilla/dom/SVGSVGElement.h"
|
2019-01-02 16:05:23 +03:00
|
|
|
#include "mozilla/dom/Document.h"
|
2010-08-24 11:05:56 +04:00
|
|
|
#include "mozilla/dom/Element.h"
|
2011-08-11 17:29:50 +04:00
|
|
|
#include "nsContentUtils.h"
|
2013-08-24 06:42:40 +04:00
|
|
|
#include "nsIURI.h"
|
2017-04-06 09:51:29 +03:00
|
|
|
#include "mozilla/URLExtraData.h"
|
2017-08-30 16:14:46 +03:00
|
|
|
#include "SVGObserverUtils.h"
|
2017-08-27 21:15:03 +03:00
|
|
|
#include "nsSVGUseFrame.h"
|
2010-08-24 11:05:56 +04:00
|
|
|
|
2018-12-21 14:43:29 +03:00
|
|
|
NS_IMPL_NS_NEW_SVG_ELEMENT(Use)
|
2013-01-17 00:50:58 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
2004-11-23 16:51:57 +03:00
|
|
|
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
JSObject* SVGUseElement::WrapNode(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) {
|
2018-06-26 00:20:54 +03:00
|
|
|
return SVGUseElement_Binding::Wrap(aCx, this, aGivenProto);
|
2013-01-17 00:50:59 +04:00
|
|
|
}
|
|
|
|
|
2004-11-23 16:51:57 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// implementation
|
|
|
|
|
2018-12-21 11:58:14 +03:00
|
|
|
SVGElement::LengthInfo SVGUseElement::sLengthInfo[4] = {
|
2018-03-29 12:45:24 +03:00
|
|
|
{nsGkAtoms::x, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
|
|
|
|
SVGContentUtils::X},
|
|
|
|
{nsGkAtoms::y, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
|
|
|
|
SVGContentUtils::Y},
|
|
|
|
{nsGkAtoms::width, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
|
|
|
|
SVGContentUtils::X},
|
|
|
|
{nsGkAtoms::height, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
|
|
|
|
SVGContentUtils::Y},
|
2006-04-14 19:09:39 +04:00
|
|
|
};
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2018-12-21 11:58:14 +03:00
|
|
|
SVGElement::StringInfo SVGUseElement::sStringInfo[2] = {
|
2018-03-29 12:45:24 +03:00
|
|
|
{nsGkAtoms::href, kNameSpaceID_None, true},
|
|
|
|
{nsGkAtoms::href, kNameSpaceID_XLink, true}};
|
2008-06-14 13:01:02 +04:00
|
|
|
|
2004-11-23 16:51:57 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsISupports methods
|
|
|
|
|
2013-08-02 05:29:05 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(SVGUseElement)
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGUseElement,
|
|
|
|
SVGUseElementBase)
|
2008-04-11 21:29:06 +04:00
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginal)
|
2008-06-26 02:41:04 +04:00
|
|
|
tmp->UnlinkSource();
|
2007-11-30 21:41:10 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
2013-01-17 00:50:58 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGUseElement,
|
|
|
|
SVGUseElementBase)
|
2012-11-15 11:32:40 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginal)
|
2017-09-12 12:43:16 +03:00
|
|
|
tmp->mReferencedElementTracker.Traverse(&cb);
|
2007-11-30 21:41:10 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2017-09-01 02:29:22 +03:00
|
|
|
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(SVGUseElement, SVGUseElementBase,
|
|
|
|
nsIMutationObserver)
|
2004-11-23 16:51:57 +03:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Implementation
|
|
|
|
|
2018-09-21 23:45:49 +03:00
|
|
|
SVGUseElement::SVGUseElement(
|
|
|
|
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
|
|
|
: SVGUseElementBase(std::move(aNodeInfo)),
|
2017-09-12 12:43:16 +03:00
|
|
|
mReferencedElementTracker(this) {}
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
SVGUseElement::~SVGUseElement() {
|
2008-06-26 02:41:04 +04:00
|
|
|
UnlinkSource();
|
2018-07-16 17:07:58 +03:00
|
|
|
MOZ_DIAGNOSTIC_ASSERT(!OwnerDoc()->SVGUseElementNeedsShadowTreeUpdate(*this),
|
|
|
|
"Dying without unbinding?");
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-05-30 05:58:49 +03:00
|
|
|
// nsINode methods
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2018-10-29 02:20:43 +03:00
|
|
|
void SVGUseElement::ProcessAttributeChange(int32_t aNamespaceID,
|
|
|
|
nsAtom* aAttribute) {
|
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
|
|
if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) {
|
|
|
|
if (auto* frame = GetFrame()) {
|
|
|
|
frame->PositionAttributeChanged();
|
|
|
|
}
|
|
|
|
} else if (aAttribute == nsGkAtoms::width ||
|
|
|
|
aAttribute == nsGkAtoms::height) {
|
|
|
|
const bool hadValidDimensions = HasValidDimensions();
|
|
|
|
const bool isUsed = OurWidthAndHeightAreUsed();
|
|
|
|
if (isUsed) {
|
|
|
|
SyncWidthOrHeight(aAttribute);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto* frame = GetFrame()) {
|
|
|
|
frame->DimensionAttributeChanged(hadValidDimensions, isUsed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((aNamespaceID == kNameSpaceID_XLink ||
|
|
|
|
aNamespaceID == kNameSpaceID_None) &&
|
|
|
|
aAttribute == nsGkAtoms::href) {
|
|
|
|
// We're changing our nature, clear out the clone information.
|
|
|
|
if (auto* frame = GetFrame()) {
|
|
|
|
frame->HrefChanged();
|
|
|
|
}
|
|
|
|
mOriginal = nullptr;
|
|
|
|
UnlinkSource();
|
|
|
|
TriggerReclone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult SVGUseElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aAttribute,
|
|
|
|
const nsAttrValue* aValue,
|
|
|
|
const nsAttrValue* aOldValue,
|
|
|
|
nsIPrincipal* aSubjectPrincipal,
|
|
|
|
bool aNotify) {
|
|
|
|
ProcessAttributeChange(aNamespaceID, aAttribute);
|
|
|
|
return SVGUseElementBase::AfterSetAttr(aNamespaceID, aAttribute, aValue,
|
|
|
|
aOldValue, aSubjectPrincipal, aNotify);
|
|
|
|
}
|
|
|
|
|
2018-08-09 02:58:44 +03:00
|
|
|
nsresult SVGUseElement::Clone(dom::NodeInfo* aNodeInfo,
|
|
|
|
nsINode** aResult) const {
|
2012-07-30 18:20:58 +04:00
|
|
|
*aResult = nullptr;
|
2020-03-17 17:53:16 +03:00
|
|
|
SVGUseElement* it =
|
|
|
|
new (aNodeInfo->NodeInfoManager()) SVGUseElement(do_AddRef(aNodeInfo));
|
2005-09-20 19:40:57 +04:00
|
|
|
|
2006-09-05 14:22:54 +04:00
|
|
|
nsCOMPtr<nsINode> kungFuDeathGrip(it);
|
2012-07-27 18:03:08 +04:00
|
|
|
nsresult rv1 = it->Init();
|
2018-08-09 02:58:44 +03:00
|
|
|
nsresult rv2 = const_cast<SVGUseElement*>(this)->CopyInnerTo(it);
|
2005-09-20 19:40:57 +04:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
// SVGUseElement specific portion - record who we cloned from
|
|
|
|
it->mOriginal = const_cast<SVGUseElement*>(this);
|
2005-09-20 19:40:57 +04:00
|
|
|
|
2012-07-27 18:03:08 +04:00
|
|
|
if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
|
2005-09-20 19:40:57 +04:00
|
|
|
kungFuDeathGrip.swap(*aResult);
|
|
|
|
}
|
|
|
|
|
2012-07-27 18:03:08 +04:00
|
|
|
return NS_FAILED(rv1) ? rv1 : rv2;
|
2005-09-20 19:40:57 +04:00
|
|
|
}
|
|
|
|
|
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 SVGUseElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|
|
|
nsresult rv = SVGUseElementBase::BindToTree(aContext, aParent);
|
2018-07-16 17:07:58 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
TriggerReclone();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-05-29 01:47:08 +03:00
|
|
|
void SVGUseElement::UnbindFromTree(bool aNullParent) {
|
|
|
|
SVGUseElementBase::UnbindFromTree(aNullParent);
|
2018-07-16 17:07:58 +03:00
|
|
|
OwnerDoc()->UnscheduleSVGUseElementShadowTreeUpdate(*this);
|
|
|
|
}
|
|
|
|
|
2019-03-19 03:01:03 +03:00
|
|
|
already_AddRefed<DOMSVGAnimatedString> SVGUseElement::Href() {
|
2016-07-05 11:37:17 +03:00
|
|
|
return mStringAttributes[HREF].IsExplicitlySet()
|
|
|
|
? mStringAttributes[HREF].ToDOMAnimatedString(this)
|
|
|
|
: mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2013-01-17 00:50:59 +04:00
|
|
|
|
2019-03-19 03:01:03 +03:00
|
|
|
already_AddRefed<DOMSVGAnimatedLength> SVGUseElement::X() {
|
2013-01-17 00:50:59 +04:00
|
|
|
return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2019-03-19 03:01:03 +03:00
|
|
|
already_AddRefed<DOMSVGAnimatedLength> SVGUseElement::Y() {
|
2013-01-17 00:50:59 +04:00
|
|
|
return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2019-03-19 03:01:03 +03:00
|
|
|
already_AddRefed<DOMSVGAnimatedLength> SVGUseElement::Width() {
|
2013-01-17 00:50:59 +04:00
|
|
|
return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2019-03-19 03:01:03 +03:00
|
|
|
already_AddRefed<DOMSVGAnimatedLength> SVGUseElement::Height() {
|
2013-01-17 00:50:59 +04:00
|
|
|
return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2006-07-11 23:41:11 +04:00
|
|
|
// nsIMutationObserver methods
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
void SVGUseElement::CharacterDataChanged(nsIContent* aContent,
|
2018-02-27 17:30:27 +03:00
|
|
|
const CharacterDataChangeInfo&) {
|
2019-06-13 23:02:42 +03:00
|
|
|
if (nsContentUtils::IsInSameAnonymousTree(mReferencedElementTracker.get(),
|
|
|
|
aContent)) {
|
2007-06-07 00:01:56 +04:00
|
|
|
TriggerReclone();
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
void SVGUseElement::AttributeChanged(Element* aElement, int32_t aNamespaceID,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute, int32_t aModType,
|
2015-07-25 09:01:19 +03:00
|
|
|
const nsAttrValue* aOldValue) {
|
2019-06-13 23:02:42 +03:00
|
|
|
if (nsContentUtils::IsInSameAnonymousTree(mReferencedElementTracker.get(),
|
|
|
|
aElement)) {
|
2007-06-07 00:01:56 +04:00
|
|
|
TriggerReclone();
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
void SVGUseElement::ContentAppended(nsIContent* aFirstNewContent) {
|
|
|
|
// FIXME(emilio, bug 1442336): Why does this check the parent but
|
|
|
|
// ContentInserted the child?
|
2019-06-13 23:02:42 +03:00
|
|
|
if (nsContentUtils::IsInSameAnonymousTree(mReferencedElementTracker.get(),
|
2018-03-01 14:36:58 +03:00
|
|
|
aFirstNewContent->GetParent())) {
|
2007-06-07 00:01:56 +04:00
|
|
|
TriggerReclone();
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
void SVGUseElement::ContentInserted(nsIContent* aChild) {
|
|
|
|
// FIXME(emilio, bug 1442336): Why does this check the child but
|
|
|
|
// ContentAppended the parent?
|
2019-06-13 23:02:42 +03:00
|
|
|
if (nsContentUtils::IsInSameAnonymousTree(mReferencedElementTracker.get(),
|
|
|
|
aChild)) {
|
2007-06-07 00:01:56 +04:00
|
|
|
TriggerReclone();
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
void SVGUseElement::ContentRemoved(nsIContent* aChild,
|
|
|
|
nsIContent* aPreviousSibling) {
|
2019-06-13 23:02:42 +03:00
|
|
|
if (nsContentUtils::IsInSameAnonymousTree(mReferencedElementTracker.get(),
|
|
|
|
aChild)) {
|
2007-06-07 00:01:56 +04:00
|
|
|
TriggerReclone();
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
void SVGUseElement::NodeWillBeDestroyed(const nsINode* aNode) {
|
2010-07-21 19:33:32 +04:00
|
|
|
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
|
2008-06-26 02:41:04 +04:00
|
|
|
UnlinkSource();
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
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
|
|
|
// Returns whether this node could ever be displayed.
|
|
|
|
static bool NodeCouldBeRendered(const nsINode& aNode) {
|
|
|
|
if (aNode.IsSVGElement(nsGkAtoms::symbol)) {
|
|
|
|
// Only <symbol> elements in the root of a <svg:use> shadow tree are
|
|
|
|
// displayed.
|
|
|
|
auto* shadowRoot = ShadowRoot::FromNodeOrNull(aNode.GetParentNode());
|
|
|
|
return shadowRoot && shadowRoot->Host()->IsSVGElement(nsGkAtoms::use);
|
|
|
|
}
|
|
|
|
// TODO: Do we have other cases we can optimize out easily?
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Circular loop detection, plus detection of whether this shadow tree is
|
|
|
|
// rendered at all.
|
|
|
|
auto SVGUseElement::ScanAncestors(const Element& aTarget) const -> ScanResult {
|
2019-03-23 01:26:53 +03:00
|
|
|
if (&aTarget == this) {
|
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
|
|
|
return ScanResult::CyclicReference;
|
2019-03-23 01:26:53 +03:00
|
|
|
}
|
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
|
|
|
if (mOriginal &&
|
|
|
|
mOriginal->ScanAncestors(aTarget) == ScanResult::CyclicReference) {
|
|
|
|
return ScanResult::CyclicReference;
|
2019-03-23 01:26:53 +03:00
|
|
|
}
|
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
|
|
|
auto result = ScanResult::Ok;
|
2019-07-15 14:03:33 +03:00
|
|
|
for (nsINode* parent = GetParentOrShadowHostNode(); parent;
|
|
|
|
parent = parent->GetParentOrShadowHostNode()) {
|
2019-03-23 01:26:53 +03:00
|
|
|
if (parent == &aTarget) {
|
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
|
|
|
return ScanResult::CyclicReference;
|
2019-03-23 01:26:53 +03:00
|
|
|
}
|
|
|
|
if (auto* use = SVGUseElement::FromNode(*parent)) {
|
|
|
|
if (mOriginal && use->mOriginal == mOriginal) {
|
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
|
|
|
return ScanResult::CyclicReference;
|
2019-03-23 01:26:53 +03:00
|
|
|
}
|
|
|
|
}
|
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
|
|
|
// Do we have other similar cases we can optimize out easily?
|
|
|
|
if (!NodeCouldBeRendered(*parent)) {
|
|
|
|
// NOTE(emilio): We can't just return here. If we're cyclic, we need to
|
|
|
|
// know.
|
|
|
|
result = ScanResult::Invisible;
|
|
|
|
}
|
2019-03-23 01:26:53 +03:00
|
|
|
}
|
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
|
|
|
return result;
|
2019-03-23 01:26:53 +03:00
|
|
|
}
|
|
|
|
|
2004-11-23 16:51:57 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
void SVGUseElement::UpdateShadowTree() {
|
|
|
|
MOZ_ASSERT(IsInComposedDoc());
|
|
|
|
|
2017-09-12 12:43:16 +03:00
|
|
|
if (mReferencedElementTracker.get()) {
|
|
|
|
mReferencedElementTracker.get()->RemoveMutationObserver(this);
|
2008-06-26 02:41:04 +04:00
|
|
|
}
|
2006-07-11 23:41:11 +04:00
|
|
|
|
2008-06-26 02:41:04 +04:00
|
|
|
LookupHref();
|
2018-07-16 17:07:58 +03:00
|
|
|
|
|
|
|
RefPtr<ShadowRoot> shadow = GetShadowRoot();
|
|
|
|
if (!shadow) {
|
|
|
|
shadow = AttachShadowWithoutNameChecks(ShadowRootMode::Closed);
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(shadow);
|
|
|
|
|
|
|
|
Element* targetElement = mReferencedElementTracker.get();
|
|
|
|
RefPtr<Element> newElement;
|
|
|
|
|
|
|
|
auto UpdateShadowTree = mozilla::MakeScopeExit([&]() {
|
|
|
|
nsIContent* firstChild = shadow->GetFirstChild();
|
|
|
|
if (firstChild) {
|
|
|
|
MOZ_ASSERT(!firstChild->GetNextSibling());
|
|
|
|
shadow->RemoveChildNode(firstChild, /* aNotify = */ true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newElement) {
|
|
|
|
shadow->AppendChildTo(newElement, /* aNotify = */ true);
|
|
|
|
}
|
|
|
|
});
|
2004-11-23 16:51:57 +03:00
|
|
|
|
|
|
|
// make sure target is valid type for <use>
|
|
|
|
// QIable nsSVGGraphicsElement would eliminate enumerating all elements
|
2018-07-16 17:07:58 +03:00
|
|
|
if (!targetElement ||
|
|
|
|
!targetElement->IsAnyOfSVGElements(
|
2015-03-03 14:09:00 +03:00
|
|
|
nsGkAtoms::svg, nsGkAtoms::symbol, nsGkAtoms::g, nsGkAtoms::path,
|
|
|
|
nsGkAtoms::text, nsGkAtoms::rect, nsGkAtoms::circle,
|
|
|
|
nsGkAtoms::ellipse, nsGkAtoms::line, nsGkAtoms::polyline,
|
|
|
|
nsGkAtoms::polygon, nsGkAtoms::image, nsGkAtoms::use)) {
|
2018-07-16 17:07:58 +03:00
|
|
|
return;
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
|
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
|
|
|
if (ScanAncestors(*targetElement) != ScanResult::Ok) {
|
2018-07-16 17:07:58 +03:00
|
|
|
return;
|
|
|
|
}
|
2005-09-20 19:40:57 +04:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
nsCOMPtr<nsIURI> baseURI = targetElement->GetBaseURI();
|
|
|
|
if (!baseURI) {
|
|
|
|
return;
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
{
|
|
|
|
nsNodeInfoManager* nodeInfoManager = targetElement->OwnerDoc() == OwnerDoc()
|
|
|
|
? nullptr
|
|
|
|
: OwnerDoc()->NodeInfoManager();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-11-05 23:43:53 +03:00
|
|
|
nsCOMPtr<nsINode> newNode =
|
2020-02-11 19:38:18 +03:00
|
|
|
targetElement->Clone(true, nodeInfoManager, IgnoreErrors());
|
2018-07-16 17:07:58 +03:00
|
|
|
if (!newNode) {
|
|
|
|
return;
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
MOZ_ASSERT(newNode->IsElement());
|
|
|
|
newElement = newNode.forget().downcast<Element>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newElement->IsAnyOfSVGElements(nsGkAtoms::svg, nsGkAtoms::symbol)) {
|
2018-12-21 11:58:14 +03:00
|
|
|
auto* newSVGElement = static_cast<SVGElement*>(newElement.get());
|
2013-01-17 00:50:59 +04:00
|
|
|
if (mLengthAttributes[ATTR_WIDTH].IsExplicitlySet())
|
2018-07-16 17:07:58 +03:00
|
|
|
newSVGElement->SetLength(nsGkAtoms::width, mLengthAttributes[ATTR_WIDTH]);
|
2013-01-17 00:50:59 +04:00
|
|
|
if (mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet())
|
2018-07-16 17:07:58 +03:00
|
|
|
newSVGElement->SetLength(nsGkAtoms::height,
|
|
|
|
mLengthAttributes[ATTR_HEIGHT]);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2019-07-16 14:43:56 +03:00
|
|
|
// Bug 1415044 the specs do not say which referrer information we should use.
|
|
|
|
// This may change if there's any spec comes out.
|
|
|
|
nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo();
|
|
|
|
referrerInfo->InitWithNode(this);
|
|
|
|
|
|
|
|
mContentURLData = new URLExtraData(baseURI.forget(), referrerInfo.forget(),
|
|
|
|
do_AddRef(NodePrincipal()));
|
2008-09-28 23:18:04 +04:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
targetElement->AddMutationObserver(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2016-09-20 09:13:13 +03:00
|
|
|
nsIURI* SVGUseElement::GetSourceDocURI() {
|
2018-07-16 17:07:58 +03:00
|
|
|
nsIContent* targetElement = mReferencedElementTracker.get();
|
|
|
|
if (!targetElement) {
|
2016-09-20 09:13:13 +03:00
|
|
|
return nullptr;
|
2018-07-16 17:07:58 +03:00
|
|
|
}
|
2016-09-20 09:13:13 +03:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
return targetElement->OwnerDoc()->GetDocumentURI();
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsINode* GetClonedChild(const SVGUseElement& aUseElement) {
|
|
|
|
const ShadowRoot* shadow = aUseElement.GetShadowRoot();
|
|
|
|
return shadow ? shadow->GetFirstChild() : nullptr;
|
2016-09-20 09:13:13 +03:00
|
|
|
}
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
bool SVGUseElement::OurWidthAndHeightAreUsed() const {
|
2018-07-16 17:07:58 +03:00
|
|
|
nsINode* clonedChild = GetClonedChild(*this);
|
|
|
|
return clonedChild &&
|
|
|
|
clonedChild->IsAnyOfSVGElements(nsGkAtoms::svg, nsGkAtoms::symbol);
|
2012-06-23 20:36:46 +04:00
|
|
|
}
|
|
|
|
|
2004-11-23 16:51:57 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// implementation helpers
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
void SVGUseElement::SyncWidthOrHeight(nsAtom* aName) {
|
2011-10-08 10:32:44 +04:00
|
|
|
NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height,
|
|
|
|
"The clue is in the function name");
|
2012-06-23 20:36:46 +04:00
|
|
|
NS_ASSERTION(OurWidthAndHeightAreUsed(), "Don't call this");
|
2011-10-08 10:32:44 +04:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
if (!OurWidthAndHeightAreUsed()) {
|
|
|
|
return;
|
|
|
|
}
|
2017-08-27 21:15:03 +03:00
|
|
|
|
2018-12-21 11:58:14 +03:00
|
|
|
auto* target = SVGElement::FromNode(GetClonedChild(*this));
|
2018-03-29 12:45:24 +03:00
|
|
|
uint32_t index =
|
|
|
|
sLengthInfo[ATTR_WIDTH].mName == aName ? ATTR_WIDTH : ATTR_HEIGHT;
|
2012-03-03 13:21:09 +04:00
|
|
|
|
2018-07-16 17:07:58 +03:00
|
|
|
if (mLengthAttributes[index].IsExplicitlySet()) {
|
|
|
|
target->SetLength(aName, mLengthAttributes[index]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (target->IsSVGElement(nsGkAtoms::svg)) {
|
2012-03-03 13:21:09 +04:00
|
|
|
// Our width/height attribute is now no longer explicitly set, so we
|
2018-07-16 17:07:58 +03:00
|
|
|
// need to revert the clone's width/height to the width/height of the
|
|
|
|
// content that's being cloned.
|
|
|
|
TriggerReclone();
|
2012-03-03 13:21:09 +04:00
|
|
|
return;
|
2006-04-14 19:09:39 +04:00
|
|
|
}
|
2018-07-16 17:07:58 +03:00
|
|
|
// Our width/height attribute is now no longer explicitly set, so we
|
|
|
|
// need to set the value to 100%
|
2019-04-09 23:04:33 +03:00
|
|
|
SVGAnimatedLength length;
|
2018-07-16 17:07:58 +03:00
|
|
|
length.Init(SVGContentUtils::XY, 0xff, 100,
|
|
|
|
SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE);
|
|
|
|
target->SetLength(aName, length);
|
2006-04-14 19:09:39 +04:00
|
|
|
}
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
void SVGUseElement::LookupHref() {
|
2009-01-22 03:56:51 +03:00
|
|
|
nsAutoString href;
|
2016-07-05 11:37:17 +03:00
|
|
|
if (mStringAttributes[HREF].IsExplicitlySet()) {
|
|
|
|
mStringAttributes[HREF].GetAnimValue(href, this);
|
|
|
|
} else {
|
|
|
|
mStringAttributes[XLINK_HREF].GetAnimValue(href, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (href.IsEmpty()) {
|
2008-06-26 02:41:04 +04:00
|
|
|
return;
|
2016-07-05 11:37:17 +03:00
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
|
2017-04-18 21:06:07 +03:00
|
|
|
nsCOMPtr<nsIURI> originURI =
|
|
|
|
mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
|
|
|
|
nsCOMPtr<nsIURI> baseURI =
|
|
|
|
nsContentUtils::IsLocalRefURL(href)
|
2017-08-30 17:58:31 +03:00
|
|
|
? SVGObserverUtils::GetBaseURLForLocalRef(this, originURI)
|
2017-04-18 21:06:07 +03:00
|
|
|
: originURI;
|
|
|
|
|
2008-09-28 23:16:15 +04:00
|
|
|
nsCOMPtr<nsIURI> targetURI;
|
2006-07-11 23:41:11 +04:00
|
|
|
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
|
2014-10-03 16:32:26 +04:00
|
|
|
GetComposedDoc(), baseURI);
|
2019-07-16 14:43:56 +03:00
|
|
|
nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
|
|
|
ReferrerInfo::CreateForSVGResources(OwnerDoc());
|
|
|
|
|
|
|
|
mReferencedElementTracker.ResetToURIFragmentID(this, targetURI, referrerInfo);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
void SVGUseElement::TriggerReclone() {
|
2019-01-02 16:05:23 +03:00
|
|
|
if (Document* doc = GetComposedDoc()) {
|
2018-07-16 17:07:58 +03:00
|
|
|
doc->ScheduleSVGUseElementShadowTreeUpdate(*this);
|
|
|
|
}
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
void SVGUseElement::UnlinkSource() {
|
2017-09-12 12:43:16 +03:00
|
|
|
if (mReferencedElementTracker.get()) {
|
|
|
|
mReferencedElementTracker.get()->RemoveMutationObserver(this);
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
2017-09-12 12:43:16 +03:00
|
|
|
mReferencedElementTracker.Unlink();
|
2004-11-23 16:51:57 +03:00
|
|
|
}
|
2006-04-14 19:09:39 +04:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2018-12-21 11:58:14 +03:00
|
|
|
// SVGElement methods
|
2006-04-14 19:09:39 +04:00
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* virtual */
|
|
|
|
gfxMatrix SVGUseElement::PrependLocalTransformsTo(
|
2015-12-03 01:36:23 +03:00
|
|
|
const gfxMatrix& aMatrix, SVGTransformTypes aWhich) const {
|
2012-02-17 12:12:47 +04:00
|
|
|
// 'transform' attribute:
|
2017-02-23 11:35:08 +03:00
|
|
|
gfxMatrix userToParent;
|
|
|
|
|
|
|
|
if (aWhich == eUserSpaceToParent || aWhich == eAllTransforms) {
|
2020-02-25 23:03:26 +03:00
|
|
|
userToParent = GetUserToParentTransform(mAnimateMotionTransform.get(),
|
|
|
|
mTransforms.get());
|
2017-02-23 11:35:08 +03:00
|
|
|
if (aWhich == eUserSpaceToParent) {
|
|
|
|
return userToParent * aMatrix;
|
|
|
|
}
|
2012-02-17 12:12:47 +04:00
|
|
|
}
|
2017-02-23 11:35:08 +03:00
|
|
|
|
2012-02-17 12:12:47 +04:00
|
|
|
// our 'x' and 'y' attributes:
|
2009-04-29 08:31:34 +04:00
|
|
|
float x, y;
|
2013-01-17 00:50:58 +04:00
|
|
|
const_cast<SVGUseElement*>(this)->GetAnimatedLengthValues(&x, &y, nullptr);
|
2017-02-23 11:35:08 +03:00
|
|
|
|
|
|
|
gfxMatrix childToUser = gfxMatrix::Translation(x, y);
|
|
|
|
|
|
|
|
if (aWhich == eAllTransforms) {
|
|
|
|
return childToUser * userToParent * aMatrix;
|
2012-02-17 12:12:47 +04:00
|
|
|
}
|
2017-02-23 11:35:08 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(aWhich == eChildToUserSpace, "Unknown TransformTypes");
|
|
|
|
|
|
|
|
// The following may look broken because pre-multiplying our eChildToUserSpace
|
|
|
|
// transform with another matrix without including our eUserSpaceToParent
|
|
|
|
// 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;
|
2009-04-29 08:31:34 +04:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* virtual */
|
|
|
|
bool SVGUseElement::HasValidDimensions() const {
|
2013-01-17 00:50:59 +04:00
|
|
|
return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() ||
|
|
|
|
mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
|
|
|
|
(!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() ||
|
|
|
|
mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0);
|
2012-03-03 13:21:09 +04:00
|
|
|
}
|
|
|
|
|
2018-12-21 11:58:14 +03:00
|
|
|
SVGElement::LengthAttributesInfo SVGUseElement::GetLengthInfo() {
|
2006-04-14 19:09:39 +04:00
|
|
|
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
|
2011-10-11 09:50:08 +04:00
|
|
|
ArrayLength(sLengthInfo));
|
2006-04-14 19:09:39 +04:00
|
|
|
}
|
2006-10-20 03:48:12 +04:00
|
|
|
|
2018-12-21 11:58:14 +03:00
|
|
|
SVGElement::StringAttributesInfo SVGUseElement::GetStringInfo() {
|
2008-06-14 13:01:02 +04:00
|
|
|
return StringAttributesInfo(mStringAttributes, sStringInfo,
|
2011-10-11 09:50:08 +04:00
|
|
|
ArrayLength(sStringInfo));
|
2008-06-14 13:01:02 +04:00
|
|
|
}
|
|
|
|
|
2017-08-27 21:15:03 +03:00
|
|
|
nsSVGUseFrame* SVGUseElement::GetFrame() const {
|
|
|
|
nsIFrame* frame = GetPrimaryFrame();
|
2018-10-29 22:30:22 +03:00
|
|
|
// We might be a plain nsSVGContainerFrame if we didn't pass the conditional
|
|
|
|
// processing checks.
|
|
|
|
if (!frame || !frame->IsSVGUseFrame()) {
|
|
|
|
MOZ_ASSERT_IF(frame, frame->Type() == LayoutFrameType::None);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-08-27 21:15:03 +03:00
|
|
|
return static_cast<nsSVGUseFrame*>(frame);
|
|
|
|
}
|
|
|
|
|
2006-10-20 03:48:12 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIContent methods
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP_(bool)
|
2017-10-03 01:05:19 +03:00
|
|
|
SVGUseElement::IsAttributeMapped(const nsAtom* name) const {
|
2006-10-20 03:48:12 +04:00
|
|
|
static const MappedAttributeEntry* const map[] = {sFEFloodMap,
|
2007-01-30 16:19:55 +03:00
|
|
|
sFiltersMap,
|
2006-10-20 03:48:12 +04:00
|
|
|
sFontSpecificationMap,
|
|
|
|
sGradientStopMap,
|
2007-07-26 10:57:42 +04:00
|
|
|
sLightingEffectsMap,
|
2006-10-20 03:48:12 +04:00
|
|
|
sMarkersMap,
|
|
|
|
sTextContentElementsMap,
|
2007-01-19 18:20:11 +03:00
|
|
|
sViewportsMap};
|
2006-10-20 03:48:12 +04:00
|
|
|
|
2011-12-18 14:09:27 +04:00
|
|
|
return FindAttributeDependence(name, map) ||
|
2013-01-17 00:50:58 +04:00
|
|
|
SVGUseElementBase::IsAttributeMapped(name);
|
2006-10-20 03:48:12 +04:00
|
|
|
}
|
2009-01-22 03:56:51 +03:00
|
|
|
|
2013-01-17 00:50:58 +04:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|