gnash-commit
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]