From b7cc93fd85f72038a52371753a09b1d40db2a293 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sat, 3 Mar 2012 09:21:09 +0000 Subject: [PATCH] Bug 730658 - use element does not display properly when animated with set. r=dholbert --- .../src/SVGAnimatedPreserveAspectRatio.cpp | 4 +- content/svg/content/src/nsSVGAngle.cpp | 4 +- content/svg/content/src/nsSVGBoolean.cpp | 3 +- .../svg/content/src/nsSVGCircleElement.cpp | 10 +++ content/svg/content/src/nsSVGElement.h | 3 + .../svg/content/src/nsSVGEllipseElement.cpp | 12 +++ content/svg/content/src/nsSVGEnum.cpp | 3 +- .../svg/content/src/nsSVGFilterElement.cpp | 9 +++ content/svg/content/src/nsSVGFilterElement.h | 3 + content/svg/content/src/nsSVGFilters.cpp | 9 +++ content/svg/content/src/nsSVGFilters.h | 3 + .../content/src/nsSVGForeignObjectElement.cpp | 9 +++ .../content/src/nsSVGForeignObjectElement.h | 1 + content/svg/content/src/nsSVGImageElement.cpp | 9 +++ content/svg/content/src/nsSVGImageElement.h | 3 + content/svg/content/src/nsSVGInteger.cpp | 3 +- content/svg/content/src/nsSVGIntegerPair.cpp | 4 +- content/svg/content/src/nsSVGLength2.cpp | 3 +- .../svg/content/src/nsSVGMarkerElement.cpp | 9 +++ content/svg/content/src/nsSVGMarkerElement.h | 3 + content/svg/content/src/nsSVGMaskElement.cpp | 9 +++ content/svg/content/src/nsSVGMaskElement.h | 3 + content/svg/content/src/nsSVGNumber2.cpp | 3 +- content/svg/content/src/nsSVGNumberPair.cpp | 4 +- content/svg/content/src/nsSVGPathElement.cpp | 6 ++ content/svg/content/src/nsSVGPathElement.h | 3 + .../svg/content/src/nsSVGPatternElement.cpp | 9 +++ content/svg/content/src/nsSVGPatternElement.h | 3 + content/svg/content/src/nsSVGRectElement.cpp | 12 +++ content/svg/content/src/nsSVGSVGElement.cpp | 20 +++++ content/svg/content/src/nsSVGSVGElement.h | 3 + content/svg/content/src/nsSVGUseElement.cpp | 73 ++++++++++--------- content/svg/content/src/nsSVGUseElement.h | 4 +- layout/reftests/svg/reftest.list | 1 + layout/reftests/svg/smil/reftest.list | 1 + layout/svg/base/src/nsSVGImageFrame.cpp | 4 +- layout/svg/base/src/nsSVGInnerSVGFrame.cpp | 14 +++- layout/svg/base/src/nsSVGUseFrame.cpp | 26 +++++-- layout/svg/base/src/nsSVGUtils.cpp | 21 ++++-- 39 files changed, 265 insertions(+), 61 deletions(-) diff --git a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp index 429de200e13..73d88b9de0c 100644 --- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp +++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp @@ -392,9 +392,9 @@ void SMILPreserveAspectRatio::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(PackPreserveAspectRatio(mVal->GetBaseValue()), - mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal = mVal->mBaseVal; + mSVGElement->DidAnimatePreserveAspectRatio(); } } diff --git a/content/svg/content/src/nsSVGAngle.cpp b/content/svg/content/src/nsSVGAngle.cpp index 68979970836..364d96661ea 100644 --- a/content/svg/content/src/nsSVGAngle.cpp +++ b/content/svg/content/src/nsSVGAngle.cpp @@ -510,8 +510,10 @@ nsSVGAngle::SMILOrient::ClearAnimValue() { if (mAngle->mIsAnimated) { mOrientType->SetAnimValue(mOrientType->GetBaseValue()); - mAngle->SetAnimValue(mAngle->mBaseVal, mAngle->mBaseValUnit, mSVGElement); mAngle->mIsAnimated = false; + mAngle->mAnimVal = mAngle->mBaseVal; + mAngle->mAnimValUnit = mAngle->mBaseValUnit; + mSVGElement->DidAnimateAngle(mAngle->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGBoolean.cpp b/content/svg/content/src/nsSVGBoolean.cpp index c31fca96e4d..1c65694c319 100644 --- a/content/svg/content/src/nsSVGBoolean.cpp +++ b/content/svg/content/src/nsSVGBoolean.cpp @@ -190,8 +190,9 @@ void nsSVGBoolean::SMILBool::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal = mVal->mBaseVal; + mSVGElement->DidAnimateBoolean(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGCircleElement.cpp b/content/svg/content/src/nsSVGCircleElement.cpp index ddb9ec62d64..e194c77d5e6 100644 --- a/content/svg/content/src/nsSVGCircleElement.cpp +++ b/content/svg/content/src/nsSVGCircleElement.cpp @@ -67,6 +67,9 @@ public: NS_FORWARD_NSIDOMELEMENT(nsSVGCircleElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGCircleElementBase::) + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + // nsSVGPathGeometryElement methods: virtual void ConstructPath(gfxContext *aCtx); @@ -143,6 +146,13 @@ NS_IMETHODIMP nsSVGCircleElement::GetR(nsIDOMSVGAnimatedLength * *aR) //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGCircleElement::HasValidDimensions() const +{ + return mLengthAttributes[R].IsExplicitlySet() && + mLengthAttributes[R].GetAnimValInSpecifiedUnits() > 0; +} + nsSVGElement::LengthAttributesInfo nsSVGCircleElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGElement.h b/content/svg/content/src/nsSVGElement.h index afe2583d746..47e0dfdda0c 100644 --- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -194,6 +194,9 @@ public: bool NumberAttrAllowsPercentage(PRUint8 aAttrEnum) { return GetNumberInfo().mNumberInfo[aAttrEnum].mPercentagesAllowed; } + virtual bool HasValidDimensions() const { + return true; + } void SetLength(nsIAtom* aName, const nsSVGLength2 &aLength); nsAttrValue WillChangeLength(PRUint8 aAttrEnum); diff --git a/content/svg/content/src/nsSVGEllipseElement.cpp b/content/svg/content/src/nsSVGEllipseElement.cpp index 5183018da93..8bbabaaa011 100644 --- a/content/svg/content/src/nsSVGEllipseElement.cpp +++ b/content/svg/content/src/nsSVGEllipseElement.cpp @@ -68,6 +68,9 @@ public: NS_FORWARD_NSIDOMELEMENT(nsSVGEllipseElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGEllipseElementBase::) + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + // nsSVGPathGeometryElement methods: virtual void ConstructPath(gfxContext *aCtx); @@ -151,6 +154,15 @@ NS_IMETHODIMP nsSVGEllipseElement::GetRy(nsIDOMSVGAnimatedLength * *aRy) //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGEllipseElement::HasValidDimensions() const +{ + return mLengthAttributes[RX].IsExplicitlySet() && + mLengthAttributes[RX].GetAnimValInSpecifiedUnits() > 0 && + mLengthAttributes[RY].IsExplicitlySet() && + mLengthAttributes[RY].GetAnimValInSpecifiedUnits() > 0; +} + nsSVGElement::LengthAttributesInfo nsSVGEllipseElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGEnum.cpp b/content/svg/content/src/nsSVGEnum.cpp index 3e5e5317dc6..a97167cc194 100644 --- a/content/svg/content/src/nsSVGEnum.cpp +++ b/content/svg/content/src/nsSVGEnum.cpp @@ -200,8 +200,9 @@ void nsSVGEnum::SMILEnum::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal = mVal->mBaseVal; + mSVGElement->DidAnimateEnum(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGFilterElement.cpp b/content/svg/content/src/nsSVGFilterElement.cpp index 4c5ecff987a..fd96286554d 100644 --- a/content/svg/content/src/nsSVGFilterElement.cpp +++ b/content/svg/content/src/nsSVGFilterElement.cpp @@ -219,6 +219,15 @@ nsSVGFilterElement::Invalidate() //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGFilterElement::HasValidDimensions() const +{ + return (!mLengthAttributes[WIDTH].IsExplicitlySet() || + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[HEIGHT].IsExplicitlySet() || + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0); +} + nsSVGElement::LengthAttributesInfo nsSVGFilterElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGFilterElement.h b/content/svg/content/src/nsSVGFilterElement.h index 4d7f3018389..c761a3ca6d3 100644 --- a/content/svg/content/src/nsSVGFilterElement.h +++ b/content/svg/content/src/nsSVGFilterElement.h @@ -83,6 +83,9 @@ public: void Invalidate(); virtual nsXPCClassInfo* GetClassInfo(); + + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; protected: virtual LengthAttributesInfo GetLengthInfo(); diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp index c5d3ec86422..624be8b8da7 100644 --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -310,6 +310,15 @@ nsSVGFE::IsAttributeMapped(const nsIAtom* name) const //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGFE::HasValidDimensions() const +{ + return (!mLengthAttributes[WIDTH].IsExplicitlySet() || + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[HEIGHT].IsExplicitlySet() || + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0); +} + nsSVGElement::LengthAttributesInfo nsSVGFE::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGFilters.h b/content/svg/content/src/nsSVGFilters.h index 3f5a7b1536d..a433d89a6f6 100644 --- a/content/svg/content/src/nsSVGFilters.h +++ b/content/svg/content/src/nsSVGFilters.h @@ -158,6 +158,9 @@ public: // nsIContent interface NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; + // nsSVGElement interface + virtual bool HasValidDimensions() const; + virtual nsSVGString& GetResultImageName() = 0; // Return a list of all image names used as sources. Default is to // return no sources. diff --git a/content/svg/content/src/nsSVGForeignObjectElement.cpp b/content/svg/content/src/nsSVGForeignObjectElement.cpp index 4385a4a2830..c78b30ddf33 100644 --- a/content/svg/content/src/nsSVGForeignObjectElement.cpp +++ b/content/svg/content/src/nsSVGForeignObjectElement.cpp @@ -136,6 +136,15 @@ nsSVGForeignObjectElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix, return toUserSpace * fromUserSpace; } +/* virtual */ bool +nsSVGForeignObjectElement::HasValidDimensions() const +{ + return mLengthAttributes[WIDTH].IsExplicitlySet() && + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 && + mLengthAttributes[HEIGHT].IsExplicitlySet() && + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0; +} + //---------------------------------------------------------------------- // nsIContent methods diff --git a/content/svg/content/src/nsSVGForeignObjectElement.h b/content/svg/content/src/nsSVGForeignObjectElement.h index d9794dbeffe..c18ca6575e7 100644 --- a/content/svg/content/src/nsSVGForeignObjectElement.h +++ b/content/svg/content/src/nsSVGForeignObjectElement.h @@ -71,6 +71,7 @@ public: // nsSVGElement specializations: virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix, TransformTypes aWhich = eAllTransforms) const; + virtual bool HasValidDimensions() const; // nsIContent interface NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const; diff --git a/content/svg/content/src/nsSVGImageElement.cpp b/content/svg/content/src/nsSVGImageElement.cpp index b5582e41730..beaa47176ca 100644 --- a/content/svg/content/src/nsSVGImageElement.cpp +++ b/content/svg/content/src/nsSVGImageElement.cpp @@ -267,6 +267,15 @@ nsSVGImageElement::ConstructPath(gfxContext *aCtx) //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGImageElement::HasValidDimensions() const +{ + return mLengthAttributes[WIDTH].IsExplicitlySet() && + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 && + mLengthAttributes[HEIGHT].IsExplicitlySet() && + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0; +} + nsSVGElement::LengthAttributesInfo nsSVGImageElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGImageElement.h b/content/svg/content/src/nsSVGImageElement.h index 663c9ac2e84..8aea8028775 100644 --- a/content/svg/content/src/nsSVGImageElement.h +++ b/content/svg/content/src/nsSVGImageElement.h @@ -90,6 +90,9 @@ public: // nsSVGPathGeometryElement methods: virtual void ConstructPath(gfxContext *aCtx); + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; nsresult CopyInnerTo(nsGenericElement* aDest) const; diff --git a/content/svg/content/src/nsSVGInteger.cpp b/content/svg/content/src/nsSVGInteger.cpp index 8a1f06dbb0d..c02165462c2 100644 --- a/content/svg/content/src/nsSVGInteger.cpp +++ b/content/svg/content/src/nsSVGInteger.cpp @@ -185,8 +185,9 @@ void nsSVGInteger::SMILInteger::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal = mVal->mBaseVal; + mSVGElement->DidAnimateInteger(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGIntegerPair.cpp b/content/svg/content/src/nsSVGIntegerPair.cpp index dc35ada0e4e..f9417c61d0a 100644 --- a/content/svg/content/src/nsSVGIntegerPair.cpp +++ b/content/svg/content/src/nsSVGIntegerPair.cpp @@ -241,8 +241,10 @@ void nsSVGIntegerPair::SMILIntegerPair::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal[0] = mVal->mBaseVal[0]; + mVal->mAnimVal[1] = mVal->mBaseVal[1]; + mSVGElement->DidAnimateIntegerPair(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGLength2.cpp b/content/svg/content/src/nsSVGLength2.cpp index 40301209dc0..da3c15465cc 100644 --- a/content/svg/content/src/nsSVGLength2.cpp +++ b/content/svg/content/src/nsSVGLength2.cpp @@ -570,8 +570,9 @@ void nsSVGLength2::SMILLength::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValueInSpecifiedUnits(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal = mVal->mBaseVal; + mSVGElement->DidAnimateLength(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGMarkerElement.cpp b/content/svg/content/src/nsSVGMarkerElement.cpp index 91c6e2950fc..e82830f7625 100644 --- a/content/svg/content/src/nsSVGMarkerElement.cpp +++ b/content/svg/content/src/nsSVGMarkerElement.cpp @@ -306,6 +306,15 @@ nsSVGMarkerElement::SetParentCoordCtxProvider(nsSVGSVGElement *aContext) mViewBoxToViewportTransform = nsnull; } +/* virtual */ bool +nsSVGMarkerElement::HasValidDimensions() const +{ + return (!mLengthAttributes[MARKERWIDTH].IsExplicitlySet() || + mLengthAttributes[MARKERWIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[MARKERHEIGHT].IsExplicitlySet() || + mLengthAttributes[MARKERHEIGHT].GetAnimValInSpecifiedUnits() > 0); +} + nsSVGElement::LengthAttributesInfo nsSVGMarkerElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGMarkerElement.h b/content/svg/content/src/nsSVGMarkerElement.h index 8f53d281c0e..bbb930246df 100644 --- a/content/svg/content/src/nsSVGMarkerElement.h +++ b/content/svg/content/src/nsSVGMarkerElement.h @@ -133,6 +133,9 @@ public: virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, bool aNotify); + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + // public helpers gfxMatrix GetMarkerTransform(float aStrokeWidth, float aX, float aY, float aAutoAngle); diff --git a/content/svg/content/src/nsSVGMaskElement.cpp b/content/svg/content/src/nsSVGMaskElement.cpp index 9ab4ba223e0..83a7ff760cf 100644 --- a/content/svg/content/src/nsSVGMaskElement.cpp +++ b/content/svg/content/src/nsSVGMaskElement.cpp @@ -136,6 +136,15 @@ NS_IMETHODIMP nsSVGMaskElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGMaskElement::HasValidDimensions() const +{ + return (!mLengthAttributes[WIDTH].IsExplicitlySet() || + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[HEIGHT].IsExplicitlySet() || + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0); +} + nsSVGElement::LengthAttributesInfo nsSVGMaskElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGMaskElement.h b/content/svg/content/src/nsSVGMaskElement.h index 7e286c3b98c..a21a02db143 100644 --- a/content/svg/content/src/nsSVGMaskElement.h +++ b/content/svg/content/src/nsSVGMaskElement.h @@ -76,6 +76,9 @@ public: NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsXPCClassInfo* GetClassInfo(); + + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; protected: virtual LengthAttributesInfo GetLengthInfo(); diff --git a/content/svg/content/src/nsSVGNumber2.cpp b/content/svg/content/src/nsSVGNumber2.cpp index 9cc4d64632a..48792f60c5a 100644 --- a/content/svg/content/src/nsSVGNumber2.cpp +++ b/content/svg/content/src/nsSVGNumber2.cpp @@ -227,8 +227,9 @@ void nsSVGNumber2::SMILNumber::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal = mVal->mBaseVal; + mSVGElement->DidAnimateNumber(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGNumberPair.cpp b/content/svg/content/src/nsSVGNumberPair.cpp index 825704e0476..891c3450724 100644 --- a/content/svg/content/src/nsSVGNumberPair.cpp +++ b/content/svg/content/src/nsSVGNumberPair.cpp @@ -239,8 +239,10 @@ void nsSVGNumberPair::SMILNumberPair::ClearAnimValue() { if (mVal->mIsAnimated) { - mVal->SetAnimValue(mVal->mBaseVal, mSVGElement); mVal->mIsAnimated = false; + mVal->mAnimVal[0] = mVal->mBaseVal[0]; + mVal->mAnimVal[1] = mVal->mBaseVal[1]; + mSVGElement->DidAnimateNumberPair(mVal->mAttrEnum); } } diff --git a/content/svg/content/src/nsSVGPathElement.cpp b/content/svg/content/src/nsSVGPathElement.cpp index c43da6ebec1..be225acc672 100644 --- a/content/svg/content/src/nsSVGPathElement.cpp +++ b/content/svg/content/src/nsSVGPathElement.cpp @@ -341,6 +341,12 @@ nsSVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y, ns //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGPathElement::HasValidDimensions() const +{ + return !mD.GetAnimValue().IsEmpty(); +} + nsSVGElement::NumberAttributesInfo nsSVGPathElement::GetNumberInfo() { diff --git a/content/svg/content/src/nsSVGPathElement.h b/content/svg/content/src/nsSVGPathElement.h index 91465871fd2..5307d5e0482 100644 --- a/content/svg/content/src/nsSVGPathElement.h +++ b/content/svg/content/src/nsSVGPathElement.h @@ -76,6 +76,9 @@ public: // nsIContent interface NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const; + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + // nsSVGPathGeometryElement methods: virtual bool AttributeDefinesGeometry(const nsIAtom *aName); virtual bool IsMarkable(); diff --git a/content/svg/content/src/nsSVGPatternElement.cpp b/content/svg/content/src/nsSVGPatternElement.cpp index 658ee0de730..23267a43727 100644 --- a/content/svg/content/src/nsSVGPatternElement.cpp +++ b/content/svg/content/src/nsSVGPatternElement.cpp @@ -214,6 +214,15 @@ nsSVGPatternElement::GetAnimatedTransformList() return mPatternTransform; } +/* virtual */ bool +nsSVGPatternElement::HasValidDimensions() const +{ + return mLengthAttributes[WIDTH].IsExplicitlySet() && + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 && + mLengthAttributes[HEIGHT].IsExplicitlySet() && + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0; +} + nsSVGElement::LengthAttributesInfo nsSVGPatternElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGPatternElement.h b/content/svg/content/src/nsSVGPatternElement.h index 59fbff8a0ce..f0fe6dcf57a 100644 --- a/content/svg/content/src/nsSVGPatternElement.h +++ b/content/svg/content/src/nsSVGPatternElement.h @@ -96,6 +96,9 @@ public: virtual nsXPCClassInfo* GetClassInfo(); + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + virtual mozilla::SVGAnimatedTransformList* GetAnimatedTransformList(); virtual nsIAtom* GetTransformListAttrName() const { return nsGkAtoms::patternTransform; diff --git a/content/svg/content/src/nsSVGRectElement.cpp b/content/svg/content/src/nsSVGRectElement.cpp index 6494ef6f504..b392e562b9e 100644 --- a/content/svg/content/src/nsSVGRectElement.cpp +++ b/content/svg/content/src/nsSVGRectElement.cpp @@ -67,6 +67,9 @@ public: NS_FORWARD_NSIDOMELEMENT(nsSVGRectElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGRectElementBase::) + // nsSVGSVGElement methods: + virtual bool HasValidDimensions() const; + // nsSVGPathGeometryElement methods: virtual void ConstructPath(gfxContext *aCtx); @@ -164,6 +167,15 @@ NS_IMETHODIMP nsSVGRectElement::GetRy(nsIDOMSVGAnimatedLength * *aRy) //---------------------------------------------------------------------- // nsSVGElement methods +/* virtual */ bool +nsSVGRectElement::HasValidDimensions() const +{ + return mLengthAttributes[WIDTH].IsExplicitlySet() && + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 && + mLengthAttributes[HEIGHT].IsExplicitlySet() && + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0; +} + nsSVGElement::LengthAttributesInfo nsSVGRectElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGSVGElement.cpp b/content/svg/content/src/nsSVGSVGElement.cpp index eed270768a6..f038085a7b0 100644 --- a/content/svg/content/src/nsSVGSVGElement.cpp +++ b/content/svg/content/src/nsSVGSVGElement.cpp @@ -1189,6 +1189,16 @@ nsSVGSVGElement::GetLength(PRUint8 aCtxType) return 0; } +void +nsSVGSVGElement::SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const +{ + NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height, + "The clue is in the function name"); + + PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT; + aTarget->SetLength(aName, mLengthAttributes[index]); +} + //---------------------------------------------------------------------- // nsSVGElement methods @@ -1229,6 +1239,16 @@ nsSVGSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix, return GetViewBoxTransform() * aMatrix; } +/* virtual */ bool +nsSVGSVGElement::HasValidDimensions() const +{ + return !IsInner() || + ((!mLengthAttributes[WIDTH].IsExplicitlySet() || + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[HEIGHT].IsExplicitlySet() || + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0)); +} + nsSVGElement::LengthAttributesInfo nsSVGSVGElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGSVGElement.h b/content/svg/content/src/nsSVGSVGElement.h index 668de43e533..c4cb02cc0ac 100644 --- a/content/svg/content/src/nsSVGSVGElement.h +++ b/content/svg/content/src/nsSVGSVGElement.h @@ -188,9 +188,12 @@ public: // nsSVGElement specializations: virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix, TransformTypes aWhich = eAllTransforms) const; + virtual bool HasValidDimensions() const; // nsSVGSVGElement methods: float GetLength(PRUint8 mCtxType); + // Copy our width or height to the target + void SyncWidthOrHeight(nsIAtom* aName, nsSVGElement *aTarget) const; // public helpers: gfxMatrix GetViewBoxTransform() const; diff --git a/content/svg/content/src/nsSVGUseElement.cpp b/content/svg/content/src/nsSVGUseElement.cpp index 458b8cc6124..e34524ecba4 100644 --- a/content/svg/content/src/nsSVGUseElement.cpp +++ b/content/svg/content/src/nsSVGUseElement.cpp @@ -40,7 +40,7 @@ #include "nsIDOMSVGGElement.h" #include "nsGkAtoms.h" #include "nsIDOMDocument.h" -#include "nsIDOMSVGSVGElement.h" +#include "nsSVGSVGElement.h" #include "nsIDOMSVGSymbolElement.h" #include "nsIDocument.h" #include "nsIPresShell.h" @@ -288,10 +288,6 @@ nsSVGUseElement::CreateAnonymousContent() tag != nsGkAtoms::use) return nsnull; - // Make sure the use attributes are valid - if (!HasValidDimensions()) - return nsnull; - // circular loop detection // check 1 - check if we're a document descendent of the target @@ -299,8 +295,8 @@ nsSVGUseElement::CreateAnonymousContent() return nsnull; // check 2 - check if we're a clone, and if we already exist in the hierarchy - if (this->GetParent() && mOriginal) { - for (nsCOMPtr content = this->GetParent(); + if (GetParent() && mOriginal) { + for (nsCOMPtr content = GetParent(); content; content = content->GetParent()) { nsCOMPtr useElement = do_QueryInterface(content); @@ -407,43 +403,43 @@ nsSVGUseElement::DestroyAnonymousContent() //---------------------------------------------------------------------- // implementation helpers -bool nsSVGUseElement::HasValidDimensions() -{ - nsSVGSVGElement *ctx = GetCtx(); - - return (!mLengthAttributes[WIDTH].IsExplicitlySet() || - mLengthAttributes[WIDTH].GetAnimValue(ctx) > 0) && - (!mLengthAttributes[HEIGHT].IsExplicitlySet() || - mLengthAttributes[HEIGHT].GetAnimValue(ctx) > 0); -} - void -nsSVGUseElement::SyncWidthHeight(nsIAtom* aName) +nsSVGUseElement::SyncWidthOrHeight(nsIAtom* aName) { NS_ASSERTION(aName == nsGkAtoms::width || aName == nsGkAtoms::height, "The clue is in the function name"); - if (HasValidDimensions() == !mClone) { - TriggerReclone(); + if (!mClone) { return; } - if (mClone) { - nsCOMPtr symbol = do_QueryInterface(mClone); - nsCOMPtr svg = do_QueryInterface(mClone); + nsCOMPtr symbol = do_QueryInterface(mClone); + nsCOMPtr svg = do_QueryInterface(mClone); - if (symbol || svg) { - PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT; - if (mLengthAttributes[index].IsExplicitlySet()) { - static_cast(mClone.get())-> - SetLength(aName, mLengthAttributes[index]); - } else { - // Our width/height attribute is now no longer explicitly set, so we - // need to revert the clone's width/height to the width/height of the - // content that's being cloned. - TriggerReclone(); - } + if (symbol || svg) { + nsSVGElement *target = static_cast(mClone.get()); + PRUint32 index = *sLengthInfo[WIDTH].mName == aName ? WIDTH : HEIGHT; + + if (mLengthAttributes[index].IsExplicitlySet()) { + target->SetLength(aName, mLengthAttributes[index]); + return; } + if (svg) { + // Our width/height attribute is now no longer explicitly set, so we + // need to revert the clone's width/height to the width/height of the + // content that's being cloned. + nsSVGSVGElement* svgElement = + static_cast(mSource.get()); + svgElement->SyncWidthOrHeight(aName, target); + return; + } + // Our width/height attribute is now no longer explicitly set, so we + // need to set the value to 100% + nsSVGLength2 length; + length.Init(nsSVGUtils::XY, 0xff, + 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + target->SetLength(aName, length); + return; } } @@ -511,6 +507,15 @@ nsSVGUseElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix, return toUserSpace * fromUserSpace; } +/* virtual */ bool +nsSVGUseElement::HasValidDimensions() const +{ + return (!mLengthAttributes[WIDTH].IsExplicitlySet() || + mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[HEIGHT].IsExplicitlySet() || + mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0); +} + nsSVGElement::LengthAttributesInfo nsSVGUseElement::GetLengthInfo() { diff --git a/content/svg/content/src/nsSVGUseElement.h b/content/svg/content/src/nsSVGUseElement.h index f9f4d43df13..dcc05e7d041 100644 --- a/content/svg/content/src/nsSVGUseElement.h +++ b/content/svg/content/src/nsSVGUseElement.h @@ -105,6 +105,7 @@ public: // nsSVGElement specializations: virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix, TransformTypes aWhich = eAllTransforms) const; + virtual bool HasValidDimensions() const; // nsIContent interface virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; @@ -130,8 +131,7 @@ protected: virtual LengthAttributesInfo GetLengthInfo(); virtual StringAttributesInfo GetStringInfo(); - bool HasValidDimensions(); - void SyncWidthHeight(nsIAtom *aName); + void SyncWidthOrHeight(nsIAtom *aName); void LookupHref(); void TriggerReclone(); void UnlinkSource(); diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index e33ce513a8a..867d7c09ca8 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -215,6 +215,7 @@ random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-02.svg objectBoundin == rect-01.svg pass.svg == rect-02.svg pass.svg == rect-03.svg pass.svg +== rect-04.svg pass.svg == rect-with-rx-and-ry-01.svg pass.svg == rect-with-rx-or-ry-01.svg rect-with-rx-or-ry-01-ref.svg == rootElement-null-01.svg pass.svg diff --git a/layout/reftests/svg/smil/reftest.list b/layout/reftests/svg/smil/reftest.list index b2896e4f364..a029ca4d4b8 100644 --- a/layout/reftests/svg/smil/reftest.list +++ b/layout/reftests/svg/smil/reftest.list @@ -95,6 +95,7 @@ fails == anim-fillcolor-1.svg anim-standard-ref.svg # bug 436296 == anim-length-reset-01.svg lime.svg == anim-nonpixel-length-reset-01.svg lime.svg == anim-use-length-01.svg lime.svg +== anim-use-length-02.svg lime.svg # animate some attributes: == anim-feComponentTransfer-01.svg lime.svg diff --git a/layout/svg/base/src/nsSVGImageFrame.cpp b/layout/svg/base/src/nsSVGImageFrame.cpp index 42e4ed2bc33..b153b5f0559 100644 --- a/layout/svg/base/src/nsSVGImageFrame.cpp +++ b/layout/svg/base/src/nsSVGImageFrame.cpp @@ -321,8 +321,8 @@ nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext, float x, y, width, height; nsSVGImageElement *imgElem = static_cast(mContent); imgElem->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); - if (width <= 0 || height <= 0) - return NS_OK; + NS_ASSERTION(width > 0 && height > 0, + "Should only be painting things with valid width/height"); if (!mImageContainer) { nsCOMPtr currentRequest; diff --git a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp index 7ce03e7b3b0..1bc90d1104d 100644 --- a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp @@ -164,14 +164,24 @@ nsSVGInnerSVGFrame::AttributeChanged(PRInt32 aNameSpaceID, if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) { - if (static_cast(mContent)->mViewBox.IsValid()) { + nsSVGSVGElement* svg = static_cast(mContent); + if (svg->mViewBox.IsValid()) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); } else { - nsSVGUtils::NotifyChildrenOfSVGChange(this, COORD_CONTEXT_CHANGED); + + PRUint32 flags = COORD_CONTEXT_CHANGED; + + if (mCanvasTM && mCanvasTM->IsSingular()) { + + mCanvasTM = nsnull; + + flags |= TRANSFORM_CHANGED; + } + nsSVGUtils::NotifyChildrenOfSVGChange(this, flags); } } else if (aAttribute == nsGkAtoms::transform || diff --git a/layout/svg/base/src/nsSVGUseFrame.cpp b/layout/svg/base/src/nsSVGUseFrame.cpp index 698aedd43ee..6554632c2dd 100644 --- a/layout/svg/base/src/nsSVGUseFrame.cpp +++ b/layout/svg/base/src/nsSVGUseFrame.cpp @@ -51,7 +51,10 @@ class nsSVGUseFrame : public nsSVGUseFrameBase, NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: - nsSVGUseFrame(nsStyleContext* aContext) : nsSVGUseFrameBase(aContext) {} + nsSVGUseFrame(nsStyleContext* aContext) : + nsSVGUseFrameBase(aContext), + mHasValidDimensions(true) + {} public: NS_DECL_QUERYFRAME @@ -59,11 +62,9 @@ public: // nsIFrame interface: -#ifdef DEBUG NS_IMETHOD Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow); -#endif NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, @@ -94,6 +95,9 @@ public: virtual nsresult CreateAnonymousContent(nsTArray& aElements); virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, PRUint32 aFilter); + +private: + bool mHasValidDimensions; }; //---------------------------------------------------------------------- @@ -123,18 +127,21 @@ NS_QUERYFRAME_TAIL_INHERITING(nsSVGUseFrameBase) //---------------------------------------------------------------------- // nsIFrame methods: -#ifdef DEBUG NS_IMETHODIMP nsSVGUseFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) { +#ifdef DEBUG nsCOMPtr use = do_QueryInterface(aContent); NS_ASSERTION(use, "Content is not an SVG use!"); +#endif /* DEBUG */ + + mHasValidDimensions = + static_cast(aContent)->HasValidDimensions(); return nsSVGUseFrameBase::Init(aContent, aParent, aPrevInFlow); } -#endif /* DEBUG */ NS_IMETHODIMP nsSVGUseFrame::AttributeChanged(PRInt32 aNameSpaceID, @@ -150,7 +157,14 @@ nsSVGUseFrame::AttributeChanged(PRInt32 aNameSpaceID, nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); } else if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) { - static_cast(mContent)->SyncWidthHeight(aAttribute); + static_cast(mContent)->SyncWidthOrHeight(aAttribute); + + if (mHasValidDimensions != + static_cast(mContent)->HasValidDimensions()) { + + mHasValidDimensions = !mHasValidDimensions; + nsSVGUtils::UpdateGraphic(this); + } } } else if (aNameSpaceID == kNameSpaceID_XLink && aAttribute == nsGkAtoms::href) { diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index 6358215f46f..984cb86b18d 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -1051,6 +1051,12 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, if (opacity == 0.0f) return; + const nsIContent* content = aFrame->GetContent(); + if (content->IsSVG() && + !static_cast(content)->HasValidDimensions()) { + return; + } + /* Properties are added lazily and may have been removed by a restyle, so make sure all applicable ones are set again. */ @@ -1209,9 +1215,9 @@ nsSVGUtils::HitTestChildren(nsIFrame *aFrame, const nsPoint &aPoint) current = current->GetPrevSibling()) { nsISVGChildFrame* SVGFrame = do_QueryFrame(current); if (SVGFrame) { - result = SVGFrame->GetFrameForPoint(aPoint); - if (result) - break; + result = SVGFrame->GetFrameForPoint(aPoint); + if (result) + break; } } @@ -1443,13 +1449,18 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, PRUint32 aFlags) } svg = do_QueryFrame(aFrame); } + nsIContent* content = aFrame->GetContent(); + if (content->IsSVG() && + !static_cast(content)->HasValidDimensions()) { + return bbox; + } gfxMatrix matrix; if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) { // The spec says getBBox "Returns the tight bounding box in *current user // space*". So we should really be doing this for all elements, but that // needs investigation to check that we won't break too much content. - NS_ABORT_IF_FALSE(aFrame->GetContent()->IsSVG(), "bad cast"); - nsSVGElement *element = static_cast(aFrame->GetContent()); + NS_ABORT_IF_FALSE(content->IsSVG(), "bad cast"); + nsSVGElement *element = static_cast(content); matrix = element->PrependLocalTransformsTo(matrix, nsSVGElement::eChildToUserSpace); }