Bug 1362400 part 1 - Make it possible for SMIL to change the link state of an SVG anchor element r=jwatt r=smaug (DOM)

This commit is contained in:
Robert Longson 2017-05-06 20:32:14 +01:00
Родитель e8e5fe66b7
Коммит 5bf763e903
8 изменённых файлов: 60 добавлений и 26 удалений

Просмотреть файл

@ -115,7 +115,7 @@ public:
virtual size_t
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
bool ElementHasHref() const;
virtual bool ElementHasHref() const;
// This is called by HTMLAnchorElement.
void TryDNSPrefetch();

Просмотреть файл

@ -12,6 +12,7 @@ interface nsIDOMMutationEvent : nsISupports
const unsigned short MODIFICATION = 1;
const unsigned short ADDITION = 2;
const unsigned short REMOVAL = 3;
const unsigned short SMIL = 4;
readonly attribute nsIDOMNode relatedNode;
readonly attribute DOMString prevValue;

Просмотреть файл

@ -80,6 +80,16 @@ SVGAElement::Href()
: mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
}
//----------------------------------------------------------------------
// Link methods
bool
SVGAElement::ElementHasHref() const
{
return mStringAttributes[HREF].IsExplicitlySet() ||
mStringAttributes[XLINK_HREF].IsExplicitlySet();
}
//----------------------------------------------------------------------
// nsINode methods
@ -277,13 +287,9 @@ SVGAElement::IsLink(nsIURI** aURI) const
{ &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nullptr };
// Optimization: check for href first for early return
bool useXLink = !HasAttr(kNameSpaceID_None, nsGkAtoms::href);
const nsAttrValue* href =
useXLink
? mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_XLink)
: mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_None);
bool useBareHref = mStringAttributes[HREF].IsExplicitlySet();
if (href &&
if ((useBareHref || mStringAttributes[XLINK_HREF].IsExplicitlySet()) &&
FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::type,
sTypeVals, eCaseMatters) !=
nsIContent::ATTR_VALUE_NO_MATCH &&
@ -296,7 +302,7 @@ SVGAElement::IsLink(nsIURI** aURI) const
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
// Get absolute URI
nsAutoString str;
const uint8_t idx = useXLink ? XLINK_HREF : HREF;
const uint8_t idx = useBareHref ? HREF : XLINK_HREF;
mStringAttributes[idx].GetAnimValue(str, this);
nsContentUtils::NewURIWithDocumentCharset(aURI, str, OwnerDoc(), baseURI);
// must promise out param is non-null if we return true
@ -373,9 +379,7 @@ SVGAElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
if (aAttr == nsGkAtoms::href &&
(aNameSpaceID == kNameSpaceID_XLink ||
aNameSpaceID == kNameSpaceID_None)) {
bool hasHref = HasAttr(kNameSpaceID_None, nsGkAtoms::href) ||
HasAttr(kNameSpaceID_XLink, nsGkAtoms::href);
Link::ResetLinkState(!!aNotify, hasHref);
Link::ResetLinkState(!!aNotify, Link::ElementHasHref());
}
return rv;

Просмотреть файл

@ -68,6 +68,9 @@ public:
virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify) override;
// Link
virtual bool ElementHasHref() const override;
// WebIDL
already_AddRefed<SVGAnimatedString> Href();
already_AddRefed<SVGAnimatedString> Target();

Просмотреть файл

