Bug 824229 Part 7: Make nsSVGClipPathElement inherit from SVGTransformableElement to preserve existing behavior; move SVGGraphicsElement up to SVGTransformableElement r=longsonr

This commit is contained in:
David Zbarsky 2013-01-06 01:25:54 -05:00
parent 937861a33d
commit 6a754329b5
5 changed files with 157 additions and 163 deletions

View File

@ -3,21 +3,7 @@
* 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/. */
#include "mozilla/Util.h"
#include "mozilla/dom/SVGGraphicsElement.h"
#include "nsSVGSVGElement.h"
#include "DOMSVGAnimatedTransformList.h"
#include "DOMSVGMatrix.h"
#include "nsGkAtoms.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMMutationEvent.h"
#include "nsIFrame.h"
#include "nsISVGChildFrame.h"
#include "nsSVGUtils.h"
#include "nsError.h"
#include "nsSVGRect.h"
#include "nsContentUtils.h"
#include "mozilla/dom/SVGGraphicsElementBinding.h"
namespace mozilla {
@ -47,120 +33,5 @@ SVGGraphicsElement::SVGGraphicsElement(already_AddRefed<nsINodeInfo> aNodeInfo)
{
}
//----------------------------------------------------------------------
// nsIContent methods
NS_IMETHODIMP_(bool)
SVGGraphicsElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sColorMap,
sFillStrokeMap,
sGraphicsMap
};
return FindAttributeDependence(name, map) ||
SVGGraphicsElementBase::IsAttributeMapped(name);
}
nsChangeHint
SVGGraphicsElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const
{
nsChangeHint retval =
SVGGraphicsElementBase::GetAttributeChangeHint(aAttribute, aModType);
if (aAttribute == nsGkAtoms::transform ||
aAttribute == nsGkAtoms::mozAnimateMotionDummyAttr) {
// We add nsChangeHint_UpdateOverflow so that nsFrame::UpdateOverflow()
// will be called on us and our ancestors.
nsIFrame* frame =
const_cast<SVGGraphicsElement*>(this)->GetPrimaryFrame();
if (!frame || (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
return retval; // no change
}
if (aModType == nsIDOMMutationEvent::ADDITION ||
aModType == nsIDOMMutationEvent::REMOVAL) {
// Reconstruct the frame tree to handle stacking context changes:
NS_UpdateHint(retval, nsChangeHint_ReconstructFrame);
} else {
NS_ABORT_IF_FALSE(aModType == nsIDOMMutationEvent::MODIFICATION,
"Unknown modification type.");
// We just assume the old and new transforms are different.
NS_UpdateHint(retval, NS_CombineHint(nsChangeHint_UpdateOverflow,
nsChangeHint_UpdateTransformLayer));
}
}
return retval;
}
bool
SVGGraphicsElement::IsEventAttributeName(nsIAtom* aName)
{
return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
}
//----------------------------------------------------------------------
// nsSVGElement overrides
gfxMatrix
SVGGraphicsElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
TransformTypes aWhich) const
{
NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
"Skipping eUserSpaceToParent transforms makes no sense");
gfxMatrix result(aMatrix);
if (aWhich == eChildToUserSpace) {
// We don't have anything to prepend.
// eChildToUserSpace is not the common case, which is why we return
// 'result' to benefit from NRVO rather than returning aMatrix before
// creating 'result'.
return result;
}
NS_ABORT_IF_FALSE(aWhich == eAllTransforms || aWhich == eUserSpaceToParent,
"Unknown TransformTypes");
// animateMotion's resulting transform is supposed to apply *on top of*
// any transformations from the |transform| attribute. So since we're
// PRE-multiplying, we need to apply the animateMotion transform *first*.
if (mAnimateMotionTransform) {
result.PreMultiply(*mAnimateMotionTransform);
}
if (mTransforms) {
result.PreMultiply(mTransforms->GetAnimValue().GetConsolidationMatrix());
}
return result;
}
const gfxMatrix*
SVGGraphicsElement::GetAnimateMotionTransform() const
{
return mAnimateMotionTransform.get();
}
void
SVGGraphicsElement::SetAnimateMotionTransform(const gfxMatrix* aMatrix)
{
if ((!aMatrix && !mAnimateMotionTransform) ||
(aMatrix && mAnimateMotionTransform && *aMatrix == *mAnimateMotionTransform)) {
return;
}
mAnimateMotionTransform = aMatrix ? new gfxMatrix(*aMatrix) : nullptr;
DidAnimateTransformList();
}
SVGAnimatedTransformList*
SVGGraphicsElement::GetAnimatedTransformList(uint32_t aFlags)
{
if (!mTransforms && (aFlags & DO_ALLOCATE)) {
mTransforms = new SVGAnimatedTransformList();
}
return mTransforms;
}
} // namespace dom
} // namespace mozilla

