Bug 265894 - Part 3. Move preserveAspectRatio-overriding stuff back to SVGSVGElement.
MozReview-Commit-ID: 174dBvrzfsj
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -131,17 +131,18 @@ NS_INTERFACE_TABLE_TAIL_INHERITING(SVGSV
//----------------------------------------------------------------------
// Implementation
SVGSVGElement::SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser)
: SVGSVGElementBase(aNodeInfo),
mStartAnimationOnBindToTree(aFromParser == NOT_FROM_PARSER ||
aFromParser == FROM_PARSER_FRAGMENT ||
- aFromParser == FROM_PARSER_XSLT)
+ aFromParser == FROM_PARSER_XSLT),
+ mImageNeedsTransformInvalidation(false)
{
}
SVGSVGElement::~SVGSVGElement()
{
}
//----------------------------------------------------------------------
@@ -638,10 +639,127 @@ SVGSVGElement::HasPreserveAspectRatio()
nsSVGElement::EnumAttributesInfo
SVGSVGElement::GetEnumInfo()
{
return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
ArrayLength(sEnumInfo));
}
+void
+SVGSVGElement::
+ SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR)
+{
+#ifdef DEBUG
+ MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
+ "should only override preserveAspectRatio in images");
+#endif
+
+ bool hasViewBoxRect = HasViewBoxRect();
+ if (!hasViewBoxRect && ShouldSynthesizeViewBox()) {
+ // My non-<svg:image> clients will have been painting me with a synthesized
+ // viewBox, but my <svg:image> client that's about to paint me now does NOT
+ // want that. Need to tell ourselves to flush our transform.
+ mImageNeedsTransformInvalidation = true;
+ }
+
+ if (!hasViewBoxRect) {
+ return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
+ }
+
+ if (SetPreserveAspectRatioProperty(aPAR)) {
+ mImageNeedsTransformInvalidation = true;
+ }
+}
+
+void
+SVGSVGElement::ClearImageOverridePreserveAspectRatio()
+{
+#ifdef DEBUG
+ MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
+ "should only override image preserveAspectRatio in images");
+#endif
+
+ if (!HasViewBoxRect() && ShouldSynthesizeViewBox()) {
+ // My non-<svg:image> clients will want to paint me with a synthesized
+ // viewBox, but my <svg:image> client that just painted me did NOT
+ // use that. Need to tell ourselves to flush our transform.
+ mImageNeedsTransformInvalidation = true;
+ }
+
+ if (ClearPreserveAspectRatioProperty()) {
+ mImageNeedsTransformInvalidation = true;
+ }
+}
+
+bool
+SVGSVGElement::SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR)
+{
+ SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR);
+ nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio,
+ pAROverridePtr,
+ nsINode::DeleteProperty<SVGPreserveAspectRatio>,
+ true);
+ MOZ_ASSERT(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
+ "Setting override value when it's already set...?");
+
+ if (MOZ_UNLIKELY(NS_FAILED(rv))) {
+ // property-insertion failed (e.g. OOM in property-table code)
+ delete pAROverridePtr;
+ return false;
+ }
+ return true;
+}
+
+const SVGPreserveAspectRatio*
+SVGSVGElement::GetPreserveAspectRatioProperty() const
+{
+ void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio);
+ if (valPtr) {
+ return static_cast<SVGPreserveAspectRatio*>(valPtr);
+ }
+ return nullptr;
+}
+
+bool
+SVGSVGElement::ClearPreserveAspectRatioProperty()
+{
+ void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio);
+ delete static_cast<SVGPreserveAspectRatio*>(valPtr);
+ return valPtr;
+}
+
+
+SVGPreserveAspectRatio
+SVGSVGElement::GetPreserveAspectRatioWithOverride() const
+{
+ nsIDocument* doc = GetUncomposedDoc();
+ if (doc && doc->IsBeingUsedAsImage()) {
+ const SVGPreserveAspectRatio *pAROverridePtr = GetPreserveAspectRatioProperty();
+ if (pAROverridePtr) {
+ return *pAROverridePtr;
+ }
+ }
+
+ SVGViewElement* viewElement = GetCurrentViewElement();
+
+ // This check is equivalent to "!HasViewBoxRect() && ShouldSynthesizeViewBox()".
+ // We're just holding onto the viewElement that HasViewBoxRect() would look up,
+ // so that we don't have to look it up again later.
+ if (!((viewElement && viewElement->mViewBox.HasRect()) ||
+ (mSVGView && mSVGView->mViewBox.HasRect()) ||
+ mViewBox.HasRect()) &&
+ ShouldSynthesizeViewBox()) {
+ // If we're synthesizing a viewBox, use preserveAspectRatio="none";
+ return SVGPreserveAspectRatio(SVG_PRESERVEASPECTRATIO_NONE, SVG_MEETORSLICE_SLICE);
+ }
+
+ if (viewElement && viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
+ return viewElement->mPreserveAspectRatio.GetAnimValue();
+ }
+ if (mSVGView && mSVGView->mPreserveAspectRatio.IsExplicitlySet()) {
+ return mSVGView->mPreserveAspectRatio.GetAnimValue();
+ }
+ return mPreserveAspectRatio.GetAnimValue();
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -58,16 +58,17 @@ private:
typedef SVGViewportElement SVGSVGElementBase;
class SVGSVGElement final : public SVGSVGElementBase
{
friend class ::nsSVGOuterSVGFrame;
friend class mozilla::SVGFragmentIdentifier;
friend class mozilla::AutoSVGViewHandler;
+ friend class mozilla::AutoPreserveAspectRatioOverride;
protected:
SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser);
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
friend nsresult (::NS_NewSVGSVGElement(nsIContent **aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
@@ -177,16 +178,19 @@ public:
}
void SetViewportSize(const svgFloatSize& aSize) {
mViewportWidth = aSize.width;
mViewportHeight = aSize.height;
}
private:
+ // SVGViewportElement methods:
+
+ virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const override;
// implementation helpers:
/*
* While binding to the tree we need to determine if we will be the outermost
* <svg> element _before_ the children are bound (as they want to know what
* timed document root to register with) and therefore _before_ our parent is
* set (both actions are performed by Element::BindToTree) so we
@@ -200,31 +204,45 @@ private:
// invalidate viewbox -> viewport xform & inform frames
void InvalidateTransformNotifyFrame();
// Returns true if we have at least one of the following:
// - a (valid or invalid) value for the preserveAspectRatio attribute
// - a SMIL-animated value for the preserveAspectRatio attribute
bool HasPreserveAspectRatio();
+ // Methods for <image> elements to override my "PreserveAspectRatio" value.
+ // These are private so that only our friends
+ // (AutoPreserveAspectRatioOverride in particular) have access.
+ void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
+ void ClearImageOverridePreserveAspectRatio();
+
+ // Set/Clear properties to hold old version of preserveAspectRatio
+ // when it's being overridden by an <image> element that we are inside of.
+ bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR);
+ const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
+ bool ClearPreserveAspectRatioProperty();
+
virtual EnumAttributesInfo GetEnumInfo() override;
nsSVGEnum mEnumAttributes[1];
static nsSVGEnumMapping sZoomAndPanMap[];
static EnumInfo sEnumInfo[1];
// The time container for animations within this SVG document fragment. Set
// for all outermost <svg> elements (not nested <svg> elements).
nsAutoPtr<nsSMILTimeContainer> mTimedDocumentRoot;
// For outermost <svg> elements created from parsing, animation is started by
// the onload event in accordance with the SVG spec, but for <svg> elements
// created by script or promoted from inner <svg> to outermost <svg> we need
// to manually kick off animation when they are bound to the tree.
bool mStartAnimationOnBindToTree;
+
+ bool mImageNeedsTransformInvalidation;
};
} // namespace dom
class MOZ_RAII AutoSVGTimeSetRestore
{
public:
AutoSVGTimeSetRestore(dom::SVGSVGElement* aRootElem,
@@ -243,11 +261,47 @@ public:
}
private:
const RefPtr<dom::SVGSVGElement> mRootElem;
const float mOriginalTime;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
+class MOZ_RAII AutoPreserveAspectRatioOverride
+{
+public:
+ AutoPreserveAspectRatioOverride(const Maybe<SVGImageContext>& aSVGContext,
+ dom::SVGSVGElement* aRootElem
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mRootElem(aRootElem)
+ , mDidOverride(false)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ MOZ_ASSERT(mRootElem, "No SVG/Symbol node to manage?");
+
+ if (aSVGContext.isSome() &&
+ aSVGContext->GetPreserveAspectRatio().isSome()) {
+ // Override preserveAspectRatio in our helper document.
+ // XXXdholbert We should technically be overriding the helper doc's clip
+ // and overflow properties here, too. See bug 272288 comment 36.
+ mRootElem->SetImageOverridePreserveAspectRatio(
+ *aSVGContext->GetPreserveAspectRatio());
+ mDidOverride = true;
+ }
+ }
+
+ ~AutoPreserveAspectRatioOverride()
+ {
+ if (mDidOverride) {
+ mRootElem->ClearImageOverridePreserveAspectRatio();
+ }
+ }
+
+private:
+ const RefPtr<dom::SVGSVGElement> mRootElem;
+ bool mDidOverride;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
} // namespace mozilla
#endif // SVGSVGElement_h
--- a/dom/svg/SVGViewElement.h
+++ b/dom/svg/SVGViewElement.h
@@ -29,16 +29,17 @@ class SVGFragmentIdentifier;
namespace dom {
class SVGViewportElement;
class SVGViewElement : public SVGViewElementBase
{
protected:
friend class mozilla::SVGFragmentIdentifier;
+ friend class SVGSVGElement;
friend class SVGViewportElement;
friend class ::nsSVGOuterSVGFrame;
explicit SVGViewElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
friend nsresult (::NS_NewSVGViewElement(nsIContent **aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
public:
--- a/dom/svg/SVGViewportElement.cpp
+++ b/dom/svg/SVGViewportElement.cpp
@@ -59,17 +59,16 @@ SVGView::SVGView()
SVGViewportElement::SVGViewportElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: SVGGraphicsElement(aNodeInfo),
mViewportWidth(0),
mViewportHeight(0),
mCurrentTranslate(0.0f, 0.0f),
mCurrentScale(1.0f),
mPreviousTranslate(0.0f, 0.0f),
mPreviousScale(1.0f),
- mImageNeedsTransformInvalidation(false),
mHasChildrenOnlyTransform(false)
{
}
SVGViewportElement::~SVGViewportElement()
{
}
@@ -386,100 +385,16 @@ SVGViewportElement::HasViewBoxRect() con
bool
SVGViewportElement::ShouldSynthesizeViewBox() const
{
MOZ_ASSERT(!HasViewBoxRect(), "Should only be called if we lack a viewBox");
return IsRoot() && OwnerDoc()->IsBeingUsedAsImage();
}
-bool
-SVGViewportElement::SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR)
-{
- SVGPreserveAspectRatio* pAROverridePtr = new SVGPreserveAspectRatio(aPAR);
- nsresult rv = SetProperty(nsGkAtoms::overridePreserveAspectRatio,
- pAROverridePtr,
- nsINode::DeleteProperty<SVGPreserveAspectRatio>,
- true);
- MOZ_ASSERT(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
- "Setting override value when it's already set...?");
-
- if (MOZ_UNLIKELY(NS_FAILED(rv))) {
- // property-insertion failed (e.g. OOM in property-table code)
- delete pAROverridePtr;
- return false;
- }
- return true;
-}
-
-const SVGPreserveAspectRatio*
-SVGViewportElement::GetPreserveAspectRatioProperty() const
-{
- void* valPtr = GetProperty(nsGkAtoms::overridePreserveAspectRatio);
- if (valPtr) {
- return static_cast<SVGPreserveAspectRatio*>(valPtr);
- }
- return nullptr;
-}
-
-bool
-SVGViewportElement::ClearPreserveAspectRatioProperty()
-{
- void* valPtr = UnsetProperty(nsGkAtoms::overridePreserveAspectRatio);
- delete static_cast<SVGPreserveAspectRatio*>(valPtr);
- return valPtr;
-}
-
-void
-SVGViewportElement::
- SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR)
-{
-#ifdef DEBUG
- MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
- "should only override preserveAspectRatio in images");
-#endif
-
- bool hasViewBoxRect = HasViewBoxRect();
- if (!hasViewBoxRect && ShouldSynthesizeViewBox()) {
- // My non-<svg:image> clients will have been painting me with a synthesized
- // viewBox, but my <svg:image> client that's about to paint me now does NOT
- // want that. Need to tell ourselves to flush our transform.
- mImageNeedsTransformInvalidation = true;
- }
-
- if (!hasViewBoxRect) {
- return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
- }
-
- if (SetPreserveAspectRatioProperty(aPAR)) {
- mImageNeedsTransformInvalidation = true;
- }
-}
-
-void
-SVGViewportElement::ClearImageOverridePreserveAspectRatio()
-{
-#ifdef DEBUG
- MOZ_ASSERT(OwnerDoc()->IsBeingUsedAsImage(),
- "should only override image preserveAspectRatio in images");
-#endif
-
- if (!HasViewBoxRect() && ShouldSynthesizeViewBox()) {
- // My non-<svg:image> clients will want to paint me with a synthesized
- // viewBox, but my <svg:image> client that just painted me did NOT
- // use that. Need to tell ourselves to flush our transform.
- mImageNeedsTransformInvalidation = true;
- }
-
- if (ClearPreserveAspectRatioProperty()) {
- mImageNeedsTransformInvalidation = true;
- }
-}
-
-
//----------------------------------------------------------------------
// implementation helpers
SVGViewElement*
SVGViewportElement::GetCurrentViewElement() const
{
if (mCurrentViewID) {
//XXXsmaug It is unclear how this should work in case we're in Shadow DOM.
@@ -521,49 +436,16 @@ SVGViewportElement::GetViewBoxWithSynthe
}
// No viewBox attribute, so we shouldn't auto-scale. This is equivalent
// to having a viewBox that exactly matches our viewport size.
return nsSVGViewBoxRect(0, 0, aViewportWidth, aViewportHeight);
}
-SVGPreserveAspectRatio
-SVGViewportElement::GetPreserveAspectRatioWithOverride() const
-{
- nsIDocument* doc = GetUncomposedDoc();
- if (doc && doc->IsBeingUsedAsImage()) {
- const SVGPreserveAspectRatio *pAROverridePtr = GetPreserveAspectRatioProperty();
- if (pAROverridePtr) {
- return *pAROverridePtr;
- }
- }
-
- SVGViewElement* viewElement = GetCurrentViewElement();
-
- // This check is equivalent to "!HasViewBoxRect() && ShouldSynthesizeViewBox()".
- // We're just holding onto the viewElement that HasViewBoxRect() would look up,
- // so that we don't have to look it up again later.
- if (!((viewElement && viewElement->mViewBox.HasRect()) ||
- (mSVGView && mSVGView->mViewBox.HasRect()) ||
- mViewBox.HasRect()) &&
- ShouldSynthesizeViewBox()) {
- // If we're synthesizing a viewBox, use preserveAspectRatio="none";
- return SVGPreserveAspectRatio(SVG_PRESERVEASPECTRATIO_NONE, SVG_MEETORSLICE_SLICE);
- }
-
- if (viewElement && viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
- return viewElement->mPreserveAspectRatio.GetAnimValue();
- }
- if (mSVGView && mSVGView->mPreserveAspectRatio.IsExplicitlySet()) {
- return mSVGView->mPreserveAspectRatio.GetAnimValue();
- }
- return mPreserveAspectRatio.GetAnimValue();
-}
-
nsSVGElement::LengthAttributesInfo
SVGViewportElement::GetLengthInfo()
{
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
ArrayLength(sLengthInfo));
}
} // namespace dom
--- a/dom/svg/SVGViewportElement.h
+++ b/dom/svg/SVGViewportElement.h
@@ -56,17 +56,16 @@ public:
SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
};
class SVGViewportElement : public SVGGraphicsElement
{
friend class ::nsSVGOuterSVGFrame;
friend class ::nsSVGInnerSVGFrame;
- friend class mozilla::AutoPreserveAspectRatioOverride;
friend class mozilla::dom::SVGView;
protected:
SVGViewportElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
~SVGViewportElement();
public:
@@ -143,28 +142,16 @@ public:
already_AddRefed<SVGAnimatedRect> ViewBox();
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
virtual nsSVGViewBox* GetViewBox() override;
protected:
// implementation helpers:
- // Methods for <image> elements to override my "PreserveAspectRatio" value.
- // These are private so that only our friends
- // (AutoPreserveAspectRatioOverride in particular) have access.
- void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
- void ClearImageOverridePreserveAspectRatio();
-
- // Set/Clear properties to hold old version of preserveAspectRatio
- // when it's being overridden by an <image> element that we are inside of.
- bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR);
- const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
- bool ClearPreserveAspectRatioProperty();
-
bool IsRoot() const {
NS_ASSERTION((IsInUncomposedDoc() && !GetParent()) ==
(OwnerDoc() && (OwnerDoc()->GetRootElement() == this)),
"Can't determine if we're root");
return IsInUncomposedDoc() && !GetParent();
}
/**
@@ -179,17 +166,19 @@ protected:
}
SVGViewElement* GetCurrentViewElement() const;
/**
* Returns the explicit or default preserveAspectRatio, unless we're
* synthesizing a viewBox, in which case it returns the "none" value.
*/
- SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const;
+ virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const {
+ return mPreserveAspectRatio.GetAnimValue();
+ }
/**
* Returns the explicit viewBox rect, if specified, or else a synthesized
* viewBox, if appropriate, or else a viewBox matching the dimensions of the
* SVG viewport.
*/
nsSVGViewBoxRect GetViewBoxWithSynthesis(
float aViewportWidth, float aViewportHeight) const;
@@ -224,53 +213,16 @@ protected:
// zoom and pan
// IMPORTANT: see the comment in RecordCurrentScaleTranslate before writing
// code to change any of these!
SVGPoint mCurrentTranslate;
float mCurrentScale;
SVGPoint mPreviousTranslate;
float mPreviousScale;
- bool mImageNeedsTransformInvalidation;
bool mHasChildrenOnlyTransform;
};
} // namespace dom
-class MOZ_RAII AutoPreserveAspectRatioOverride
-{
-public:
- AutoPreserveAspectRatioOverride(const Maybe<SVGImageContext>& aSVGContext,
- dom::SVGViewportElement* aRootElem
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mRootElem(aRootElem)
- , mDidOverride(false)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- MOZ_ASSERT(mRootElem, "No SVG/Symbol node to manage?");
-
- if (aSVGContext.isSome() &&
- aSVGContext->GetPreserveAspectRatio().isSome()) {
- // Override preserveAspectRatio in our helper document.
- // XXXdholbert We should technically be overriding the helper doc's clip
- // and overflow properties here, too. See bug 272288 comment 36.
- mRootElem->SetImageOverridePreserveAspectRatio(
- *aSVGContext->GetPreserveAspectRatio());
- mDidOverride = true;
- }
- }
-
- ~AutoPreserveAspectRatioOverride()
- {
- if (mDidOverride) {
- mRootElem->ClearImageOverridePreserveAspectRatio();
- }
- }
-
-private:
- const RefPtr<dom::SVGViewportElement> mRootElem;
- bool mDidOverride;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
} // namespace mozilla
#endif // SVGViewportElement_h