Bug 436418, patch H: SVG/SMIL animateMotion - add support for <mpath> sub-element. r=roc

This commit is contained in:
Daniel Holbert 2010-04-28 16:00:54 -07:00
parent c121001886
commit 128f3eaa73
14 changed files with 656 additions and 45 deletions

View File

@ -129,6 +129,7 @@ CPPSRCS += nsSVGAnimateElement.cpp \
nsSVGAnimateTransformElement.cpp \
nsSVGAnimateMotionElement.cpp \
nsSVGAnimationElement.cpp \
nsSVGMpathElement.cpp \
nsSVGSetElement.cpp \
nsSVGTransformSMILType.cpp \
nsSVGTransformSMILAttr.cpp \

View File

@ -43,6 +43,7 @@
#include "nsSVGPathDataParser.h"
#include "nsSVGPathSeg.h"
#include "nsSVGPathElement.h" // for nsSVGPathList
#include "nsSVGMpathElement.h"
namespace mozilla {
@ -150,6 +151,25 @@ SVGMotionSMILAnimationFunction::GetCalcMode() const
//----------------------------------------------------------------------
// Helpers for GetValues
/*
* Returns the first <mpath> child of the given element
*/
static nsSVGMpathElement*
GetFirstMpathChild(nsIContent* aElem)
{
PRUint32 childCount = aElem->GetChildCount();
for (PRUint32 i = 0; i < childCount; ++i) {
nsIContent* child = aElem->GetChildAt(i);
if (child->Tag() == nsGkAtoms::mpath &&
child->GetNameSpaceID() == kNameSpaceID_SVG) {
return static_cast<nsSVGMpathElement*>(child);
}
}
return nsnull;
}
void
SVGMotionSMILAnimationFunction::
RebuildPathAndVerticesFromBasicAttrs(const nsIContent* aContextElem)
@ -224,6 +244,27 @@ SVGMotionSMILAnimationFunction::
}
}
void
SVGMotionSMILAnimationFunction::
RebuildPathAndVerticesFromMpathElem(nsSVGMpathElement* aMpathElem)
{
mPathSourceType = ePathSourceType_Mpath;
// Use the path that's the target of our chosen <mpath> child.
nsSVGPathElement* pathElem = aMpathElem->GetReferencedPath();
if (pathElem) {
if (pathElem->HasAttr(kNameSpaceID_None, nsGkAtoms::d)) {
const nsAString& pathSpec =
pathElem->GetParsedAttr(nsGkAtoms::d)->GetStringValue();
nsresult rv = SetPathVerticesFromPathString(pathSpec);
if (NS_SUCCEEDED(rv)) {
mPath = pathElem->GetFlattenedPath(
pathElem->PrependLocalTransformTo(gfxMatrix()));
}
}
}
}
void
SVGMotionSMILAnimationFunction::RebuildPathAndVerticesFromPathAttr()
{
@ -304,9 +345,13 @@ SVGMotionSMILAnimationFunction::
// Do we have a mpath child? if so, it trumps everything. Otherwise, we look
// through our list of path-defining attributes, in order of priority.
// XXXdholbert This is where we should check for mpath, in <mpath> patch.
// ...else, if no mpath child:
if (HasAttr(nsGkAtoms::path)) {
nsSVGMpathElement* firstMpathChild =
GetFirstMpathChild(&mAnimationElement->Content());
if (firstMpathChild) {
RebuildPathAndVerticesFromMpathElem(firstMpathChild);
mValueNeedsReparsingEverySample = PR_FALSE;
} else if (HasAttr(nsGkAtoms::path)) {
RebuildPathAndVerticesFromPathAttr();
mValueNeedsReparsingEverySample = PR_FALSE;
} else {

View File

@ -42,6 +42,8 @@
#include "SVGMotionSMILType.h" // for RotateType
#include "gfxPath.h" // for gfxFlattenedPath
class nsSVGMpathElement;
namespace mozilla {
//----------------------------------------------------------------------
@ -60,6 +62,13 @@ public:
nsresult* aParseResult = nsnull);
NS_OVERRIDE virtual PRBool UnsetAttr(nsIAtom* aAttribute);
// Method to allow our owner-element to signal us when our <mpath>
// has changed or been added/removed. When that happens, we need to
// mark ourselves as changed so we'll get recomposed, and mark our path data
// as stale so it'll get regenerated (regardless of mPathSourceType, since
// <mpath> trumps all the other sources of path data)
void MpathChanged() { mIsPathStale = mHasChanged = PR_TRUE; }
protected:
enum PathSourceType {
// NOTE: Ordering matters here. Higher-priority path-descriptors should
@ -88,6 +97,7 @@ protected:
void MarkStaleIfAttributeAffectsPath(nsIAtom* aAttribute);
nsresult SetPathVerticesFromPathString(const nsAString& aPathSpec);
void RebuildPathAndVertices(const nsIContent* aContextElem);
void RebuildPathAndVerticesFromMpathElem(nsSVGMpathElement* aMpathElem);
void RebuildPathAndVerticesFromPathAttr();
void RebuildPathAndVerticesFromBasicAttrs(const nsIContent* aContextElem);
PRBool GenerateValuesForPathAndPoints(gfxFlattenedPath* aPath,

View File

@ -0,0 +1,4 @@
<svg:mpath xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="#foo">
</svg:mpath>

After

Width:  |  Height:  |  Size: 147 B

View File

@ -42,6 +42,7 @@ load 427325-1.svg
load 428228-1.svg
load 428841-1.svg
load 435209-1.svg
load 436418-mpathRoot-1.svg
load 448244-1.svg
load 466576-1.xhtml
load 535691-1.svg

View File

@ -38,48 +38,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGAnimationElement.h"
#include "nsIDOMSVGAnimateMotionElement.h"
#include "nsSVGEnum.h"
#include "SVGMotionSMILAnimationFunction.h"
#include "nsCOMArray.h"
#include "nsIDOMSVGPathSeg.h"
#include "nsSVGPathSeg.h"
#include "nsSVGPathDataParser.h"
typedef nsSVGAnimationElement nsSVGAnimateMotionElementBase;
class nsSVGAnimateMotionElement : public nsSVGAnimateMotionElementBase,
public nsIDOMSVGAnimateMotionElement
{
protected:
friend nsresult NS_NewSVGAnimateMotionElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGAnimateMotionElement(nsINodeInfo* aNodeInfo);
mozilla::SVGMotionSMILAnimationFunction mAnimationFunction;
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGANIMATEMOTIONELEMENT
NS_FORWARD_NSIDOMNODE(nsSVGAnimateMotionElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGAnimateMotionElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAnimateMotionElementBase::)
NS_FORWARD_NSIDOMSVGANIMATIONELEMENT(nsSVGAnimateMotionElementBase::)
// nsIDOMNode specializations
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// nsISMILAnimationElement
virtual nsSMILAnimationFunction& AnimationFunction();
virtual nsIAtom* GetTargetAttributeName() const;
virtual nsSMILTargetAttrType GetTargetAttributeType() const;
};
#include "nsSVGAnimateMotionElement.h"
NS_IMPL_NS_NEW_SVG_ELEMENT(AnimateMotion)

View File

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NS_SVGANIMATEMOTIONELEMENT_H_
#define NS_SVGANIMATEMOTIONELEMENT_H_
#include "nsSVGAnimationElement.h"
#include "nsIDOMSVGAnimateMotionElement.h"
#include "nsSVGEnum.h"
#include "SVGMotionSMILAnimationFunction.h"
typedef nsSVGAnimationElement nsSVGAnimateMotionElementBase;
class nsSVGAnimateMotionElement : public nsSVGAnimateMotionElementBase,
public nsIDOMSVGAnimateMotionElement
{
protected:
friend nsresult NS_NewSVGAnimateMotionElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGAnimateMotionElement(nsINodeInfo* aNodeInfo);
mozilla::SVGMotionSMILAnimationFunction mAnimationFunction;
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGANIMATEMOTIONELEMENT
NS_FORWARD_NSIDOMNODE(nsSVGAnimateMotionElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGAnimateMotionElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAnimateMotionElementBase::)
NS_FORWARD_NSIDOMSVGANIMATIONELEMENT(nsSVGAnimateMotionElementBase::)
// nsIDOMNode specializations
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// nsISMILAnimationElement
virtual nsSMILAnimationFunction& AnimationFunction();
virtual nsIAtom* GetTargetAttributeName() const;
virtual nsSMILTargetAttrType GetTargetAttributeType() const;
// Utility method to let our <mpath> children tell us when they've changed,
// so we can make sure our mAnimationFunction is marked as having changed.
void MpathChanged() { mAnimationFunction.MpathChanged(); }
};
#endif // NS_SVGANIMATEMOTIONELEMENT_H_

View File

@ -172,6 +172,8 @@ NS_NewSVGAnimateTransformElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGAnimateMotionElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGMpathElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGSetElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
#endif // MOZ_SMIL
@ -313,6 +315,8 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo,
return NS_NewSVGAnimateTransformElement(aResult, aNodeInfo);
if (name == nsGkAtoms::animateMotion)
return NS_NewSVGAnimateMotionElement(aResult, aNodeInfo);
if (name == nsGkAtoms::mpath)
return NS_NewSVGMpathElement(aResult, aNodeInfo);
if (name == nsGkAtoms::set)
return NS_NewSVGSetElement(aResult, aNodeInfo);
}

View File

@ -0,0 +1,296 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGMpathElement.h"
#include "nsAutoPtr.h"
#include "nsDebug.h"
#include "nsSVGPathElement.h"
#include "nsSVGAnimateMotionElement.h"
nsSVGElement::StringInfo nsSVGMpathElement::sStringInfo[1] =
{
{ &nsGkAtoms::href, kNameSpaceID_XLink },
};
NS_IMPL_NS_NEW_SVG_ELEMENT(Mpath)
// Cycle collection magic -- based on nsSVGUseElement
NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGMpathElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGMpathElement,
nsSVGMpathElementBase)
tmp->UnlinkHrefTarget(PR_FALSE);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGMpathElement,
nsSVGMpathElementBase)
tmp->mHrefTarget.Traverse(&cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGMpathElement,nsSVGMpathElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGMpathElement,nsSVGMpathElementBase)
DOMCI_DATA(SVGMpathElement, nsSVGMpathElement)
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGMpathElement)
NS_NODE_INTERFACE_TABLE6(nsSVGMpathElement, nsIDOMNode, nsIDOMElement,
nsIDOMSVGElement, nsIDOMSVGURIReference,
nsIDOMSVGMpathElement, nsIMutationObserver)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGMpathElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGMpathElementBase)
// Constructor
#ifdef _MSC_VER
// Disable "warning C4355: 'this' : used in base member initializer list".
// We can ignore that warning because we know that mHrefTarget's constructor
// doesn't dereference the pointer passed to it.
#pragma warning(push)
#pragma warning(disable:4355)
#endif
nsSVGMpathElement::nsSVGMpathElement(nsINodeInfo* aNodeInfo)
: nsSVGMpathElementBase(aNodeInfo),
mHrefTarget(this)
#ifdef _MSC_VER
#pragma warning(pop)
#endif
{
}
nsSVGMpathElement::~nsSVGMpathElement()
{
UnlinkHrefTarget(PR_FALSE);
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGMpathElement)
//----------------------------------------------------------------------
// nsIDOMSVGURIReference methods
/* readonly attribute nsIDOMSVGAnimatedString href; */
NS_IMETHODIMP
nsSVGMpathElement::GetHref(nsIDOMSVGAnimatedString** aHref)
{
return mStringAttributes[HREF].ToDOMAnimatedString(aHref, this);
}
//----------------------------------------------------------------------
// nsIContent methods
nsresult
nsSVGMpathElement::BindToTree(nsIDocument* aDocument,
nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
NS_ABORT_IF_FALSE(!mHrefTarget.get(),
"Shouldn't have href-target yet "
"(or it should've been cleared)");
nsresult rv = nsSVGMpathElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv,rv);
if (aDocument) {
const nsAttrValue* hrefAttrValue =
mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_XLink);
if (hrefAttrValue) {
UpdateHrefTarget(aParent, hrefAttrValue->GetStringValue());
}
}
return NS_OK;
}
void
nsSVGMpathElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
UnlinkHrefTarget(PR_TRUE);
nsSVGMpathElementBase::UnbindFromTree(aDeep, aNullParent);
}
PRBool
nsSVGMpathElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
PRBool returnVal =
nsSVGMpathElementBase::ParseAttribute(aNamespaceID, aAttribute,
aValue, aResult);
if (aNamespaceID == kNameSpaceID_XLink &&
aAttribute == nsGkAtoms::href &&
IsInDoc()) {
// NOTE: If we fail the IsInDoc call, it's ok -- we'll update the target
// on next BindToTree call.
UpdateHrefTarget(GetParent(), aValue);
}
return returnVal;
}
nsresult
nsSVGMpathElement::UnsetAttr(PRInt32 aNamespaceID,
nsIAtom* aAttribute, PRBool aNotify)
{
nsresult rv = nsSVGMpathElementBase::UnsetAttr(aNamespaceID, aAttribute,
aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNamespaceID == kNameSpaceID_XLink &&
aAttribute == nsGkAtoms::href) {
UnlinkHrefTarget(PR_TRUE);
}
return NS_OK;
}
//----------------------------------------------------------------------
// nsSVGElement methods
nsSVGElement::StringAttributesInfo
nsSVGMpathElement::GetStringInfo()
{
return StringAttributesInfo(mStringAttributes, sStringInfo,
NS_ARRAY_LENGTH(sStringInfo));
}
//----------------------------------------------------------------------
// nsIMutationObserver methods
void
nsSVGMpathElement::AttributeChanged(nsIDocument *aDocument,
nsIContent *aContent,
PRInt32 aNameSpaceID,
nsIAtom *aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::d) {
NotifyParentOfMpathChange(GetParent());
}
}
}
//----------------------------------------------------------------------
// Public helper methods
nsSVGPathElement*
nsSVGMpathElement::GetReferencedPath()
{
if (!HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
NS_ABORT_IF_FALSE(!mHrefTarget.get(),
"We shouldn't have an xlink:href target "
"if we don't have an xlink:href attribute");
return nsnull;
}
nsIContent* genericTarget = mHrefTarget.get();
if (genericTarget &&
genericTarget->Tag() == nsGkAtoms::path) {
return static_cast<nsSVGPathElement*>(genericTarget);
}
return nsnull;
}
//----------------------------------------------------------------------
// Protected helper methods
void
nsSVGMpathElement::UpdateHrefTarget(nsIContent* aParent,
const nsAString& aHrefStr)
{
nsCOMPtr<nsIURI> targetURI;
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI),
aHrefStr, GetOwnerDoc(), baseURI);
// Stop observing old target (if any)
if (mHrefTarget.get()) {
mHrefTarget.get()->RemoveMutationObserver(this);
}
if (aParent) {
// Pass in |aParent| instead of |this| -- first argument is only used
// for a call to GetCurrentDoc(), and |this| might not have a current
// document yet (if our caller is BindToTree).
mHrefTarget.Reset(aParent, targetURI);
} else {
// if we don't have a parent, then there's no animateMotion element
// depending on our target, so there's no point tracking it right now.
mHrefTarget.Unlink();
}
// Start observing new target (if any)
if (mHrefTarget.get()) {
mHrefTarget.get()->AddMutationObserver(this);
}
NotifyParentOfMpathChange(aParent);
}
void
nsSVGMpathElement::UnlinkHrefTarget(PRBool aNotifyParent)
{
// Stop observing old target (if any)
if (mHrefTarget.get()) {
mHrefTarget.get()->RemoveMutationObserver(this);
}
mHrefTarget.Unlink();
if (aNotifyParent) {
NotifyParentOfMpathChange(GetParent());
}
}
void
nsSVGMpathElement::NotifyParentOfMpathChange(nsIContent* aParent)
{
if (aParent &&
aParent->GetNameSpaceID() == kNameSpaceID_SVG &&
aParent->Tag() == nsGkAtoms::animateMotion) {
nsSVGAnimateMotionElement* animateMotionParent =
static_cast<nsSVGAnimateMotionElement*>(aParent);
animateMotionParent->MpathChanged();
AnimationNeedsResample();
}
}