View File

@ -6,9 +6,7 @@
#ifndef mozilla_dom_SVGGraphicsElement_h
#define mozilla_dom_SVGGraphicsElement_h
#include "gfxMatrix.h"
#include "SVGTransformableElement.h"
#include "SVGAnimatedTransformList.h"
#include "mozilla/dom/SVGTransformableElement.h"
#include "DOMSVGTests.h"
#define MOZILLA_SVGGRAPHICSELEMENT_IID \
@ -33,36 +31,9 @@ public:
NS_FORWARD_NSIDOMSVGLOCATABLE(SVGLocatableElement::)
NS_FORWARD_NSIDOMSVGTRANSFORMABLE(SVGTransformableElement::)
// nsIContent interface
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const;
virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
TransformTypes aWhich = eAllTransforms) const;
virtual const gfxMatrix* GetAnimateMotionTransform() const;
virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix);
virtual SVGAnimatedTransformList*
GetAnimatedTransformList(uint32_t aFlags = 0);
virtual nsIAtom* GetTransformListAttrName() const {
return nsGkAtoms::transform;
}
protected:
virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE;
// nsSVGElement overrides
nsAutoPtr<SVGAnimatedTransformList> mTransforms;
// XXX maybe move this to property table, to save space on un-animated elems?
nsAutoPtr<gfxMatrix> mAnimateMotionTransform;
};
NS_DEFINE_STATIC_IID_ACCESSOR(SVGGraphicsElement,

View File

@ -3,8 +3,12 @@
* 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/. */
#include "SVGTransformableElement.h"
#include "mozilla/dom/SVGTransformableElement.h"
#include "DOMSVGAnimatedTransformList.h"
#include "nsIDOMMutationEvent.h"
#include "nsIFrame.h"
#include "nsSVGUtils.h"
#include "nsContentUtils.h"
namespace mozilla {
namespace dom {
@ -41,6 +45,121 @@ SVGTransformableElement::Transform()
}
//----------------------------------------------------------------------
// nsIContent methods
NS_IMETHODIMP_(bool)
SVGTransformableElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sColorMap,
sFillStrokeMap,
sGraphicsMap
};
return FindAttributeDependence(name, map) ||
SVGLocatableElement::IsAttributeMapped(name);
}
nsChangeHint
SVGTransformableElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const
{
nsChangeHint retval =
SVGLocatableElement::GetAttributeChangeHint(aAttribute, aModType);
if (aAttribute == nsGkAtoms::transform ||
aAttribute == nsGkAtoms::mozAnimateMotionDummyAttr) {
// We add nsChangeHint_UpdateOverflow so that nsFrame::UpdateOverflow()
// will be called on us and our ancestors.
nsIFrame* frame =
const_cast<SVGTransformableElement*>(this)->GetPrimaryFrame();
if (!frame || (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
return retval; // no change
}
if (aModType == nsIDOMMutationEvent::ADDITION ||
aModType == nsIDOMMutationEvent::REMOVAL) {
// Reconstruct the frame tree to handle stacking context changes:
NS_UpdateHint(retval, nsChangeHint_ReconstructFrame);
} else {
NS_ABORT_IF_FALSE(aModType == nsIDOMMutationEvent::MODIFICATION,
"Unknown modification type.");
// We just assume the old and new transforms are different.
NS_UpdateHint(retval, NS_CombineHint(nsChangeHint_UpdateOverflow,
nsChangeHint_UpdateTransformLayer));
}
}
return retval;
}
bool
SVGTransformableElement::IsEventAttributeName(nsIAtom* aName)
{
return nsContentUtils::IsEventAttributeName(aName, EventNameType_SVGGraphic);
}
//----------------------------------------------------------------------
// nsSVGElement overrides
gfxMatrix
SVGTransformableElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
TransformTypes aWhich) const
{
NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
"Skipping eUserSpaceToParent transforms makes no sense");
gfxMatrix result(aMatrix);
if (aWhich == eChildToUserSpace) {
// We don't have anything to prepend.
// eChildToUserSpace is not the common case, which is why we return
// 'result' to benefit from NRVO rather than returning aMatrix before
// creating 'result'.
return result;
}
NS_ABORT_IF_FALSE(aWhich == eAllTransforms || aWhich == eUserSpaceToParent,
"Unknown TransformTypes");
// animateMotion's resulting transform is supposed to apply *on top of*
// any transformations from the |transform| attribute. So since we're
// PRE-multiplying, we need to apply the animateMotion transform *first*.
if (mAnimateMotionTransform) {
result.PreMultiply(*mAnimateMotionTransform);
}
if (mTransforms) {
result.PreMultiply(mTransforms->GetAnimValue().GetConsolidationMatrix());
}
return result;
}
const gfxMatrix*
SVGTransformableElement::GetAnimateMotionTransform() const
{
return mAnimateMotionTransform.get();
}
void
SVGTransformableElement::SetAnimateMotionTransform(const gfxMatrix* aMatrix)
{
if ((!aMatrix && !mAnimateMotionTransform) ||
(aMatrix && mAnimateMotionTransform && *aMatrix == *mAnimateMotionTransform)) {
return;
}
mAnimateMotionTransform = aMatrix ? new gfxMatrix(*aMatrix) : nullptr;
DidAnimateTransformList();
}
SVGAnimatedTransformList*
SVGTransformableElement::GetAnimatedTransformList(uint32_t aFlags)
{
if (!mTransforms && (aFlags & DO_ALLOCATE)) {
mTransforms = new SVGAnimatedTransformList();
}
return mTransforms;
}
} // namespace dom
} // namespace mozilla

