Add SkMatrix44 constructor that allows user to control the initialization
method.  Preliminary results using Chromium's cc_perftests
show that we can avoid almost half of the default constructors from
redundantly/unnecessarily initializing the matrix to identity.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@6742 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/utils/SkMatrix44.h b/include/utils/SkMatrix44.h
index af61a11..4789e7e 100644
--- a/include/utils/SkMatrix44.h
+++ b/include/utils/SkMatrix44.h
@@ -103,6 +103,17 @@
 
 class SK_API SkMatrix44 {
 public:
+
+    enum Uninitialized_Constructor {
+        kUninitialized_Constructor
+    };
+    enum Identity_Constructor {
+        kIdentity_Constructor
+    };
+
+    SkMatrix44(Uninitialized_Constructor) { }
+    SkMatrix44(Identity_Constructor) { this->setIdentity(); }
+
     SkMatrix44() { this->setIdentity(); }
     SkMatrix44(const SkMatrix44&);
     SkMatrix44(const SkMatrix44& a, const SkMatrix44& b);
diff --git a/tests/Matrix44Test.cpp b/tests/Matrix44Test.cpp
index 9dc77c2..794c935 100644
--- a/tests/Matrix44Test.cpp
+++ b/tests/Matrix44Test.cpp
@@ -77,6 +77,35 @@
     return 0 == (value & ~mask);
 }
 
+static void test_constructor(skiatest::Reporter* reporter) {
+    // Allocate a matrix on the heap
+    SkMatrix44* placeholderMatrix = new SkMatrix44();
+    for (int row = 0; row < 4; ++row) {
+        for (int col = 0; col < 4; ++col) {
+            placeholderMatrix->setDouble(row, col, row * col);
+        }
+    }
+
+    // Use placement-new syntax to trigger the constructor on top of the heap
+    // address we already initialized. This allows us to check that the
+    // constructor did avoid initializing the matrix contents.
+    SkMatrix44* testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kUninitialized_Constructor);
+    REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix);
+    REPORTER_ASSERT(reporter, !testMatrix->isIdentity());
+    for (int row = 0; row < 4; ++row) {
+        for (int col = 0; col < 4; ++col) {
+            REPORTER_ASSERT(reporter, nearly_equal_double(row * col, testMatrix->getDouble(row, col)));
+        }
+    }
+
+    // Verify that kIdentity_Constructor really does initialize to an identity matrix.
+    testMatrix = 0;
+    testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kIdentity_Constructor); 
+    REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix);
+    REPORTER_ASSERT(reporter, testMatrix->isIdentity());
+    REPORTER_ASSERT(reporter, *testMatrix == SkMatrix44::I());
+}
+
 static void test_translate(skiatest::Reporter* reporter) {
     SkMatrix44 mat, inverse;
 
@@ -396,6 +425,7 @@
         test_common_angles(reporter);
     }
 
+    test_constructor(reporter);
     test_gettype(reporter);
     test_determinant(reporter);
     test_transpose(reporter);