View File

@ -0,0 +1,139 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NS_SVGMPATHELEMENT_H_
#define NS_SVGMPATHELEMENT_H_
#include "nsIDOMSVGMpathElement.h"
#include "nsIDOMSVGURIReference.h"
#include "nsSVGElement.h"
#include "nsStubMutationObserver.h"
#include "nsSVGPathElement.h"
#include "nsSVGString.h"
#include "nsReferencedElement.h"
typedef nsSVGElement nsSVGMpathElementBase;
class nsSVGMpathElement : public nsSVGMpathElementBase,
public nsIDOMSVGMpathElement,
public nsIDOMSVGURIReference,
public nsStubMutationObserver
{
protected:
friend nsresult NS_NewSVGMpathElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGMpathElement(nsINodeInfo* aNodeInfo);
~nsSVGMpathElement();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGMPATHELEMENT
NS_DECL_NSIDOMSVGURIREFERENCE
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSVGMpathElement,
nsSVGMpathElementBase)
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
// Forward interface implementations to base class
NS_FORWARD_NSIDOMNODE(nsSVGMpathElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGMpathElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGMpathElementBase::)
// nsIContent interface
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep, PRBool aNullParent);
virtual nsresult UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
PRBool aNotify);
// nsGenericElement specializations
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
// Public helper method: If our xlink:href attribute links to a <path>
// element, this method returns a pointer to that element. Otherwise,
// this returns nsnull.
nsSVGPathElement* GetReferencedPath();
protected:
class PathReference : public nsReferencedElement {
public:
PathReference(nsSVGMpathElement* aMpathElement) :
mMpathElement(aMpathElement) {}
protected:
// We need to be notified when target changes, in order to request a sample
// (which will clear animation effects that used the old target-path
// and recompute the animation effects using the new target-path).
virtual void ContentChanged(nsIContent* aFrom, nsIContent* aTo) {
nsReferencedElement::ContentChanged(aFrom, aTo);
if (aFrom) {
aFrom->RemoveMutationObserver(mMpathElement);
}
if (aTo) {
aTo->AddMutationObserver(mMpathElement);
}
mMpathElement->NotifyParentOfMpathChange(mMpathElement->GetParent());
}
// We need to override IsPersistent to get persistent tracking (beyond the
// first time the target changes)
virtual PRBool IsPersistent() { return PR_TRUE; }
private:
nsSVGMpathElement* const mMpathElement;
};
virtual StringAttributesInfo GetStringInfo();
void UpdateHrefTarget(nsIContent* aParent, const nsAString& aHrefStr);
void UnlinkHrefTarget(PRBool aNotifyParent);
void NotifyParentOfMpathChange(nsIContent* aParent);
enum { HREF };
nsSVGString mStringAttributes[1];
static StringInfo sStringInfo[1];
PathReference mHrefTarget;
};
#endif // NS_SVGMPATHELEMENT_H_

