[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/asobj/flash/geom/Matrix_...
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] gnash ChangeLog server/asobj/flash/geom/Matrix_... |
Date: |
Mon, 09 Jun 2008 11:55:39 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Benjamin Wolsey <bwy> 08/06/09 11:55:38
Modified files:
. : ChangeLog
server/asobj/flash/geom: Matrix_as.cpp
testsuite/actionscript.all: Matrix.as
Log message:
* server/asobj/flash/geom/Matrix_as.{cpp,h}: implement concat
and
invert. Clean up and provide a helper function for filling
boost matrices with AS matrix properties.
* testsuite/actionscript.all: test Matrix more.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6861&r2=1.6862
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/flash/geom/Matrix_as.cpp?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/Matrix.as?cvsroot=gnash&r1=1.3&r2=1.4
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6861
retrieving revision 1.6862
diff -u -b -r1.6861 -r1.6862
--- ChangeLog 9 Jun 2008 11:20:57 -0000 1.6861
+++ ChangeLog 9 Jun 2008 11:55:37 -0000 1.6862
@@ -1,3 +1,10 @@
+2008-06-09 Benjamin Wolsey <address@hidden>
+
+ * server/asobj/flash/geom/Matrix_as.{cpp,h}: implement concat and
+ invert. Clean up and provide a helper function for filling
+ boost matrices with AS matrix properties.
+ * testsuite/actionscript.all: test Matrix more.
+
2008-06-09 Sandro Santilli <address@hidden>
* libbase/: Makefile.am, IOChannel.{cpp,h}: initial draft for a virtual
Index: server/asobj/flash/geom/Matrix_as.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/flash/geom/Matrix_as.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- server/asobj/flash/geom/Matrix_as.cpp 7 Jun 2008 16:27:16 -0000
1.8
+++ server/asobj/flash/geom/Matrix_as.cpp 9 Jun 2008 11:55:38 -0000
1.9
@@ -33,9 +33,9 @@
#include "Point_as.h" // Matrix needs to operate on Points.
#include <cmath>
-#include <limits>
#include <boost/numeric/ublas/matrix.hpp> // boost matrix
#include <boost/numeric/ublas/io.hpp>
+#include <boost/numeric/ublas/lu.hpp> // permutation matrix etc.
#include <sstream>
#include <memory> // std::auto_ptr
@@ -52,6 +52,8 @@
namespace gnash {
+class Matrix_as;
+
// Forward declarations
static as_value Matrix_clone(const fn_call& fn);
static as_value Matrix_concat(const fn_call& fn);
@@ -65,13 +67,8 @@
static as_value Matrix_toString(const fn_call& fn);
static as_value Matrix_transformPoint(const fn_call& fn);
static as_value Matrix_translate(const fn_call& fn);
-static as_value Matrix_a_getset(const fn_call& fn);
-static as_value Matrix_b_getset(const fn_call& fn);
-static as_value Matrix_c_getset(const fn_call& fn);
-static as_value Matrix_d_getset(const fn_call& fn);
-static as_value Matrix_tx_getset(const fn_call& fn);
-static as_value Matrix_ty_getset(const fn_call& fn);
-
+static void fillMatrix(boost::numeric::ublas::c_matrix<double, 3, 3>& matrix,
+ as_object* const matrixObject);
as_value Matrix_ctor(const fn_call& fn);
@@ -174,12 +171,67 @@
return as_value(ret.get());
}
+// A full, normal concatenation, so use full 3x3 matrices.
static as_value
Matrix_concat(const fn_call& fn)
{
boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
- UNUSED(ptr);
- LOG_ONCE( log_unimpl (__FUNCTION__) );
+
+ if (fn.nargs != 1)
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::ostringstream ss;
+ fn.dump_args(ss);
+ log_aserror("Matrix.concat(%s) needs exactly one argument; "
+ "%d were passed", ss.str(), fn.nargs);
+ );
+ return as_value();
+ }
+
+ // Matrix passed as argument:
+ const as_value& arg = fn.arg(0);
+
+ if ( ! arg.is_object() )
+ {
+ /// Isn't an object...
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::ostringstream ss;
+ fn.dump_args(ss);
+ log_aserror("Matrix.concat(%s): needs a Matrix object", ss.str());
+ );
+ return as_value();
+ }
+
+ as_object* obj = arg.to_object().get();
+ assert(obj);
+ if ( ! obj->instanceOf(getFlashGeomMatrixConstructor()) )
+ {
+ /// Isn't a point.
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::ostringstream ss;
+ fn.dump_args(ss);
+ log_aserror("Matrix.concat(%s): object must be a Matrix",
ss.str());
+ );
+ return as_value();
+ }
+
+ boost::numeric::ublas::c_matrix<double, 3, 3> concatMatrix;
+ fillMatrix(concatMatrix, obj);
+
+ // Current ('this') Matrix
+ boost::numeric::ublas::c_matrix<double, 3, 3> currentMatrix;
+ fillMatrix(currentMatrix, ptr.get());
+
+ currentMatrix = boost::numeric::ublas::prod(concatMatrix, currentMatrix);
+
+ // Set values of current matrix
+ ptr->set_member(NSV::PROP_A, as_value(currentMatrix(0, 0)));
+ ptr->set_member(NSV::PROP_B, as_value(currentMatrix(1, 0)));
+ ptr->set_member(NSV::PROP_C, as_value(currentMatrix(0, 1)));
+ ptr->set_member(NSV::PROP_D, as_value(currentMatrix(1, 1)));
+ ptr->set_member(NSV::PROP_TX, as_value(currentMatrix(0, 2)));
+ ptr->set_member(NSV::PROP_TY, as_value(currentMatrix(1, 2)));
+
return as_value();
}
@@ -265,14 +317,14 @@
transformMatrix(1, 1) = d.to_number();
// Construct the point
- boost::numeric::ublas::vector<double> point(2);
+ boost::numeric::ublas::c_vector<double, 2> point;
point(0) = x.to_number();
point(1) = y.to_number();
// Transform
point = boost::numeric::ublas::prod(point, transformMatrix);
- // Get an auto_ptr to a Point and keep alive.
+ // Get an auto_ptr to a Point and pretend to keep alive.
boost::intrusive_ptr<as_object> ret = init_Point_instance().release();
ret->set_member(NSV::PROP_X, point(0));
ret->set_member(NSV::PROP_Y, point(1));
@@ -285,7 +337,7 @@
///
/// | 1 0 0 |
/// | 0 1 0 |
-///
+///(| 0 0 1 |)
/// Returns void.
static as_value
Matrix_identity(const fn_call& fn)
@@ -306,8 +358,48 @@
Matrix_invert(const fn_call& fn)
{
boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
- UNUSED(ptr);
- LOG_ONCE( log_unimpl (__FUNCTION__) );
+
+ using namespace boost::numeric;
+
+ const double u = 0.0;
+ const double v = 0.0;
+ const double w = 1.0;
+
+ // This starts off as the identity matrix. If it's impossible to invert the
+ // matrix, this is returned.
+ ublas::c_matrix<double, 3, 3> inverseMatrix;
+ inverseMatrix(0, 0) = 1.0;
+ inverseMatrix(0, 1) = 0.0;
+ inverseMatrix(0, 2) = 0.0;
+ inverseMatrix(1, 0) = 0.0;
+ inverseMatrix(1, 1) = 1.0;
+ inverseMatrix(1, 2) = 0.0;
+ inverseMatrix(2, 0) = u;
+ inverseMatrix(2, 1) = v;
+ inverseMatrix(2, 2) = w;
+
+ // Get current matrix
+ ublas::c_matrix<double, 3, 3> currentMatrix;
+ fillMatrix(currentMatrix, ptr.get());
+
+ ublas::permutation_matrix<double> pm(currentMatrix.size1());
+
+ int valid = ublas::lu_factorize(currentMatrix, pm);
+
+ if( valid == 0 )
+ {
+ // We can invert.
+ boost::numeric::ublas::lu_substitute(currentMatrix, pm,
inverseMatrix);
+ }
+
+ // Returns the identity matrix if unsuccessful.
+ ptr->set_member(NSV::PROP_A, as_value(inverseMatrix(0, 0)));
+ ptr->set_member(NSV::PROP_B, as_value(inverseMatrix(1, 0)));
+ ptr->set_member(NSV::PROP_C, as_value(inverseMatrix(0, 1)));
+ ptr->set_member(NSV::PROP_D, as_value(inverseMatrix(1, 1)));
+ ptr->set_member(NSV::PROP_TX, as_value(inverseMatrix(0, 2)));
+ ptr->set_member(NSV::PROP_TY, as_value(inverseMatrix(1, 2)));
+
return as_value();
}
@@ -357,7 +449,7 @@
ptr->set_member(NSV::PROP_D, as_value(currentMatrix(1, 1)));
// Do rotation separately.
- boost::numeric::ublas::vector<double> translation(2);
+ boost::numeric::ublas::c_vector<double, 2> translation;
translation(0) = tx.to_number();
translation(1) = ty.to_number();
@@ -478,128 +570,37 @@
return as_value();
}
-static as_value
-Matrix_a_getset(const fn_call& fn)
-{
- boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
-
- if ( ! fn.nargs ) // getter
- {
- as_value a;
- ptr->get_member(NSV::PROP_A, &a);
- return a;
- }
- else // setter
- {
- as_value a = fn.arg(0);
- ptr->set_member(NSV::PROP_A, a);
- }
-
- return as_value();
-}
-
-static as_value
-Matrix_b_getset(const fn_call& fn)
-{
- boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
-
- if ( ! fn.nargs ) // getter
- {
- as_value b;
- ptr->get_member(NSV::PROP_B, &b);
- return b;
- }
- else // setter
- {
- as_value b = fn.arg(0);
- ptr->set_member(NSV::PROP_B, b);
- }
-
- return as_value();
-}
-static as_value
-Matrix_c_getset(const fn_call& fn)
+// A helper function to create a boost matrix from a Matrix object
+static void fillMatrix(boost::numeric::ublas::c_matrix<double, 3, 3>& matrix,
+ as_object* const matrixObject)
{
- boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
-
- if ( ! fn.nargs ) // getter
- {
- as_value c;
- ptr->get_member(NSV::PROP_C, &c);
- return c;
- }
- else // setter
- {
- as_value c = fn.arg(0);
- ptr->set_member(NSV::PROP_C, c);
- }
- return as_value();
-}
-
-static as_value
-Matrix_d_getset(const fn_call& fn)
-{
- boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
+ const double u = 0.0;
+ const double v = 0.0;
+ const double w = 1.0;
- if ( ! fn.nargs ) // getter
- {
- as_value d;
- ptr->get_member(NSV::PROP_D, &d);
- return d;
- }
- else // setter
- {
- as_value d = fn.arg(0);
- ptr->set_member(NSV::PROP_D, d);
- }
-
- return as_value();
-}
-
-static as_value
-Matrix_tx_getset(const fn_call& fn)
-{
- boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
-
- if ( ! fn.nargs ) // getter
- {
- as_value tx;
- ptr->get_member(NSV::PROP_TX, &tx);
- return tx;
- }
- else // setter
- {
- as_value tx = fn.arg(0);
- ptr->set_member(NSV::PROP_TX, tx);
- }
-
- return as_value();
-}
-
-static as_value
-Matrix_ty_getset(const fn_call& fn)
-{
- boost::intrusive_ptr<Matrix_as> ptr = ensureType<Matrix_as>(fn.this_ptr);
+ as_value a, b, c, d, tx, ty;
- if ( ! fn.nargs ) // getter
- {
- as_value ty;
- ptr->get_member(NSV::PROP_TY, &ty);
- return ty;
- }
- else // setter
- {
- as_value ty = fn.arg(0);
- ptr->set_member(NSV::PROP_TY, ty);
- }
+ matrixObject->get_member(NSV::PROP_A, &a);
+ matrixObject->get_member(NSV::PROP_B, &b);
+ matrixObject->get_member(NSV::PROP_C, &c);
+ matrixObject->get_member(NSV::PROP_D, &d);
+ matrixObject->get_member(NSV::PROP_TX, &tx);
+ matrixObject->get_member(NSV::PROP_TY, &ty);
+
+ matrix(0, 0) = a.to_number();
+ matrix(0, 1) = c.to_number();
+ matrix(0, 2) = tx.to_number();
+ matrix(1, 0) = b.to_number();
+ matrix(1, 1) = d.to_number();
+ matrix(1, 2) = ty.to_number();
+ matrix(2, 0) = u;
+ matrix(2, 1) = v;
+ matrix(2, 2) = w;
- return as_value();
}
-
-
as_value
Matrix_ctor(const fn_call& fn)
{
Index: testsuite/actionscript.all/Matrix.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/Matrix.as,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- testsuite/actionscript.all/Matrix.as 7 Jun 2008 12:44:26 -0000
1.3
+++ testsuite/actionscript.all/Matrix.as 9 Jun 2008 11:55:38 -0000
1.4
@@ -20,7 +20,7 @@
// compile this test case with Ming makeswf, and then
// execute it like this gnash -1 -r 0 -v out.swf
-rcsid="$Id: Matrix.as,v 1.3 2008/06/07 12:44:26 bwy Exp $";
+rcsid="$Id: Matrix.as,v 1.4 2008/06/09 11:55:38 bwy Exp $";
// There are lots of floating point calculations here. Comparing them
@@ -41,7 +41,6 @@
Matrix = flash.geom.Matrix;
check_equals(typeof(Matrix), 'function');
check_equals(typeof(Matrix.prototype), 'object');
-// TODO: check prototypes properties
check(Matrix.prototype.hasOwnProperty('identity'));
check(Matrix.prototype.hasOwnProperty('rotate'));
check(Matrix.prototype.hasOwnProperty('concat'));
@@ -54,6 +53,12 @@
check(Matrix.prototype.hasOwnProperty('createGradientBox'));
check(Matrix.prototype.hasOwnProperty('invert'));
check(Matrix.prototype.hasOwnProperty('toString'));
+check(!Matrix.prototype.hasOwnProperty('a'));
+check(!Matrix.prototype.hasOwnProperty('b'));
+check(!Matrix.prototype.hasOwnProperty('c'));
+check(!Matrix.prototype.hasOwnProperty('d'));
+check(!Matrix.prototype.hasOwnProperty('tx'));
+check(!Matrix.prototype.hasOwnProperty('ty'));
//-------------------------------------------------------------
// Test constructor
@@ -130,23 +135,19 @@
m1.scale(32, -3.4);
check_equals(m1.toString(), "(a=32, b=-6.8, c=96, d=-13.6, tx=160, ty=-20.4)");
-
+// Do not change m1; it's used later to test concat!
m2 = new Matrix();
m2.rotate(Math.PI);
// PP: "(a=-1, b=1.22460635382238e-16, c=-1.22460635382238e-16, d=-1, tx=0,
ty=0) ");
-// Can we risk it?
check_equals (m2.a, -1);
check (m2.b < 0.00000000001 && m2.b > -0.000000000001);
check (m2.c < 0.00000000001 && m2.c > -0.000000000001);
check (m2.d == -1);
-// Probably okay:
check (m2.tx == 0);
check (m2.ty == 0);
-m2.rotate();
-
m2 = new Matrix();
m2.rotate(1.3);
@@ -156,7 +157,7 @@
check (m2.d < 0.26749883 && m2.d > 0.26749881);
check (m2.tx == 0);
check (m2.ty == 0);
-
+// Do not change m2 after this; it's used later to test concat!
///
/// Test deltaTransform of Point
@@ -167,18 +168,34 @@
check_equals(typeof(newP), "object");
check_equals(newP.toString(), "(x=31.2567984378314, y=26.6085052458191)");
-
+// Scale
m3 = new Matrix(2, 0, 0, 2, 100, 100);
m3.scale(3, 4);
check_equals(m3.toString(), "(a=6, b=0, c=0, d=8, tx=300, ty=400)");
+// Do not change m3; it is used to test invert!
// Test clone
m4 = m3.clone();
check_equals(m4.toString(), "(a=6, b=0, c=0, d=8, tx=300, ty=400)");
+// Do not change m4; it's used later to test concat!
+
// Test invert
m3.invert();
-xcheck_equals(m3.toString(), "(a=0.166666666666667, b=0, c=0, d=0.125, tx=-50,
ty=-50)");
+check_equals(m3.toString(), "(a=0.166666666666667, b=0, c=0, d=0.125, tx=-50,
ty=-50)");
+
+// Invalid inverse
+m6 = new Matrix(4, 5, 44, 55, 2, 4);
+check_equals(m6.toString(), "(a=4, b=5, c=44, d=55, tx=2, ty=4)");
+m6.invert();
+check_equals(m6.toString(), "(a=1, b=0, c=0, d=1, tx=0, ty=0)");
+
+// Valid inverse.
+m6 = new Matrix(4, 5, 0, 5, 2, 3);
+check_equals(m6.toString(), "(a=4, b=5, c=0, d=5, tx=2, ty=3)");
+m6.invert();
+check_equals(m6.toString(), "(a=0.25, b=-0.25, c=0, d=0.2, tx=-0.5, ty=-0.1)");
+
// Rotation applies to translation
m3 = new Matrix(1, 0, 0, 1, 2, 2);
@@ -199,7 +216,12 @@
check_equals(m3.tx.toString(), "0");
check_equals(m3.ty.toString(), "0");
-
+// m4 is still interesting
+m4.concat(m1);
+check_equals(m4.toString(), "(a=192, b=-40.8, c=768, d=-108.8, tx=48160,
ty=-7500.4)");
+m4.concat(m2);
+// Works for me.
+check_equals(m4.toString(), "(a=90.6729490609422, b=174.089219392218,
c=310.274230957074, d=710.908813846049, tx=20109.8154004632,
ty=44398.6139954762)");
//-------------------------------------------------------------
// END OF TEST