@ -1612,7 +1612,7 @@ nsSVGElement::DidAnimateLength(uint8_t aAttrEnum)
LengthAttributesInfo info = GetLengthInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mLengthInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -1709,7 +1709,7 @@ nsSVGElement::DidAnimateLengthList(uint8_t aAttrEnum)
LengthListAttributesInfo info = GetLengthListInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mLengthListInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -1797,7 +1797,7 @@ nsSVGElement::DidAnimateNumberList(uint8_t aAttrEnum)
frame->AttributeChanged(kNameSpaceID_None,
*info.mNumberListInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -1858,7 +1858,7 @@ nsSVGElement::DidAnimatePointList()
if (frame) {
frame->AttributeChanged(kNameSpaceID_None,
GetPointListAttrName(),
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -1895,7 +1895,7 @@ nsSVGElement::DidAnimatePathSegList()
if (frame) {
frame->AttributeChanged(kNameSpaceID_None,
GetPathDataAttrName(),
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -1936,7 +1936,7 @@ nsSVGElement::DidAnimateNumber(uint8_t aAttrEnum)
NumberAttributesInfo info = GetNumberInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mNumberInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2006,7 +2006,7 @@ nsSVGElement::DidAnimateNumberPair(uint8_t aAttrEnum)
NumberPairAttributesInfo info = GetNumberPairInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mNumberPairInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2047,7 +2047,7 @@ nsSVGElement::DidAnimateInteger(uint8_t aAttrEnum)
IntegerAttributesInfo info = GetIntegerInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mIntegerInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2118,7 +2118,7 @@ nsSVGElement::DidAnimateIntegerPair(uint8_t aAttrEnum)
IntegerPairAttributesInfo info = GetIntegerPairInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mIntegerPairInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2166,7 +2166,7 @@ nsSVGElement::DidAnimateAngle(uint8_t aAttrEnum)
AngleAttributesInfo info = GetAngleInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mAngleInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2205,7 +2205,7 @@ nsSVGElement::DidAnimateBoolean(uint8_t aAttrEnum)
BooleanAttributesInfo info = GetBooleanInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mBooleanInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2244,7 +2244,7 @@ nsSVGElement::DidAnimateEnum(uint8_t aAttrEnum)
EnumAttributesInfo info = GetEnumInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mEnumInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2281,7 +2281,7 @@ nsSVGElement::DidAnimateViewBox()
if (frame) {
frame->AttributeChanged(kNameSpaceID_None,
nsGkAtoms::viewBox,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2321,7 +2321,7 @@ nsSVGElement::DidAnimatePreserveAspectRatio()
if (frame) {
frame->AttributeChanged(kNameSpaceID_None,
nsGkAtoms::preserveAspectRatio,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}
@ -2419,7 +2419,7 @@ nsSVGElement::DidAnimateString(uint8_t aAttrEnum)
StringAttributesInfo info = GetStringInfo();
frame->AttributeChanged(info.mStringInfo[aAttrEnum].mNamespaceID,
*info.mStringInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
nsIDOMMutationEvent::SMIL);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg">
<animate href="#x" attributeName="href" values="https://www.google.com"/>
<a id="x" fill="red"><rect x="15" y="15" width="200" height="200"/></a>
<style>
a:any-link {
fill: blue;
}
</style>
</svg>

После

Ширина:  |  Высота:  |  Размер: 260 B

Просмотреть файл

@ -205,6 +205,7 @@ fails-if(!stylo) == anim-strokecolor-1.svg anim-standard-ref.svg # bug 436296
== anim-targethref-7.svg anim-standard-ref.svg
== anim-targethref-8.svg anim-standard-ref.svg
== anim-targethref-9.svg anim-standard-ref.svg
== anim-targethref-10.svg anim-standard-ref.svg
== anim-text-rotate-01.svg anim-text-rotate-01-ref.svg
== anim-feFuncR-tableValues-01.svg anim-feFuncR-tableValues-01-ref.svg

Просмотреть файл

@ -7,6 +7,7 @@
#include "gfxMatrix.h"
#include "mozilla/dom/SVGAElement.h"
#include "nsAutoPtr.h"
#include "nsIDOMMutationEvent.h"
#include "nsSVGContainerFrame.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGUtils.h"
@ -94,6 +95,21 @@ nsSVGAFrame::AttributeChanged(int32_t aNameSpaceID,
NotifySVGChanged(TRANSFORM_CHANGED);
}
// Currently our SMIL implementation does not modify the DOM attributes. Once
// we implement the SVG 2 SMIL behaviour this can be removed
// SVGAElement::SetAttr/UnsetAttr's ResetLinkState() call will be sufficient.
if (aModType == nsIDOMMutationEvent::SMIL &&
aAttribute == nsGkAtoms::href &&
(aNameSpaceID == kNameSpaceID_None ||
aNameSpaceID == kNameSpaceID_XLink)) {
dom::SVGAElement* content = static_cast<dom::SVGAElement*>(mContent);
// SMIL may change whether an <a> element is a link, in which case we will
// need to update the link state.
content->ResetLinkState(true, content->ElementHasHref());
}
return NS_OK;
}