View File

@ -373,6 +373,7 @@
#include "nsIDOMSVGAnimateElement.h"
#include "nsIDOMSVGAnimateTransformElement.h"
#include "nsIDOMSVGAnimateMotionElement.h"
#include "nsIDOMSVGMpathElement.h"
#include "nsIDOMSVGSetElement.h"
#include "nsIDOMSVGAnimationElement.h"
#include "nsIDOMElementTimeControl.h"
@ -971,6 +972,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGAnimateMotionElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGMpathElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGSetElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
#endif // MOZ_SMIL
@ -2927,6 +2930,12 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGMpathElement, nsIDOMSVGMpathElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
#endif // MOZ_SMIL
DOM_CLASSINFO_MAP_BEGIN(SVGCircleElement, nsIDOMSVGCircleElement)

View File

@ -236,6 +236,7 @@ DOMCI_CLASS(SVGAltGlyphElement)
DOMCI_CLASS(SVGAnimateElement)
DOMCI_CLASS(SVGAnimateTransformElement)
DOMCI_CLASS(SVGAnimateMotionElement)
DOMCI_CLASS(SVGMpathElement)
DOMCI_CLASS(SVGSetElement)
#endif // MOZ_SMIL
DOMCI_CLASS(SVGCircleElement)

View File

@ -135,6 +135,7 @@ XPIDLSRCS += \
nsIDOMSVGAnimateTransformElement.idl \
nsIDOMSVGAnimateMotionElement.idl \
nsIDOMSVGAnimationElement.idl \
nsIDOMSVGMpathElement.idl \
nsIDOMSVGSetElement.idl \
$(NULL)
endif

View File

@ -0,0 +1,60 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMSVGElement.idl"
/**
* For more information on this interface please see
* http://www.w3.org/TR/SVG/animate.html#mpathElement
*/
[scriptable, uuid(752f5ec1-eaf6-4cfa-887b-96bc69ec36b8)]
interface nsIDOMSVGMpathElement
: nsIDOMSVGElement
/*
The SVG DOM makes use of multiple interface inheritance.
Since XPCOM only supports single interface inheritance,
the best thing that we can do is to promise that whenever
an object implements _this_ interface it will also
implement the following interfaces. (We then have to QI to
hop between them.)
nsIDOMSVGURIReference,
nsIDOMSVGExternalResourcesRequired,
*/
{
};