SkRecord: make culling work if SkRecordAnnotateCullingPairs is called.

  - Allow stateful functors; allow visit()/mutate() at a given index; add count().
  - Annotate cull push/pop pairs on the PushCull records.  (tested)
  - Use those annotations to skip ahead in SkRecordDraw.   (not yet tested beyond dm --skr)
  - Make SkRecordDraw a function, move its implementation to a .cpp.

BUG=skia:2378
R=fmalita@chromium.org, mtklein@google.com

Author: mtklein@chromium.org

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14101 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/RecordCullingTest.cpp b/tests/RecordCullingTest.cpp
new file mode 100644
index 0000000..c6711c6
--- /dev/null
+++ b/tests/RecordCullingTest.cpp
@@ -0,0 +1,41 @@
+#include "Test.h"
+
+#include "SkRecord.h"
+#include "SkRecordCulling.h"
+#include "SkRecorder.h"
+#include "SkRecords.h"
+
+struct PushCullScanner {
+    template <typename T> void operator()(const T&) {}
+
+    SkTDArray<unsigned> fPopOffsets;
+};
+
+template <> void PushCullScanner::operator()(const SkRecords::PushCull& record) {
+    *fPopOffsets.append() = record.popOffset;
+}
+
+
+DEF_TEST(RecordCulling, r) {
+    SkRecord record;
+    SkRecorder recorder(&record, 1920, 1080);
+
+    recorder.drawRect(SkRect::MakeWH(1000, 10000), SkPaint());
+
+    recorder.pushCull(SkRect::MakeWH(100, 100));
+        recorder.drawRect(SkRect::MakeWH(10, 10), SkPaint());
+        recorder.drawRect(SkRect::MakeWH(30, 30), SkPaint());
+        recorder.pushCull(SkRect::MakeWH(5, 5));
+            recorder.drawRect(SkRect::MakeWH(1, 1), SkPaint());
+        recorder.popCull();
+    recorder.popCull();
+
+    SkRecordAnnotateCullingPairs(&record);
+
+    PushCullScanner scan;
+    record.visit(scan);
+
+    REPORTER_ASSERT(r, 2 == scan.fPopOffsets.count());
+    REPORTER_ASSERT(r, 6 == scan.fPopOffsets[0]);
+    REPORTER_ASSERT(r, 2 == scan.fPopOffsets[1]);
+}
diff --git a/tests/RecordTest.cpp b/tests/RecordTest.cpp
index 1214b1a..58e5de1 100644
--- a/tests/RecordTest.cpp
+++ b/tests/RecordTest.cpp
@@ -3,18 +3,20 @@
 #include "SkRecord.h"
 #include "SkRecords.h"
 
-// Adds the area of any DrawRect command it sees into area.
+// Sums the area of any DrawRect command it sees.
 class AreaSummer {
 public:
-    explicit AreaSummer(int* area) : fArea(area) {}
+    AreaSummer() : fArea(0) {}
 
     template <typename T> void operator()(const T&) { }
 
+    int area() const { return fArea; }
+
 private:
-    int* fArea;
+    int fArea;
 };
 template <> void AreaSummer::operator()(const SkRecords::DrawRect& record) {
-    *fArea += (int) (record.rect.width() * record.rect.height());
+    fArea += (int) (record.rect.width() * record.rect.height());
 }
 
 // Scales out the bottom-right corner of any DrawRect command it sees by 2x.
@@ -36,13 +38,15 @@
     SkNEW_PLACEMENT_ARGS(record.append<SkRecords::DrawRect>(), SkRecords::DrawRect, (rect, paint));
 
     // Its area should be 100.
-    int area = 0;
-    record.visit(AreaSummer(&area));
-    REPORTER_ASSERT(r, area == 100);
+    AreaSummer summer;
+    record.visit(summer);
+    REPORTER_ASSERT(r, summer.area() == 100);
 
-    // Scale 2x.  Now it's area should be 400.
-    record.mutate(Stretch());
-    area = 0;
-    record.visit(AreaSummer(&area));
-    REPORTER_ASSERT(r, area == 400);
+    // Scale 2x.
+    Stretch stretch;
+    record.mutate(stretch);
+
+    // Now its area should be 100 + 400.
+    record.visit(summer);
+    REPORTER_ASSERT(r, summer.area() == 500);
 }
diff --git a/tests/RecorderTest.cpp b/tests/RecorderTest.cpp
index 4f8e357..3c7b008 100644
--- a/tests/RecorderTest.cpp
+++ b/tests/RecorderTest.cpp
@@ -8,17 +8,19 @@
 static const int kRecordTypes = SK_RECORD_TYPES(COUNT);
 #undef COUNT
 
-// Tallies the types of commands it sees into histogram.
+// Tallies the types of commands it sees into a histogram.
 class Tally {
 public:
-    explicit Tally(int histogram[kRecordTypes]) : fHistogram(histogram) {}
+    Tally() { sk_bzero(&fHistogram, sizeof(fHistogram)); }
 
-    template <typename T> void operator()(const T&) {
-        ++fHistogram[T::kType];
-    }
+    template <typename T>
+    void operator()(const T&) { ++fHistogram[T::kType]; }
+
+    template <typename T>
+    int count() const { return fHistogram[T::kType]; }
 
 private:
-    int* fHistogram;
+    int fHistogram[kRecordTypes];
 };
 
 DEF_TEST(Recorder, r) {
@@ -27,10 +29,8 @@
 
     recorder.drawRect(SkRect::MakeWH(10, 10), SkPaint());
 
-    int histogram[kRecordTypes];
-    sk_bzero(&histogram, sizeof(histogram));
+    Tally tally;
+    record.visit(tally);
 
-    record.visit(Tally(histogram));
-
-    REPORTER_ASSERT(r, 1 == histogram[SkRecords::DrawRect::kType]);
+    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawRect>());
 }