зеркало из https://github.com/mozilla/pjs.git
Bug 544809 - nsSVGPatternFrame::GetPatternWithAttr and callers should take account of SMIL animation, r=longsonr, a=roc
This commit is contained in:
Родитель
c870c206b2
Коммит
4037072a35
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -80,6 +80,8 @@ public:
|
|||
// nsISupportsWeakReference
|
||||
// implementation inherited from nsSupportsWeakReference
|
||||
|
||||
PRBool IsExplicitlySet() const;
|
||||
|
||||
protected:
|
||||
friend class nsSVGTransformSMILAttr;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 600">
|
||||
<!-- 1. patternUnits -->
|
||||
<defs>
|
||||
<pattern id="patternUnits" width="80" height="80"
|
||||
patternUnits="userSpaceOnUse">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100" height="100" stroke="black" fill="url(#patternUnits)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#patternUnits)"/>
|
||||
</g>
|
||||
<!-- 2. patternContentUnits -->
|
||||
<defs>
|
||||
<pattern id="patternContentUnits" width="1" height="1"
|
||||
patternContentUnits="objectBoundingBox">
|
||||
<rect width="0.5" height="0.5" fill="blue"/>
|
||||
<rect x="0.5" width="0.5" height="0.5" fill="red"/>
|
||||
<rect y="0.5" width="0.5" height="0.5" fill="red"/>
|
||||
<rect x="0.5" y="0.5" width="0.5" height="0.5" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternContentUnits)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternContentUnits)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 3. patternTransform -->
|
||||
<defs>
|
||||
<pattern id="patternTransform" width="1" height="1"
|
||||
patternTransform="rotate(45 50 50)">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 200)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternTransform)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternTransform)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 4. preserveAspectRatio -->
|
||||
<defs>
|
||||
<pattern id="par" width="1" height="1" viewBox="0.1 0.1 0.6 0.85"
|
||||
preserveAspectRatio="none">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 300)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#par)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#par)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 5. viewBox -->
|
||||
<defs>
|
||||
<pattern id="viewBox" width="1" height="1" viewBox="0.1 0.1 0.6 0.85"
|
||||
preserveAspectRatio="none">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 400)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#viewBox)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#viewBox)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 6. xlink:href -->
|
||||
<defs>
|
||||
<pattern id="xlink" xlink:href="#xlinkRef"/>
|
||||
<pattern id="xlinkRef" width="1" height="1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 500)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xlink)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xlink)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.9 KiB |
|
@ -0,0 +1,138 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 600">
|
||||
<!-- Bug 544809 - nsSVGPatternFrame::GetPatternWithAttr and callers should
|
||||
take account of SMIL animation.
|
||||
|
||||
Test animating pattern attributes doesn't rely on the presence of
|
||||
attributes in the DOM, but also correctly detects attributes set by
|
||||
animation.
|
||||
|
||||
The format of each test is that we have a base pattern named (attName)Ref
|
||||
which does NOT specify the attribute under test, but instead sets the
|
||||
attribute to a non-default value using animation.
|
||||
|
||||
Then we have a referencing pattern named (attName) that refers to the
|
||||
base pattern and also does NOT specify the attribute under test.
|
||||
|
||||
When we go to look up the attribute under test we begin at (attName),
|
||||
notice the attribute isn't specified (either in the DOM or by animation),
|
||||
then go to (attName)Ref and detect that the attribute is specified there
|
||||
by animation and use that value.
|
||||
|
||||
To the right of each test we also include a rect that directly references
|
||||
(attName)Ref. The two rectangles should be identical but prior to fixing
|
||||
this bug they were not.
|
||||
-->
|
||||
<!-- 1. patternUnits: defaults to objectBoundingBox -->
|
||||
<defs>
|
||||
<pattern xlink:href="#patternUnitsRef" id="patternUnits"/>
|
||||
<pattern id="patternUnitsRef" width="80" height="80">
|
||||
<set attributeName="patternUnits" to="userSpaceOnUse"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100" height="100" stroke="black" fill="url(#patternUnits)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#patternUnitsRef)"/>
|
||||
</g>
|
||||
<!-- 2. patternContentUnits: defaults to userSpaceOnUse -->
|
||||
<defs>
|
||||
<pattern xlink:href="#patternContentUnitsRef" id="patternContentUnits"/>
|
||||
<pattern id="patternContentUnitsRef" width="1" height="1">
|
||||
<set attributeName="patternContentUnits" to="objectBoundingBox"/>
|
||||
<rect width="0.5" height="0.5" fill="blue"/>
|
||||
<rect x="0.5" width="0.5" height="0.5" fill="red"/>
|
||||
<rect y="0.5" width="0.5" height="0.5" fill="red"/>
|
||||
<rect x="0.5" y="0.5" width="0.5" height="0.5" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternContentUnits)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternContentUnitsRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 3. patternTransform: defaults to identity -->
|
||||
<defs>
|
||||
<pattern xlink:href="#patternTransformRef" id="patternTransform"/>
|
||||
<pattern id="patternTransformRef" width="1" height="1">
|
||||
<animateTransform attributeName="patternTransform" type="rotate"
|
||||
values="45 50 50" fill="freeze"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 200)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternTransform)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#patternTransformRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 4. preserveAspectRatio: defaults to xMidYMid meet -->
|
||||
<defs>
|
||||
<pattern xlink:href="#parRef" id="par"/>
|
||||
<pattern id="parRef" width="1" height="1" viewBox="0.1 0.1 0.6 0.85">
|
||||
<set attributeName="preserveAspectRatio" to="none"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 300)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#par)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#parRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 5. viewBox -->
|
||||
<defs>
|
||||
<pattern xlink:href="#viewBoxRef" id="viewBox"/>
|
||||
<pattern id="viewBoxRef" width="1" height="1"
|
||||
preserveAspectRatio="none">
|
||||
<set attributeName="viewBox" to="0.1 0.1 0.6 0.85"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 400)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#viewBox)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#viewBoxRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 6. xlink:href
|
||||
This attribute is not affected by bug 544809, i.e. it doesn't use
|
||||
nsSVGPatternFrame::GetPatternWithAttr, but we test it here for completeness
|
||||
-->
|
||||
<defs>
|
||||
<pattern id="xlink">
|
||||
<set attributeName="xlink:href" to="#xlinkRef"/>
|
||||
</pattern>
|
||||
<pattern id="xlinkRef" width="1" height="1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 500)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xlink)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xlinkRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 5.8 KiB |
|
@ -0,0 +1,35 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
|
||||
<!-- 1. x, y -->
|
||||
<defs>
|
||||
<pattern id="xy" width="1" height="1" x="0.1" y="-0.1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g>
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 2. width, height -->
|
||||
<defs>
|
||||
<pattern id="widthHeight" width="1" height="1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.3 KiB |
|
@ -0,0 +1,52 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
|
||||
<!-- Bug 544809 - nsSVGPatternFrame::GetPatternWithAttr and callers should
|
||||
take account of SMIL animation.
|
||||
|
||||
This test is a continuation of anim-pattern-attr-presence-01.svg but is
|
||||
separated because it currently fails due to bug 621651. Once that bug is
|
||||
resolved the tests in this file should be merged into
|
||||
anim-pattern-attr-presence-01.svg
|
||||
-->
|
||||
<!-- 1. x, y: defaults to 0 -->
|
||||
<!-- Currently broken by bug 621651 -->
|
||||
<defs>
|
||||
<pattern xlink:href="#xyRef" id="xy"/>
|
||||
<pattern id="xyRef" width="1" height="1">
|
||||
<set attributeName="x" to="0.1"/>
|
||||
<set attributeName="y" to="-0.1"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g>
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xyRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 2. width, height: defaults to 0 (disables rendering) -->
|
||||
<!-- Currently broken by bug 621651 -->
|
||||
<defs>
|
||||
<pattern xlink:href="#widthHeightRef" id="widthHeight"/>
|
||||
<pattern id="widthHeightRef">
|
||||
<set attributeName="width" to="1"/>
|
||||
<set attributeName="height" to="1"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#widthHeightRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.1 KiB |
|
@ -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
|
||||
|
||||
|
|
|
@ -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<nsSVGPatternElement *>(mContent)->mEnumAttributes[aIndex];
|
||||
|
||||
if (thisEnum.IsExplicitlySet())
|
||||
return thisEnum.GetAnimValue();
|
||||
|
||||
AutoPatternReferencer patternRef(this);
|
||||
|
||||
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
||||
return next ? next->GetEnumValue(aIndex, aDefault) :
|
||||
static_cast<nsSVGPatternElement *>(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<nsSVGPatternElement *>(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<const nsSVGAnimatedTransformList *>(thisTransformList);
|
||||
if (thisListAsConcreteType && thisListAsConcreteType->IsExplicitlySet())
|
||||
return thisTransformList;
|
||||
|
||||
AutoPatternReferencer patternRef(this);
|
||||
|
||||
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
||||
return next ? next->GetPatternTransformList(aDefault) :
|
||||
static_cast<nsSVGPatternElement *>(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<nsIDOMSVGTransformList> lTrans;
|
||||
patternElement->mPatternTransform->GetAnimVal(getter_AddRefs(lTrans));
|
||||
transformList->GetAnimVal(getter_AddRefs(lTrans));
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsSVGPatternElement *>(mContent)->mViewBox;
|
||||
|
||||
return patternElement->mViewBox;
|
||||
if (thisViewBox.IsValid())
|
||||
return thisViewBox;
|
||||
|
||||
AutoPatternReferencer patternRef(this);
|
||||
|
||||
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
||||
return next ? next->GetViewBox(aDefault) :
|
||||
static_cast<nsSVGPatternElement *>(aDefault)->mViewBox;
|
||||
}
|
||||
|
||||
const SVGAnimatedPreserveAspectRatio &
|
||||
nsSVGPatternFrame::GetPreserveAspectRatio()
|
||||
nsSVGPatternFrame::GetPreserveAspectRatio(nsIContent *aDefault)
|
||||
{
|
||||
nsSVGPatternElement *patternElement =
|
||||
GetPatternWithAttr(nsGkAtoms::preserveAspectRatio, mContent);
|
||||
const SVGAnimatedPreserveAspectRatio &thisPar =
|
||||
static_cast<nsSVGPatternElement *>(mContent)->mPreserveAspectRatio;
|
||||
|
||||
return patternElement->mPreserveAspectRatio;
|
||||
if (thisPar.IsExplicitlySet())
|
||||
return thisPar;
|
||||
|
||||
AutoPatternReferencer patternRef(this);
|
||||
|
||||
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
||||
return next ? next->GetPreserveAspectRatio(aDefault) :
|
||||
static_cast<nsSVGPatternElement *>(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<nsSVGPatternElement *>(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<nsSVGPatternElement *>(aDefault)->mLengthAttributes[aIndex];
|
||||
}
|
||||
|
||||
// Private (helper) methods
|
||||
|
@ -470,33 +510,20 @@ nsSVGPatternFrame::GetReferencedPattern()
|
|||
return static_cast<nsSVGPatternFrame*>(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<nsSVGPatternElement *>(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<nsSVGPatternElement *>(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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче