Bug 539576 - SVGTransform matrix changes still not live in all circumstances (with bustage fix). r=jwatt
--- a/content/svg/content/src/nsSVGMatrix.cpp
+++ b/content/svg/content/src/nsSVGMatrix.cpp
@@ -310,29 +310,33 @@ NS_IMETHODIMP nsSVGMatrix::FlipY(nsIDOMS
/* nsIDOMSVGMatrix skewX (in float angle); */
NS_IMETHODIMP nsSVGMatrix::SkewX(float angle, nsIDOMSVGMatrix **_retval)
{
NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
double ta = tan( angle*radPerDegree );
+ NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
return NS_NewSVGMatrix(_retval,
mA, mB,
(float) ( mC + mA*ta), (float) ( mD + mB*ta),
mE, mF);
}
/* nsIDOMSVGMatrix skewY (in float angle); */
NS_IMETHODIMP nsSVGMatrix::SkewY(float angle, nsIDOMSVGMatrix **_retval)
{
NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
double ta = tan( angle*radPerDegree );
+ NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
return NS_NewSVGMatrix(_retval,
(float) (mA + mC*ta), (float) (mB + mD*ta),
mC, mD,
mE, mF);
}
//----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGTransform.cpp
+++ b/content/svg/content/src/nsSVGTransform.cpp
@@ -41,16 +41,18 @@
#include "nsSVGMatrix.h"
#include "nsISVGValueUtils.h"
#include "nsWeakReference.h"
#include "nsSVGMatrix.h"
#include "nsTextFormatter.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
+const double radPerDegree = 2.0*3.1415926535 / 360.0;
+
//----------------------------------------------------------------------
// Implementation
nsresult
nsSVGTransform::Create(nsIDOMSVGTransform** aResult)
{
nsSVGTransform *pl = new nsSVGTransform();
NS_ENSURE_TRUE(pl, NS_ERROR_OUT_OF_MEMORY);
@@ -198,16 +200,19 @@ NS_IMETHODIMP nsSVGTransform::WillModify
{
WillModify();
return NS_OK;
}
NS_IMETHODIMP nsSVGTransform::DidModifySVGObservable (nsISVGValue* observable,
modificationType aModType)
{
+ // we become a general matrix transform if mMatrix changes
+ mType = SVG_TRANSFORM_MATRIX;
+ mAngle = 0.0f;
DidModify();
return NS_OK;
}
//----------------------------------------------------------------------
// nsIDOMSVGTransform methods:
@@ -240,76 +245,76 @@ NS_IMETHODIMP nsSVGTransform::SetMatrix(
if (!matrix)
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
WillModify();
mType = SVG_TRANSFORM_MATRIX;
mAngle = 0.0f;
- mOriginX = 0.0f;
- mOriginY = 0.0f;
matrix->GetA(&a);
matrix->GetB(&b);
matrix->GetC(&c);
matrix->GetD(&d);
matrix->GetE(&e);
matrix->GetF(&f);
+ NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
mMatrix->SetA(a);
mMatrix->SetB(b);
mMatrix->SetC(c);
mMatrix->SetD(d);
mMatrix->SetE(e);
mMatrix->SetF(f);
+ NS_ADD_SVGVALUE_OBSERVER(mMatrix);
DidModify();
return NS_OK;
}
/* void setTranslate (in float tx, in float ty); */
NS_IMETHODIMP nsSVGTransform::SetTranslate(float tx, float ty)
{
NS_ENSURE_FINITE2(tx, ty, NS_ERROR_ILLEGAL_VALUE);
WillModify();
mType = SVG_TRANSFORM_TRANSLATE;
mAngle = 0.0f;
- mOriginX = 0.0f;
- mOriginY = 0.0f;
+ NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
mMatrix->SetA(1.0f);
mMatrix->SetB(0.0f);
mMatrix->SetC(0.0f);
mMatrix->SetD(1.0f);
mMatrix->SetE(tx);
mMatrix->SetF(ty);
+ NS_ADD_SVGVALUE_OBSERVER(mMatrix);
DidModify();
return NS_OK;
}
/* void setScale (in float sx, in float sy); */
NS_IMETHODIMP nsSVGTransform::SetScale(float sx, float sy)
{
NS_ENSURE_FINITE2(sx, sy, NS_ERROR_ILLEGAL_VALUE);
WillModify();
mType = SVG_TRANSFORM_SCALE;
mAngle = 0.0f;
- mOriginX = 0.0f;
- mOriginY = 0.0f;
+ NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
mMatrix->SetA(sx);
mMatrix->SetB(0.0f);
mMatrix->SetC(0.0f);
mMatrix->SetD(sy);
mMatrix->SetE(0.0f);
mMatrix->SetF(0.0f);
+ NS_ADD_SVGVALUE_OBSERVER(mMatrix);
DidModify();
return NS_OK;
}
/* void setRotate (in float angle, in float cx, in float cy); */
NS_IMETHODIMP nsSVGTransform::SetRotate(float angle, float cx, float cy)
{
@@ -317,67 +322,81 @@ NS_IMETHODIMP nsSVGTransform::SetRotate(
WillModify();
mType = SVG_TRANSFORM_ROTATE;
mAngle = angle;
mOriginX = cx;
mOriginY = cy;
+ gfxMatrix matrix(1, 0, 0, 1, cx, cy);
+ matrix.Rotate(angle * radPerDegree);
+ matrix.Translate(gfxPoint(-cx, -cy));
+
NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
- NS_NewSVGMatrix(getter_AddRefs(mMatrix));
- nsCOMPtr<nsIDOMSVGMatrix> temp;
- mMatrix->Translate(cx, cy, getter_AddRefs(temp));
- mMatrix = temp;
- mMatrix->Rotate(angle, getter_AddRefs(temp));
- mMatrix = temp;
- mMatrix->Translate(-cx,-cy, getter_AddRefs(temp));
- mMatrix = temp;
+ mMatrix->SetA(static_cast<float>(matrix.xx));
+ mMatrix->SetB(static_cast<float>(matrix.yx));
+ mMatrix->SetC(static_cast<float>(matrix.xy));
+ mMatrix->SetD(static_cast<float>(matrix.yy));
+ mMatrix->SetE(static_cast<float>(matrix.x0));
+ mMatrix->SetF(static_cast<float>(matrix.y0));
NS_ADD_SVGVALUE_OBSERVER(mMatrix);
DidModify();
return NS_OK;
}
/* void setSkewX (in float angle); */
NS_IMETHODIMP nsSVGTransform::SetSkewX(float angle)
{
NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
+ float ta = static_cast<float>(tan(angle * radPerDegree));
+
+ NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
WillModify();
mType = SVG_TRANSFORM_SKEWX;
mAngle = angle;
NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
- NS_NewSVGMatrix(getter_AddRefs(mMatrix));
- nsCOMPtr<nsIDOMSVGMatrix> temp;
- mMatrix->SkewX(angle, getter_AddRefs(temp));
- mMatrix = temp;
+ mMatrix->SetA(1.0f);
+ mMatrix->SetB(0.0f);
+ mMatrix->SetC(ta);
+ mMatrix->SetD(1.0f);
+ mMatrix->SetE(0.0f);
+ mMatrix->SetF(0.0f);
NS_ADD_SVGVALUE_OBSERVER(mMatrix);
DidModify();
return NS_OK;
}
/* void setSkewY (in float angle); */
NS_IMETHODIMP nsSVGTransform::SetSkewY(float angle)
{
NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
+ float ta = static_cast<float>(tan(angle * radPerDegree));
+
+ NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
WillModify();
mType = SVG_TRANSFORM_SKEWY;
mAngle = angle;
NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
- NS_NewSVGMatrix(getter_AddRefs(mMatrix));
- nsCOMPtr<nsIDOMSVGMatrix> temp;
- mMatrix->SkewY(angle, getter_AddRefs(temp));
- mMatrix = temp;
+ mMatrix->SetA(1.0f);
+ mMatrix->SetB(ta);
+ mMatrix->SetC(0.0f);
+ mMatrix->SetD(1.0f);
+ mMatrix->SetE(0.0f);
+ mMatrix->SetF(0.0f);
NS_ADD_SVGVALUE_OBSERVER(mMatrix);
DidModify();
return NS_OK;
}
--- a/content/svg/content/test/test_transform.xhtml
+++ b/content/svg/content/test/test_transform.xhtml
@@ -19,16 +19,23 @@ https://bugzilla.mozilla.org/show_bug.cg
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
+var tolerance = 1 / 65535;
+
+function isequal( value, expected, tolerance )
+{
+ ok(Math.abs(value - expected) < tolerance, 'matrix value expected:' +expected + ' actual:' + value);
+}
+
function run()
{
var g, svg, t, m, m2;
svg = $('svg');
g = $('g');
t = g.transform.baseVal.getItem(0);
@@ -75,16 +82,59 @@ function run()
is(m.a, 1, 'm.a for matrix');
is(m.b, 2, 'm.b for matrix');
is(m.c, 3, 'm.c for matrix');
is(m.d, 4, 'm.d for matrix');
is(m.e, 5, 'm.e for matrix');
is(m.f, 6, 'm.f for matrix');
is(t.angle, 0, 't.angle for matrix');
+ // set the SVGTransform to be a translate() then convert to a matrix
+ t.setTranslate(0, 0);
+ m.a = 2;
+
+ // test that the SVGTransform now reflects the matrix value
+ is(t.type, SVGTransform.SVG_TRANSFORM_MATRIX, 't.type for matrix');
+
+ // set the SVGTransform to be a rotate()
+ t.setRotate(90, 0, 0);
+
+ // test that the SVGTransform now reflects the matrix value
+ is(t.type, SVGTransform.SVG_TRANSFORM_ROTATE, 't.type for rotate');
+ isequal(m.a, Math.cos(Math.PI/2), tolerance);
+ isequal(m.b, Math.sin(Math.PI/2), tolerance);
+ isequal(m.c, -Math.sin(Math.PI/2), tolerance);
+ isequal(m.d, Math.cos(Math.PI/2), tolerance);
+ isequal(m.e, 0, tolerance);
+ isequal(m.f, 0, tolerance);
+
+ // set the SVGTransform to be a skewX()
+ t.setSkewX(45);
+
+ // test that the SVGTransform now reflects the matrix value
+ is(t.type, SVGTransform.SVG_TRANSFORM_SKEWX, 't.type for skewx');
+ isequal(m.a, 1, tolerance);
+ isequal(m.b, 0, tolerance);
+ isequal(m.c, Math.tan(Math.PI/4), tolerance);
+ isequal(m.d, Math.tan(Math.PI/4), tolerance);
+ isequal(m.e, 0, tolerance);
+ isequal(m.f, 0, tolerance);
+
+ // set the SVGTransform to be a skewY()
+ t.setSkewY(45);
+
+ // test that the SVGTransform now reflects the matrix value
+ is(t.type, SVGTransform.SVG_TRANSFORM_SKEWY, 't.type for skewy');
+ isequal(m.a, Math.tan(Math.PI/4), tolerance);
+ isequal(m.b, Math.tan(Math.PI/4), tolerance);
+ isequal(m.c, 0, tolerance);
+ isequal(m.d, 1, tolerance);
+ isequal(m.e, 0, tolerance);
+ isequal(m.f, 0, tolerance);
+
SimpleTest.finish();
}
window.addEventListener("load", run, false);
]]>
</script>
</pre>