Add SkMatrix44::setColMajord, etc.

We have accessors for efficiently getting the matirx data, and it would be nice
if we had similar methods for setting the matrix entries.

Review URL: https://codereview.appspot.com/6851063

git-svn-id: http://skia.googlecode.com/svn/trunk@6494 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/utils/SkMatrix44.h b/include/utils/SkMatrix44.h
index a046a07..e1de7c7 100644
--- a/include/utils/SkMatrix44.h
+++ b/include/utils/SkMatrix44.h
@@ -126,11 +126,26 @@
         this->set(row, col, SkDoubleToMScalar(value));
     }
 
+    /** These methods allow one to efficiently read matrix entries into an
+     *  array. The given array must have room for exactly 16 entries. Whenever
+     *  possible, they will try to use memcpy rather than an entry-by-entry
+     *  copy.
+     */
     void asColMajorf(float[]) const;
     void asColMajord(double[]) const;
     void asRowMajorf(float[]) const;
     void asRowMajord(double[]) const;
 
+    /** These methods allow one to efficiently set all matrix entries from an
+     *  array. The given array must have room for exactly 16 entries. Whenever
+     *  possible, they will try to use memcpy rather than an entry-by-entry
+     *  copy.
+     */
+    void setColMajorf(const float[]);
+    void setColMajord(const double[]);
+    void setRowMajorf(const float[]);
+    void setRowMajord(const double[]);
+
     bool isIdentity() const;
     void setIdentity();
     void reset() { this->setIdentity();}
diff --git a/src/utils/SkMatrix44.cpp b/src/utils/SkMatrix44.cpp
index 0e7ad16..42c38f7 100644
--- a/src/utils/SkMatrix44.cpp
+++ b/src/utils/SkMatrix44.cpp
@@ -82,6 +82,52 @@
     }
 }
 
+void SkMatrix44::setColMajorf(const float src[]) {
+    SkMScalar* dst = &fMat[0][0];
+#ifdef SK_MSCALAR_IS_DOUBLE
+    for (int i = 0; i < 16; ++i) {
+        dst[i] = SkMScalarToFloat(src[i]);
+    }
+#elif defined SK_MSCALAR_IS_FLOAT
+    memcpy(dst, src, 16 * sizeof(float));
+#endif
+}
+
+void SkMatrix44::setColMajord(const double src[]) {
+    SkMScalar* dst = &fMat[0][0];
+#ifdef SK_MSCALAR_IS_DOUBLE
+    memcpy(dst, src, 16 * sizeof(double));
+#elif defined SK_MSCALAR_IS_FLOAT
+    for (int i = 0; i < 16; ++i) {
+        dst[i] = SkMScalarToDouble(src[i]);
+    }
+#endif
+}
+
+void SkMatrix44::setRowMajorf(const float src[]) {
+    SkMScalar* dst = &fMat[0][0];
+    for (int i = 0; i < 4; ++i) {
+        dst[0] = SkMScalarToFloat(src[0]);
+        dst[4] = SkMScalarToFloat(src[1]);
+        dst[8] = SkMScalarToFloat(src[2]);
+        dst[12] = SkMScalarToFloat(src[3]);
+        src += 4;
+        dst += 1;
+    }
+}
+
+void SkMatrix44::setRowMajord(const double src[]) {
+    SkMScalar* dst = &fMat[0][0];
+    for (int i = 0; i < 4; ++i) {
+        dst[0] = SkMScalarToDouble(src[0]);
+        dst[4] = SkMScalarToDouble(src[1]);
+        dst[8] = SkMScalarToDouble(src[2]);
+        dst[12] = SkMScalarToDouble(src[3]);
+        src += 4;
+        dst += 1;
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkMatrix44::isIdentity() const {
diff --git a/tests/Matrix44Test.cpp b/tests/Matrix44Test.cpp
index 782b51e..ea6a56f 100644
--- a/tests/Matrix44Test.cpp
+++ b/tests/Matrix44Test.cpp
@@ -123,57 +123,80 @@
 }
 
 static void test_determinant(skiatest::Reporter* reporter) {
-  SkMatrix44 a;
-  REPORTER_ASSERT(reporter, nearly_equal_double(1, a.determinant()));
-  a.set(1, 1, SkFloatToMScalar(2));
-  REPORTER_ASSERT(reporter, nearly_equal_double(2, a.determinant()));
-  SkMatrix44 b;
-  REPORTER_ASSERT(reporter, a.invert(&b));
-  REPORTER_ASSERT(reporter, nearly_equal_double(0.5, b.determinant()));
-  SkMatrix44 c = b = a;
-  c.set(0, 1, SkFloatToMScalar(4));
-  b.set(1, 0, SkFloatToMScalar(4));
-  REPORTER_ASSERT(reporter,
-                  nearly_equal_double(a.determinant(),
-                                      b.determinant()));
-  SkMatrix44 d = a;
-  d.set(0, 0, SkFloatToMScalar(8));
-  REPORTER_ASSERT(reporter, nearly_equal_double(16, d.determinant()));
+    SkMatrix44 a;
+    REPORTER_ASSERT(reporter, nearly_equal_double(1, a.determinant()));
+    a.set(1, 1, SkFloatToMScalar(2));
+    REPORTER_ASSERT(reporter, nearly_equal_double(2, a.determinant()));
+    SkMatrix44 b;
+    REPORTER_ASSERT(reporter, a.invert(&b));
+    REPORTER_ASSERT(reporter, nearly_equal_double(0.5, b.determinant()));
+    SkMatrix44 c = b = a;
+    c.set(0, 1, SkFloatToMScalar(4));
+    b.set(1, 0, SkFloatToMScalar(4));
+    REPORTER_ASSERT(reporter,
+                    nearly_equal_double(a.determinant(),
+                                        b.determinant()));
+    SkMatrix44 d = a;
+    d.set(0, 0, SkFloatToMScalar(8));
+    REPORTER_ASSERT(reporter, nearly_equal_double(16, d.determinant()));
 
-  SkMatrix44 e = a;
-  e.postConcat(d);
-  REPORTER_ASSERT(reporter, nearly_equal_double(32, e.determinant()));
-  e.set(0, 0, SkFloatToMScalar(0));
-  REPORTER_ASSERT(reporter, nearly_equal_double(0, e.determinant()));
+    SkMatrix44 e = a;
+    e.postConcat(d);
+    REPORTER_ASSERT(reporter, nearly_equal_double(32, e.determinant()));
+    e.set(0, 0, SkFloatToMScalar(0));
+    REPORTER_ASSERT(reporter, nearly_equal_double(0, e.determinant()));
 }
 
 static void test_transpose(skiatest::Reporter* reporter) {
-  SkMatrix44 a;
-  SkMatrix44 b;
+    SkMatrix44 a;
+    SkMatrix44 b;
 
-  int i = 0;
-  for (int row = 0; row < 4; ++row) {
-    for (int col = 0; col < 4; ++col) {
-      a.setDouble(row, col, i);
-      b.setDouble(col, row, i++);
+    int i = 0;
+    for (int row = 0; row < 4; ++row) {
+        for (int col = 0; col < 4; ++col) {
+            a.setDouble(row, col, i);
+            b.setDouble(col, row, i++);
+        }
     }
-  }
 
-  a.transpose();
-  REPORTER_ASSERT(reporter, nearly_equal(a, b));
+    a.transpose();
+    REPORTER_ASSERT(reporter, nearly_equal(a, b));
 }
 
 static void test_get_set_double(skiatest::Reporter* reporter) {
-  SkMatrix44 a;
-  for (int row = 0; row < 4; ++row) {
-    for (int col = 0; col < 4; ++col) {
-      a.setDouble(row, col, 3.141592653589793);
-      REPORTER_ASSERT(reporter, nearly_equal_double(3.141592653589793,
-                                                    a.getDouble(row, col)));
-      a.setDouble(row, col, 0);
-      REPORTER_ASSERT(reporter, nearly_equal_double(0, a.getDouble(row, col)));
+    SkMatrix44 a;
+    for (int row = 0; row < 4; ++row) {
+        for (int col = 0; col < 4; ++col) {
+            a.setDouble(row, col, 3.141592653589793);
+            REPORTER_ASSERT(reporter,
+                            nearly_equal_double(3.141592653589793,
+                                                a.getDouble(row, col)));
+            a.setDouble(row, col, 0);
+            REPORTER_ASSERT(reporter,
+                            nearly_equal_double(0, a.getDouble(row, col)));
+        }
     }
-  }
+}
+
+static void test_set_row_col_major(skiatest::Reporter* reporter) {
+    SkMatrix44 a, b, c, d;
+    for (int row = 0; row < 4; ++row)
+        for (int col = 0; col < 4; ++col)
+            a.setDouble(row, col, row * 4 + col);
+    double bufferd[16];
+    float bufferf[16];
+    a.asColMajord(bufferd);
+    b.setColMajord(bufferd);
+    REPORTER_ASSERT(reporter, nearly_equal(a, b));
+    b.setRowMajord(bufferd);
+    b.transpose();
+    REPORTER_ASSERT(reporter, nearly_equal(a, b));
+    a.asColMajorf(bufferf);
+    b.setColMajorf(bufferf);
+    REPORTER_ASSERT(reporter, nearly_equal(a, b));
+    b.setRowMajorf(bufferf);
+    b.transpose();
+    REPORTER_ASSERT(reporter, nearly_equal(a, b));
 }
 
 static void TestMatrix44(skiatest::Reporter* reporter) {