diff --git a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp index 5a947c44039..4e6919c40f5 100644 --- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp +++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp @@ -237,6 +237,7 @@ SVGAnimatedPreserveAspectRatio::SetBaseValueString( } mBaseVal = val; + mIsBaseSet = PR_TRUE; if (!mIsAnimated) { mAnimVal = mBaseVal; } @@ -281,6 +282,7 @@ SVGAnimatedPreserveAspectRatio::SetBaseAlign(PRUint16 aAlign, { nsresult rv = mBaseVal.SetAlign(aAlign); NS_ENSURE_SUCCESS(rv, rv); + mIsBaseSet = PR_TRUE; mAnimVal.mAlign = mBaseVal.mAlign; aSVGElement->DidChangePreserveAspectRatio(PR_TRUE); @@ -299,6 +301,7 @@ SVGAnimatedPreserveAspectRatio::SetBaseMeetOrSlice(PRUint16 aMeetOrSlice, { nsresult rv = mBaseVal.SetMeetOrSlice(aMeetOrSlice); NS_ENSURE_SUCCESS(rv, rv); + mIsBaseSet = PR_TRUE; mAnimVal.mMeetOrSlice = mBaseVal.mMeetOrSlice; aSVGElement->DidChangePreserveAspectRatio(PR_TRUE); diff --git a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h index 0d98f820361..f129e79d46c 100644 --- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h +++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.h @@ -100,6 +100,7 @@ public: mBaseVal.mDefer = PR_FALSE; mAnimVal = mBaseVal; mIsAnimated = PR_FALSE; + mIsBaseSet = PR_FALSE; } nsresult SetBaseValueString(const nsAString& aValue, @@ -117,6 +118,8 @@ public: { return mAnimVal; } PRBool IsAnimated() const { return mIsAnimated; } + PRBool IsExplicitlySet() const + { return mIsAnimated || mIsBaseSet; } nsresult ToDOMAnimatedPreserveAspectRatio( nsIDOMSVGAnimatedPreserveAspectRatio **aResult, @@ -131,6 +134,7 @@ private: SVGPreserveAspectRatio mAnimVal; SVGPreserveAspectRatio mBaseVal; PRPackedBool mIsAnimated; + PRPackedBool mIsBaseSet; nsresult ToDOMBaseVal(nsIDOMSVGPreserveAspectRatio **aResult, nsSVGElement* aSVGElement); diff --git a/content/svg/content/src/nsSVGAnimatedTransformList.cpp b/content/svg/content/src/nsSVGAnimatedTransformList.cpp index 4cfa10bac6b..17976ca2319 100644 --- a/content/svg/content/src/nsSVGAnimatedTransformList.cpp +++ b/content/svg/content/src/nsSVGAnimatedTransformList.cpp @@ -136,6 +136,31 @@ nsSVGAnimatedTransformList::DidModifySVGObservable (nsISVGValue* observable, return NS_OK; } +//---------------------------------------------------------------------- +// Misc nsSVGAnimatedTransformList methods + +PRBool +nsSVGAnimatedTransformList::IsExplicitlySet() const +{ + // XXX Dummy implementation until bug 602759 is fixed. + // Like other methods of this name, we need to know when a transform value has + // been explicitly set (either by markup, a DOM call, or animation). + // Given our current implementation, we can say that's the case so long as + // mBaseVal has something in it or mAnimVal exists. + // It's not quite right because, for example, if we have transform="" we + // should probably behave as if the value is set, but for now it will do until + // bug 602759 is fixed. + if (mAnimVal) + return PR_TRUE; + + if (!mBaseVal) + return PR_FALSE; + + PRUint32 numItems = 0; + nsIDOMSVGTransformList *list = mBaseVal.get(); + list->GetNumberOfItems(&numItems); + return numItems > 0; +} //////////////////////////////////////////////////////////////////////// // Exported creation functions: diff --git a/content/svg/content/src/nsSVGAnimatedTransformList.h b/content/svg/content/src/nsSVGAnimatedTransformList.h index dac8e6d1c03..94ab20e97db 100644 --- a/content/svg/content/src/nsSVGAnimatedTransformList.h +++ b/content/svg/content/src/nsSVGAnimatedTransformList.h @@ -80,6 +80,8 @@ public: // nsISupportsWeakReference // implementation inherited from nsSupportsWeakReference + PRBool IsExplicitlySet() const; + protected: friend class nsSVGTransformSMILAttr; diff --git a/content/svg/content/src/nsSVGEnum.cpp b/content/svg/content/src/nsSVGEnum.cpp index 8abfe2a3d3b..dcc49a62e85 100644 --- a/content/svg/content/src/nsSVGEnum.cpp +++ b/content/svg/content/src/nsSVGEnum.cpp @@ -79,6 +79,7 @@ nsSVGEnum::SetBaseValueString(const nsAString& aValue, while (mapping && mapping->mKey) { if (valAtom == *(mapping->mKey)) { + mIsBaseSet = PR_TRUE; if (mBaseVal != mapping->mVal) { mBaseVal = mapping->mVal; if (!mIsAnimated) { @@ -127,6 +128,7 @@ nsSVGEnum::SetBaseValue(PRUint16 aValue, while (mapping && mapping->mKey) { if (mapping->mVal == aValue) { + mIsBaseSet = PR_TRUE; if (mBaseVal != PRUint8(aValue)) { mBaseVal = PRUint8(aValue); if (!mIsAnimated) { diff --git a/content/svg/content/src/nsSVGEnum.h b/content/svg/content/src/nsSVGEnum.h index 0926a4d8ce6..8c782de425d 100644 --- a/content/svg/content/src/nsSVGEnum.h +++ b/content/svg/content/src/nsSVGEnum.h @@ -55,6 +55,7 @@ public: mAnimVal = mBaseVal = PRUint8(aValue); mAttrEnum = aAttrEnum; mIsAnimated = PR_FALSE; + mIsBaseSet = PR_FALSE; } nsresult SetBaseValueString(const nsAString& aValue, @@ -72,6 +73,8 @@ public: void SetAnimValue(PRUint16 aValue, nsSVGElement *aSVGElement); PRUint16 GetAnimValue() const { return mAnimVal; } + PRBool IsExplicitlySet() const + { return mIsAnimated || mIsBaseSet; } nsresult ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult, nsSVGElement* aSVGElement); @@ -85,6 +88,7 @@ private: nsSVGEnumValue mBaseVal; PRUint8 mAttrEnum; // element specified tracking for attribute PRPackedBool mIsAnimated; + PRPackedBool mIsBaseSet; nsSVGEnumMapping *GetMapping(nsSVGElement *aSVGElement); diff --git a/content/svg/content/src/nsSVGLength2.h b/content/svg/content/src/nsSVGLength2.h index 2c43d10c380..c6bd8963ae3 100644 --- a/content/svg/content/src/nsSVGLength2.h +++ b/content/svg/content/src/nsSVGLength2.h @@ -97,7 +97,7 @@ public: // explicitly set by markup or a DOM call), PR_FALSE otherwise. // If this returns PR_FALSE, the animated value is still valid, that is, // useable, and represents the default base value of the attribute. - PRBool IsAnimValSet() const + PRBool IsExplicitlySet() const { return mIsAnimated || mIsBaseSet; } nsresult ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult, diff --git a/content/svg/content/src/nsSVGRectElement.cpp b/content/svg/content/src/nsSVGRectElement.cpp index 6fb3c8e94ad..42fdec36f0a 100644 --- a/content/svg/content/src/nsSVGRectElement.cpp +++ b/content/svg/content/src/nsSVGRectElement.cpp @@ -192,8 +192,8 @@ nsSVGRectElement::ConstructPath(gfxContext *aCtx) /* If either the 'rx' or the 'ry' attribute isn't set, then we have to set it to the value of the other. */ - PRBool hasRx = mLengthAttributes[RX].IsAnimValSet(); - PRBool hasRy = mLengthAttributes[RY].IsAnimValSet(); + PRBool hasRx = mLengthAttributes[RX].IsExplicitlySet(); + PRBool hasRy = mLengthAttributes[RY].IsExplicitlySet(); if (hasRx && !hasRy) ry = rx; else if (hasRy && !hasRx) diff --git a/layout/reftests/svg/smil/anim-pattern-attr-presence-01-ref.svg b/layout/reftests/svg/smil/anim-pattern-attr-presence-01-ref.svg new file mode 100644 index 00000000000..ddb0ffe4547 --- /dev/null +++ b/layout/reftests/svg/smil/anim-pattern-attr-presence-01-ref.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/anim-pattern-attr-presence-01.svg b/layout/reftests/svg/smil/anim-pattern-attr-presence-01.svg new file mode 100644 index 00000000000..b33a58fa271 --- /dev/null +++ b/layout/reftests/svg/smil/anim-pattern-attr-presence-01.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/anim-pattern-attr-presence-02-ref.svg b/layout/reftests/svg/smil/anim-pattern-attr-presence-02-ref.svg new file mode 100644 index 00000000000..cfe0027d5f1 --- /dev/null +++ b/layout/reftests/svg/smil/anim-pattern-attr-presence-02-ref.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/anim-pattern-attr-presence-02.svg b/layout/reftests/svg/smil/anim-pattern-attr-presence-02.svg new file mode 100644 index 00000000000..e0d2e35dfff --- /dev/null +++ b/layout/reftests/svg/smil/anim-pattern-attr-presence-02.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/reftest.list b/layout/reftests/svg/smil/reftest.list index 618101892a6..b2d9f3f991a 100644 --- a/layout/reftests/svg/smil/reftest.list +++ b/layout/reftests/svg/smil/reftest.list @@ -197,7 +197,11 @@ random == anim-text-x-y-dx-dy-01.svg anim-text-x-y-dx-dy-01-ref.svg # bug 579588 == anim-y-interp-5.svg anim-y-interp-5-ref.svg == anim-y-interp-6.svg anim-y-interp-6-ref.svg +# Test we don't rely on HasAttr to see if an attribute has been set == anim-rect-rxry-1.svg anim-rect-rxry-1-ref.svg +== anim-pattern-attr-presence-01.svg anim-pattern-attr-presence-01-ref.svg +fails == anim-pattern-attr-presence-02.svg anim-pattern-attr-presence-02-ref.svg +# ^ bug 621651 == api-sanity-1.svg lime.svg diff --git a/layout/svg/base/src/nsSVGPatternFrame.cpp b/layout/svg/base/src/nsSVGPatternFrame.cpp index 9bffc01fde5..f443783d638 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.cpp +++ b/layout/svg/base/src/nsSVGPatternFrame.cpp @@ -51,6 +51,7 @@ #include "nsSVGPatternElement.h" #include "nsSVGGeometryFrame.h" #include "nsSVGPatternFrame.h" +#include "nsSVGAnimatedTransformList.h" #include "gfxContext.h" #include "gfxPlatform.h" #include "gfxPattern.h" @@ -58,6 +59,27 @@ using namespace mozilla; +//---------------------------------------------------------------------- +// Helper classes + +class nsSVGPatternFrame::AutoPatternReferencer +{ +public: + AutoPatternReferencer(nsSVGPatternFrame *aFrame) + : mFrame(aFrame) + { + // Reference loops should normally be detected in advance and handled, so + // we're not expecting to encounter them here + NS_ABORT_IF_FALSE(!mFrame->mLoopFlag, "Undetected reference loop!"); + mFrame->mLoopFlag = PR_TRUE; + } + ~AutoPatternReferencer() { + mFrame->mLoopFlag = PR_FALSE; + } +private: + nsSVGPatternFrame *mFrame; +}; + //---------------------------------------------------------------------- // Implementation @@ -331,48 +353,64 @@ nsSVGPatternFrame::GetPatternFirstChild(nsIFrame **kid) return NS_OK; // No, see if we chain to someone who does - nsSVGPatternFrame *next = GetReferencedPattern(); + AutoPatternReferencer patternRef(this); - mLoopFlag = PR_TRUE; - if (!next || next->mLoopFlag) { - mLoopFlag = PR_FALSE; + nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); + if (!next) return NS_ERROR_FAILURE; - } - nsresult rv = next->GetPatternFirstChild(kid); - mLoopFlag = PR_FALSE; - return rv; + return next->GetPatternFirstChild(kid); } PRUint16 -nsSVGPatternFrame::GetPatternUnits() +nsSVGPatternFrame::GetEnumValue(PRUint32 aIndex, nsIContent *aDefault) { - // See if we need to get the value from another pattern - nsSVGPatternElement *patternElement = - GetPatternWithAttr(nsGkAtoms::patternUnits, mContent); - return patternElement->mEnumAttributes[nsSVGPatternElement::PATTERNUNITS].GetAnimValue(); + nsSVGEnum& thisEnum = + static_cast(mContent)->mEnumAttributes[aIndex]; + + if (thisEnum.IsExplicitlySet()) + return thisEnum.GetAnimValue(); + + AutoPatternReferencer patternRef(this); + + nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); + return next ? next->GetEnumValue(aIndex, aDefault) : + static_cast(aDefault)-> + mEnumAttributes[aIndex].GetAnimValue(); } -PRUint16 -nsSVGPatternFrame::GetPatternContentUnits() +nsIDOMSVGAnimatedTransformList* +nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault) { - nsSVGPatternElement *patternElement = - GetPatternWithAttr(nsGkAtoms::patternContentUnits, mContent); - return patternElement->mEnumAttributes[nsSVGPatternElement::PATTERNCONTENTUNITS].GetAnimValue(); + nsIDOMSVGAnimatedTransformList *thisTransformList = + static_cast(mContent)->mPatternTransform.get(); + + // XXX We should be able to do something cleaner than this casting once + // bug 602759 is fixed and we have a proper animated transform list class + const nsSVGAnimatedTransformList *thisListAsConcreteType = + static_cast(thisTransformList); + if (thisListAsConcreteType && thisListAsConcreteType->IsExplicitlySet()) + return thisTransformList; + + AutoPatternReferencer patternRef(this); + + nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); + return next ? next->GetPatternTransformList(aDefault) : + static_cast(aDefault)->mPatternTransform.get(); } gfxMatrix nsSVGPatternFrame::GetPatternTransform() { - nsSVGPatternElement *patternElement = - GetPatternWithAttr(nsGkAtoms::patternTransform, mContent); + nsIDOMSVGAnimatedTransformList* transformList = + GetPatternTransformList(mContent); static const gfxMatrix identityMatrix; - if (!patternElement->mPatternTransform) { + if (!transformList) { return identityMatrix; } nsCOMPtr lTrans; - patternElement->mPatternTransform->GetAnimVal(getter_AddRefs(lTrans)); + transformList->GetAnimVal(getter_AddRefs(lTrans)); nsCOMPtr patternTransform = nsSVGTransformList::GetConsolidationMatrix(lTrans); if (!patternTransform) { @@ -382,49 +420,51 @@ nsSVGPatternFrame::GetPatternTransform() } const nsSVGViewBox & -nsSVGPatternFrame::GetViewBox() +nsSVGPatternFrame::GetViewBox(nsIContent* aDefault) { - nsSVGPatternElement *patternElement = - GetPatternWithAttr(nsGkAtoms::viewBox, mContent); + const nsSVGViewBox &thisViewBox = + static_cast(mContent)->mViewBox; - return patternElement->mViewBox; + if (thisViewBox.IsValid()) + return thisViewBox; + + AutoPatternReferencer patternRef(this); + + nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); + return next ? next->GetViewBox(aDefault) : + static_cast(aDefault)->mViewBox; } const SVGAnimatedPreserveAspectRatio & -nsSVGPatternFrame::GetPreserveAspectRatio() +nsSVGPatternFrame::GetPreserveAspectRatio(nsIContent *aDefault) { - nsSVGPatternElement *patternElement = - GetPatternWithAttr(nsGkAtoms::preserveAspectRatio, mContent); + const SVGAnimatedPreserveAspectRatio &thisPar = + static_cast(mContent)->mPreserveAspectRatio; - return patternElement->mPreserveAspectRatio; + if (thisPar.IsExplicitlySet()) + return thisPar; + + AutoPatternReferencer patternRef(this); + + nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); + return next ? next->GetPreserveAspectRatio(aDefault) : + static_cast(aDefault)->mPreserveAspectRatio; } const nsSVGLength2 * -nsSVGPatternFrame::GetX() +nsSVGPatternFrame::GetLengthValue(PRUint32 aIndex, nsIContent *aDefault) { - nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::x, mContent); - return &pattern->mLengthAttributes[nsSVGPatternElement::X]; -} + const nsSVGLength2 *thisLength = + &static_cast(mContent)->mLengthAttributes[aIndex]; -const nsSVGLength2 * -nsSVGPatternFrame::GetY() -{ - nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::y, mContent); - return &pattern->mLengthAttributes[nsSVGPatternElement::Y]; -} + if (thisLength->IsExplicitlySet()) + return thisLength; -const nsSVGLength2 * -nsSVGPatternFrame::GetWidth() -{ - nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::width, mContent); - return &pattern->mLengthAttributes[nsSVGPatternElement::WIDTH]; -} + AutoPatternReferencer patternRef(this); -const nsSVGLength2 * -nsSVGPatternFrame::GetHeight() -{ - nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::height, mContent); - return &pattern->mLengthAttributes[nsSVGPatternElement::HEIGHT]; + nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); + return next ? next->GetLengthValue(aIndex, aDefault) : + &static_cast(aDefault)->mLengthAttributes[aIndex]; } // Private (helper) methods @@ -470,33 +510,20 @@ nsSVGPatternFrame::GetReferencedPattern() return static_cast(result); } -nsSVGPatternElement * -nsSVGPatternFrame::GetPatternWithAttr(nsIAtom *aAttrName, nsIContent *aDefault) +nsSVGPatternFrame * +nsSVGPatternFrame::GetReferencedPatternIfNotInUse() { - // XXX TODO: this method needs to take account of SMIL animation, since it - // the requested attribute may be animated even if it is not set in the DOM. - // The callers also need to be fixed up to then ask for the right thing from - // the pattern we return! Do we neet to call mContent->FlushAnimations()? + nsSVGPatternFrame *referenced = GetReferencedPattern(); + if (!referenced) + return nsnull; - if (mContent->HasAttr(kNameSpaceID_None, aAttrName)) - return static_cast(mContent); + if (referenced->mLoopFlag) { + // XXXjwatt: we should really send an error to the JavaScript Console here: + NS_WARNING("pattern reference loop detected while inheriting attribute!"); + return nsnull; + } - nsSVGPatternElement *pattern = static_cast(aDefault); - - nsSVGPatternFrame *next = GetReferencedPattern(); - if (!next) - return pattern; - - // Set mLoopFlag before checking mNextGrad->mLoopFlag in case we are mNextGrad - mLoopFlag = PR_TRUE; - // XXXjwatt: we should really send an error to the JavaScript Console here: - NS_WARN_IF_FALSE(!next->mLoopFlag, "gradient reference loop detected " - "while inheriting attribute!"); - if (!next->mLoopFlag) - pattern = next->GetPatternWithAttr(aAttrName, aDefault); - mLoopFlag = PR_FALSE; - - return pattern; + return referenced; } // ------------------------------------------------------------------------- @@ -509,17 +536,17 @@ nsSVGPatternFrame::GetPatternRect(const gfxRect &aTargetBBox, nsIFrame *aTarget) { // Get our type - PRUint16 type = GetPatternUnits(); + PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNUNITS); // We need to initialize our box float x,y,width,height; // Get the pattern x,y,width, and height const nsSVGLength2 *tmpX, *tmpY, *tmpHeight, *tmpWidth; - tmpX = GetX(); - tmpY = GetY(); - tmpHeight = GetHeight(); - tmpWidth = GetWidth(); + tmpX = GetLengthValue(nsSVGPatternElement::X); + tmpY = GetLengthValue(nsSVGPatternElement::Y); + tmpHeight = GetLengthValue(nsSVGPatternElement::HEIGHT); + tmpWidth = GetLengthValue(nsSVGPatternElement::WIDTH); if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { x = nsSVGUtils::ObjectSpace(aTargetBBox, tmpX); @@ -547,7 +574,7 @@ nsSVGPatternFrame::ConstructCTM(const gfxRect &callerBBox, nsIContent* targetContent = aTarget->GetContent(); // The objectBoundingBox conversion must be handled in the CTM: - if (GetPatternContentUnits() == + if (GetEnumValue(nsSVGPatternElement::PATTERNCONTENTUNITS) == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { tCTM.Scale(callerBBox.Width(), callerBBox.Height()); } else { @@ -569,16 +596,20 @@ nsSVGPatternFrame::ConstructCTM(const gfxRect &callerBBox, // If we're dealing with an SVG target only retrieve the context once. // Calling the nsIFrame* variant of GetAnimValue would look it up on // every call. - viewportWidth = GetWidth()->GetAnimValue(ctx); - viewportHeight = GetHeight()->GetAnimValue(ctx); - refX = GetX()->GetAnimValue(ctx); - refY = GetY()->GetAnimValue(ctx); + viewportWidth = + GetLengthValue(nsSVGPatternElement::WIDTH)->GetAnimValue(ctx); + viewportHeight = + GetLengthValue(nsSVGPatternElement::HEIGHT)->GetAnimValue(ctx); + refX = GetLengthValue(nsSVGPatternElement::X)->GetAnimValue(ctx); + refY = GetLengthValue(nsSVGPatternElement::Y)->GetAnimValue(ctx); } else { // No SVG target, call the nsIFrame* variant of GetAnimValue. - viewportWidth = GetWidth()->GetAnimValue(aTarget); - viewportHeight = GetHeight()->GetAnimValue(aTarget); - refX = GetX()->GetAnimValue(aTarget); - refY = GetY()->GetAnimValue(aTarget); + viewportWidth = + GetLengthValue(nsSVGPatternElement::WIDTH)->GetAnimValue(aTarget); + viewportHeight = + GetLengthValue(nsSVGPatternElement::HEIGHT)->GetAnimValue(aTarget); + refX = GetLengthValue(nsSVGPatternElement::X)->GetAnimValue(aTarget); + refY = GetLengthValue(nsSVGPatternElement::Y)->GetAnimValue(aTarget); } gfxMatrix viewBoxTM = nsSVGUtils::GetViewBoxTransform(patternElement, viewportWidth, viewportHeight, @@ -605,7 +636,7 @@ nsSVGPatternFrame::GetPatternMatrix(const gfxRect &bbox, float minx = bbox.X(); float miny = bbox.Y(); - PRUint16 type = GetPatternContentUnits(); + PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNCONTENTUNITS); if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { minx += callerBBox.X(); miny += callerBBox.Y(); @@ -627,7 +658,7 @@ nsSVGPatternFrame::GetTargetGeometry(gfxMatrix *aCTM, *aBBox = aOverrideBounds ? *aOverrideBounds : nsSVGUtils::GetBBox(aTarget); // Sanity check - PRUint16 type = GetPatternUnits(); + PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNUNITS); if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { if (aBBox->Width() <= 0 || aBBox->Height() <= 0) { return NS_ERROR_FAILURE; diff --git a/layout/svg/base/src/nsSVGPatternFrame.h b/layout/svg/base/src/nsSVGPatternFrame.h index 742ce101e0b..4a2606c0c19 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.h +++ b/layout/svg/base/src/nsSVGPatternFrame.h @@ -110,25 +110,31 @@ public: protected: // Internal methods for handling referenced patterns + class AutoPatternReferencer; nsSVGPatternFrame* GetReferencedPattern(); - // Helper to look at our pattern and then along its reference chain (if any) - // to find the first pattern with the specified attribute. Returns - // null if there isn't one. - nsSVGPatternElement* GetPatternWithAttr(nsIAtom *aAttrName, nsIContent *aDefault); + nsSVGPatternFrame* GetReferencedPatternIfNotInUse(); - // - const nsSVGLength2 *GetX(); - const nsSVGLength2 *GetY(); - const nsSVGLength2 *GetWidth(); - const nsSVGLength2 *GetHeight(); - - PRUint16 GetPatternUnits(); - PRUint16 GetPatternContentUnits(); + // Accessors to lookup pattern attributes + PRUint16 GetEnumValue(PRUint32 aIndex, nsIContent *aDefault); + PRUint16 GetEnumValue(PRUint32 aIndex) + { + return GetEnumValue(aIndex, mContent); + } + nsIDOMSVGAnimatedTransformList* GetPatternTransformList(nsIContent* aDefault); gfxMatrix GetPatternTransform(); - - const nsSVGViewBox &GetViewBox(); - const SVGAnimatedPreserveAspectRatio &GetPreserveAspectRatio(); - + const nsSVGViewBox &GetViewBox(nsIContent *aDefault); + const nsSVGViewBox &GetViewBox() { return GetViewBox(mContent); } + const SVGAnimatedPreserveAspectRatio &GetPreserveAspectRatio( + nsIContent *aDefault); + const SVGAnimatedPreserveAspectRatio &GetPreserveAspectRatio() + { + return GetPreserveAspectRatio(mContent); + } + const nsSVGLength2 *GetLengthValue(PRUint32 aIndex, nsIContent *aDefault); + const nsSVGLength2 *GetLengthValue(PRUint32 aIndex) + { + return GetLengthValue(aIndex, mContent); + } nsresult PaintPattern(gfxASurface **surface, gfxMatrix *patternMatrix,