SkRecord bug fixes

Optional arguments to SkCanvas calls leaked refs (but not memory) because we
didn't destruct the optional objects (really, just SkPaint: other optional args
are all POD).  This adds Optional and PODArray, where Optional makes sure to
call the destructor.

I overlooked that SkPictureRecord really does call paint.computeFastBounds().
Do the same in SkRecordDraw.

BUG=skia:2378
R=reed@google.com, mtklein@google.com, tomhudson@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/235983015

git-svn-id: http://skia.googlecode.com/svn/trunk@14197 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/RecorderTest.cpp b/tests/RecorderTest.cpp
index 34b3f2c..570bce8 100644
--- a/tests/RecorderTest.cpp
+++ b/tests/RecorderTest.cpp
@@ -11,6 +11,8 @@
 #include "SkRecorder.h"
 #include "SkRecords.h"
 
+#include "SkEmptyShader.h"
+
 #define COUNT(T) + 1
 static const int kRecordTypes = SK_RECORD_TYPES(COUNT);
 #undef COUNT
@@ -41,3 +43,23 @@
 
     REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawRect>());
 }
+
+// Regression test for leaking refs held by optional arguments.
+DEF_TEST(Recorder_RefLeaking, r) {
+    // We use SaveLayer to test:
+    //   - its SkRect argument is optional and SkRect is POD.  Just testing that that works.
+    //   - its SkPaint argument is optional and SkPaint is not POD.  The bug was here.
+
+    SkRect bounds;
+    SkPaint paint;
+    paint.setShader(SkNEW(SkEmptyShader))->unref();
+
+    REPORTER_ASSERT(r, paint.getShader()->unique());
+    {
+        SkRecord record;
+        SkRecorder recorder(SkRecorder::kWriteOnly_Mode, &record, 1920, 1080);
+        recorder.saveLayer(&bounds, &paint);
+        REPORTER_ASSERT(r, !paint.getShader()->unique());
+    }
+    REPORTER_ASSERT(r, paint.getShader()->unique());
+}