Bug 561726 - make animateTransform work on gradientTransform and patternTransform. r=jwatt

This commit is contained in:
Robert Longson 2010-05-28 13:15:56 +01:00
parent f9b20eb9ad
commit 189cf82cee
11 changed files with 194 additions and 42 deletions

View File

@ -86,6 +86,8 @@
#include "nsIDOMSVGTransformList.h"
#include "nsIDOMSVGAnimTransformList.h"
#include "nsIDOMSVGAnimatedRect.h"
#include "nsIDOMSVGGradientElement.h"
#include "nsIDOMSVGPatternElement.h"
#include "nsSVGRect.h"
#include "nsIFrame.h"
#include "prdtoa.h"
@ -1940,14 +1942,30 @@ nsISMILAttr*
nsSVGElement::GetAnimatedAttr(nsIAtom* aName)
{
// Transforms:
nsCOMPtr<nsIDOMSVGAnimatedTransformList> transformList;
if (aName == nsGkAtoms::transform) {
nsCOMPtr<nsIDOMSVGTransformable> transformable(
do_QueryInterface(static_cast<nsIContent*>(this)));
if (!transformable)
return nsnull;
nsCOMPtr<nsIDOMSVGAnimatedTransformList> transformList;
nsresult rv = transformable->GetTransform(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv, nsnull);
}
if (aName == nsGkAtoms::gradientTransform) {
nsCOMPtr<nsIDOMSVGGradientElement> gradientElement(
do_QueryInterface(static_cast<nsIContent*>(this)));
nsresult rv = gradientElement->GetGradientTransform(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv, nsnull);
}
if (aName == nsGkAtoms::patternTransform) {
nsCOMPtr<nsIDOMSVGPatternElement> patternElement(
do_QueryInterface(static_cast<nsIContent*>(this)));
nsresult rv = patternElement->GetPatternTransform(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv, nsnull);
}
if (transformList) {
nsSVGAnimatedTransformList* list
= static_cast<nsSVGAnimatedTransformList*>(transformList.get());
NS_ENSURE_TRUE(list, nsnull);

View File

@ -41,10 +41,12 @@
#include "nsIDOMSVGAnimatedEnum.h"
#include "nsIDOMSVGURIReference.h"
#include "nsIDOMSVGGradientElement.h"
#include "nsIDOMMutationEvent.h"
#include "nsCOMPtr.h"
#include "nsSVGStylableElement.h"
#include "nsGkAtoms.h"
#include "nsSVGGradientElement.h"
#include "nsIFrame.h"
//--------------------- Gradients------------------------
@ -92,31 +94,55 @@ nsSVGGradientElement::nsSVGGradientElement(nsINodeInfo* aNodeInfo)
}
nsresult
nsSVGGradientElement::Init()
nsSVGGradientElement::CreateTransformList()
{
nsresult rv = nsSVGGradientElementBase::Init();
NS_ENSURE_SUCCESS(rv,rv);
nsresult rv;
// Create mapped attributes
// DOM property: gradientTransform , #IMPLIED attrib: gradientTransform
{
nsCOMPtr<nsIDOMSVGTransformList> transformList;
rv = nsSVGTransformList::Create(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedTransformList(getter_AddRefs(mGradientTransform),
transformList);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::gradientTransform, mGradientTransform);
NS_ENSURE_SUCCESS(rv,rv);
// DOM property: transform, #IMPLIED attrib: transform
nsCOMPtr<nsIDOMSVGTransformList> transformList;
rv = nsSVGTransformList::Create(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewSVGAnimatedTransformList(getter_AddRefs(mGradientTransform),
transformList);
NS_ENSURE_SUCCESS(rv, rv);
rv = AddMappedSVGValue(nsGkAtoms::gradientTransform, mGradientTransform);
if (NS_FAILED(rv)) {
mGradientTransform = nsnull;
return rv;
}
return NS_OK;
}
nsresult
nsSVGGradientElement::BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNamespaceID == kNameSpaceID_None &&
aName == nsGkAtoms::gradientTransform &&
!mGradientTransform &&
NS_FAILED(CreateTransformList()))
return NS_ERROR_OUT_OF_MEMORY;
return nsSVGGradientElementBase::BeforeSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
//----------------------------------------------------------------------
// nsSVGElement methods
void
nsSVGGradientElement::DidAnimateTransform()
{
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
frame->AttributeChanged(kNameSpaceID_None,
nsGkAtoms::gradientTransform,
nsIDOMMutationEvent::MODIFICATION);
}
}
nsSVGElement::EnumAttributesInfo
nsSVGGradientElement::GetEnumInfo()
{
@ -143,6 +169,9 @@ NS_IMETHODIMP nsSVGGradientElement::GetGradientUnits(nsIDOMSVGAnimatedEnumeratio
/* readonly attribute nsIDOMSVGAnimatedTransformList gradientTransform; */
NS_IMETHODIMP nsSVGGradientElement::GetGradientTransform(nsIDOMSVGAnimatedTransformList * *aGradientTransform)
{
if (!mGradientTransform && NS_FAILED(CreateTransformList()))
return NS_ERROR_OUT_OF_MEMORY;
*aGradientTransform = mGradientTransform;
NS_IF_ADDREF(*aGradientTransform);
return NS_OK;
@ -342,4 +371,3 @@ nsSVGRadialGradientElement::GetLengthInfo()
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
NS_ARRAY_LENGTH(sLengthInfo));
}

View File

@ -59,7 +59,6 @@ class nsSVGGradientElement : public nsSVGGradientElementBase,
protected:
nsSVGGradientElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
@ -78,6 +77,8 @@ protected:
virtual EnumAttributesInfo GetEnumInfo();
virtual StringAttributesInfo GetStringInfo();
virtual void DidAnimateTransform();
enum { GRADIENTUNITS, SPREADMETHOD };
nsSVGEnum mEnumAttributes[2];
static nsSVGEnumMapping sSpreadMethodMap[];
@ -87,8 +88,14 @@ protected:
nsSVGString mStringAttributes[1];
static StringInfo sStringInfo[1];
virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
// nsIDOMSVGGradientElement values
nsCOMPtr<nsIDOMSVGAnimatedTransformList> mGradientTransform;
// helper
nsresult CreateTransformList();
};
//---------------------Linear Gradients------------------------

View File

@ -38,6 +38,7 @@
#include "nsSVGTransformList.h"
#include "nsSVGAnimatedTransformList.h"
#include "nsIDOMMutationEvent.h"
#include "nsCOMPtr.h"
#include "nsGkAtoms.h"
#include "nsSVGPatternElement.h"
@ -97,28 +98,40 @@ nsSVGPatternElement::nsSVGPatternElement(nsINodeInfo* aNodeInfo)
}
nsresult
nsSVGPatternElement::Init()
nsSVGPatternElement::CreateTransformList()
{
nsresult rv = nsSVGPatternElementBase::Init();
NS_ENSURE_SUCCESS(rv,rv);
nsresult rv;
// Create mapped attributes
// DOM property: patternTransform , #IMPLIED attrib: patternTransform
{
nsCOMPtr<nsIDOMSVGTransformList> transformList;
rv = nsSVGTransformList::Create(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedTransformList(getter_AddRefs(mPatternTransform),
transformList);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::patternTransform, mPatternTransform);
NS_ENSURE_SUCCESS(rv,rv);
// DOM property: transform, #IMPLIED attrib: transform
nsCOMPtr<nsIDOMSVGTransformList> transformList;
rv = nsSVGTransformList::Create(getter_AddRefs(transformList));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewSVGAnimatedTransformList(getter_AddRefs(mPatternTransform),
transformList);
NS_ENSURE_SUCCESS(rv, rv);
rv = AddMappedSVGValue(nsGkAtoms::patternTransform, mPatternTransform);
if (NS_FAILED(rv)) {
mPatternTransform = nsnull;
return rv;
}
return NS_OK;
}
nsresult
nsSVGPatternElement::BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNamespaceID == kNameSpaceID_None &&
aName == nsGkAtoms::patternTransform &&
!mPatternTransform &&
NS_FAILED(CreateTransformList()))
return NS_ERROR_OUT_OF_MEMORY;
return nsSVGPatternElementBase::BeforeSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
//----------------------------------------------------------------------
// nsIDOMNode method
@ -159,6 +172,9 @@ NS_IMETHODIMP nsSVGPatternElement::GetPatternContentUnits(nsIDOMSVGAnimatedEnume
/* readonly attribute nsIDOMSVGAnimatedTransformList patternTransform; */
NS_IMETHODIMP nsSVGPatternElement::GetPatternTransform(nsIDOMSVGAnimatedTransformList * *aPatternTransform)
{
if (!mPatternTransform && NS_FAILED(CreateTransformList()))
return NS_ERROR_OUT_OF_MEMORY;
*aPatternTransform = mPatternTransform;
NS_IF_ADDREF(*aPatternTransform);
return NS_OK;
@ -223,6 +239,18 @@ nsSVGPatternElement::IsAttributeMapped(const nsIAtom* name) const
//----------------------------------------------------------------------
// nsSVGElement methods
void
nsSVGPatternElement::DidAnimateTransform()
{
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
frame->AttributeChanged(kNameSpaceID_None,
nsGkAtoms::patternTransform,
nsIDOMMutationEvent::MODIFICATION);
}
}
nsSVGElement::LengthAttributesInfo
nsSVGPatternElement::GetLengthInfo()
{

View File

@ -64,9 +64,8 @@ class nsSVGPatternElement : public nsSVGPatternElementBase,
protected:
friend nsresult NS_NewSVGPatternElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsINodeInfo *aNodeInfo);
nsSVGPatternElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
@ -92,12 +91,17 @@ public:
protected:
virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual LengthAttributesInfo GetLengthInfo();
virtual EnumAttributesInfo GetEnumInfo();
virtual nsSVGViewBox *GetViewBox();
virtual nsSVGPreserveAspectRatio *GetPreserveAspectRatio();
virtual StringAttributesInfo GetStringInfo();
virtual void DidAnimateTransform();
// nsIDOMSVGPatternElement values
enum { X, Y, WIDTH, HEIGHT };
nsSVGLength2 mLengthAttributes[4];
@ -117,6 +121,9 @@ protected:
// nsIDOMSVGFitToViewbox properties
nsSVGViewBox mViewBox;
nsSVGPreserveAspectRatio mPreserveAspectRatio;
// helper
nsresult CreateTransformList();
};
#endif