View File

@ -6,8 +6,10 @@
#ifndef SVGTransformableElement_h
#define SVGTransformableElement_h
#include "SVGLocatableElement.h"
#include "mozilla/dom/SVGLocatableElement.h"
#include "nsIDOMSVGTransformable.h"
#include "gfxMatrix.h"
#include "SVGAnimatedTransformList.h"
#define MOZILLA_SVGTRANSFORMABLEELEMENT_IID \
{ 0x77888cba, 0x0b43, 0x4654, \
@ -31,6 +33,35 @@ public:
// WebIDL
already_AddRefed<DOMSVGAnimatedTransformList> Transform();
// nsIContent interface
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const;
virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
TransformTypes aWhich = eAllTransforms) const;
virtual const gfxMatrix* GetAnimateMotionTransform() const;
virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix);
virtual SVGAnimatedTransformList*
GetAnimatedTransformList(uint32_t aFlags = 0);
virtual nsIAtom* GetTransformListAttrName() const {
return nsGkAtoms::transform;
}
protected:
// nsSVGElement overrides
nsAutoPtr<SVGAnimatedTransformList> mTransforms;
// XXX maybe move this to property table, to save space on un-animated elems?
nsAutoPtr<gfxMatrix> mAnimateMotionTransform;
};
NS_DEFINE_STATIC_IID_ACCESSOR(SVGTransformableElement,

View File

@ -9,9 +9,9 @@
#include "nsIDOMSVGClipPathElement.h"
#include "nsIDOMSVGUnitTypes.h"
#include "nsSVGEnum.h"
#include "SVGGraphicsElement.h"
#include "mozilla/dom/SVGTransformableElement.h"
typedef mozilla::dom::SVGGraphicsElement nsSVGClipPathElementBase;
typedef mozilla::dom::SVGTransformableElement nsSVGClipPathElementBase;
class nsSVGClipPathElement : public nsSVGClipPathElementBase,
public nsIDOMSVGClipPathElement,
@ -34,6 +34,8 @@ public:
NS_FORWARD_NSIDOMNODE_TO_NSINODE
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGClipPathElementBase::)
NS_FORWARD_NSIDOMSVGLOCATABLE(mozilla::dom::SVGLocatableElement::)
NS_FORWARD_NSIDOMSVGTRANSFORMABLE(mozilla::dom::SVGTransformableElement::)
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;