View File

@ -11,3 +11,5 @@
== scale-1.svg scale-1-ref.svg
== skew-1.svg skew-1-ref.svg
== translate-clipPath-1.svg lime.svg
== translate-gradient-1.svg lime.svg
== translate-pattern-1.svg lime.svg

View File

@ -23,7 +23,7 @@
<rect x="0" width="50" height="100%" fill="red"
style="clip-path: url(#clip);"/>
<!-- Test 2: Puprle background covered by clipped lime block.
<!-- Test 2: Purple background covered by clipped lime block.
Initially, the clipping path is to the right of the lime, so the purple
background shows through. But after the animation, the clipping path
exactly matches the dimensions of the lime block, which lets it

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,29 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script>
function doTest() {
setTimeAndSnapshot(1, false);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<defs>
<linearGradient id="grad" width="50">
<stop offset="0" stop-color="red"/>
<stop offset="1" stop-color="lime"/>
<stop offset="2" stop-color="lime"/>
<animateTransform attributeName="gradientTransform" type="translate" dur="1s"
from="0 0" to="-1 0" fill="freeze"/>
</linearGradient>
</defs>
<!-- Test 1: Lime background covered by left hand side of gradient.
After the animation, the right hand lime side of the gradient
is visible, so no red is shown. -->
<rect x="0" width="50" height="100%" fill="lime" />
<rect x="0" width="50" height="100%" fill="url(#grad)"/>
<!-- Not a test: Paint the rest of the viewport, to match lime.svg -->
<rect x="50" height="100%" width="100%" fill="lime"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,28 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script>
function doTest() {
setTimeAndSnapshot(1, false);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<defs>
<pattern id="pat" width="50">
<rect x="0" y="0" width="50" height="100%" fill="red"/>
<rect x="50" y="0" width="50" height="100%" fill="lime"/>
<animateTransform attributeName="patternTransform" type="translate" dur="1s"
from="0 0" to="-50 0" fill="freeze"/>
</pattern>
</defs>
<!-- Test 1: Lime background covered by left hand side of pattern.
After the animation, the right hand lime side of the pattern
is visible, so no red is shown. -->
<rect x="0" width="50" height="100%" fill="lime" />
<rect x="0" width="50" height="100%" fill="url(#pat)" />
<!-- Not a test: Paint the rest of the viewport, to match lime.svg -->
<rect x="50" height="100%" width="100%" fill="lime"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -161,8 +161,7 @@ nsSVGGradientFrame::GetGradientTransform(nsSVGGeometryFrame *aSource)
else
mSourceContent = static_cast<nsSVGElement*>(aSource->GetContent());
NS_ASSERTION(mSourceContent, "Can't get content for gradient");
}
else {
} else {
NS_ASSERTION(gradientUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX,
"Unknown gradientUnits type");
// objectBoundingBox is the default anyway
@ -176,6 +175,9 @@ nsSVGGradientFrame::GetGradientTransform(nsSVGGeometryFrame *aSource)
nsSVGGradientElement *element =
GetGradientWithAttr(nsGkAtoms::gradientTransform, mContent);
if (!element->mGradientTransform)
return bboxMatrix;
nsCOMPtr<nsIDOMSVGTransformList> trans;
element->mGradientTransform->GetAnimVal(getter_AddRefs(trans));
nsCOMPtr<nsIDOMSVGMatrix> gradientTransform =

View File

@ -357,15 +357,18 @@ nsSVGPatternFrame::GetPatternTransform()
nsSVGPatternElement *patternElement =
GetPatternWithAttr(nsGkAtoms::patternTransform, mContent);
gfxMatrix matrix;
static const gfxMatrix identityMatrix;
if (!patternElement->mPatternTransform) {
return identityMatrix;
}
nsCOMPtr<nsIDOMSVGTransformList> lTrans;
patternElement->mPatternTransform->GetAnimVal(getter_AddRefs(lTrans));
nsCOMPtr<nsIDOMSVGMatrix> patternTransform =
nsSVGTransformList::GetConsolidationMatrix(lTrans);
if (patternTransform) {
matrix = nsSVGUtils::ConvertSVGMatrixToThebes(patternTransform);
if (!patternTransform) {
return identityMatrix;
}
return matrix;
return nsSVGUtils::ConvertSVGMatrixToThebes(patternTransform);
}
const nsSVGViewBox &