Moved SkPictureContentInfo into its own file.  It now tracks the number of skia
operations (maybe, I'm not 100% sure I'm doing this right yet)  and the number
of text draws.  I also moved some of the gpu logic out of SkPictureRecord and
into SkPictureContentInfo,

http://code.google.com/p/chromium/issues/detail?id=396908
http://code.google.com/p/chromium/issues/detail?id=397198
http://code.google.com/p/chromium/issues/detail?id=399728

BUG=396908
R=nduca@chromium.org, mtklein@chromium.org, robertphillips@google.com, mtklein@google.com

Author: hendrikw@chromium.org

Review URL: https://codereview.chromium.org/435093003
diff --git a/gyp/core.gypi b/gyp/core.gypi
index da43a05..60d7859 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -130,6 +130,8 @@
         '<(skia_src_path)/core/SkPathMeasure.cpp',
         '<(skia_src_path)/core/SkPathRef.cpp',
         '<(skia_src_path)/core/SkPicture.cpp',
+        '<(skia_src_path)/core/SkPictureContentInfo.cpp',
+        '<(skia_src_path)/core/SkPictureContentInfo.h',
         '<(skia_src_path)/core/SkPictureData.cpp',
         '<(skia_src_path)/core/SkPictureData.h',
         '<(skia_src_path)/core/SkPictureFlat.cpp',
diff --git a/src/core/SkPictureContentInfo.cpp b/src/core/SkPictureContentInfo.cpp
new file mode 100644
index 0000000..8185d85
--- /dev/null
+++ b/src/core/SkPictureContentInfo.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkPaint.h"
+#include "SkPathEffect.h"
+#include "SkPictureContentInfo.h"
+
+bool SkPictureContentInfo::suitableForGpuRasterization(GrContext* context, const char **reason,
+                                                       int sampleCount) const {
+    // TODO: the heuristic used here needs to be refined
+    static const int kNumPaintWithPathEffectUsesTol = 1;
+    static const int kNumAAConcavePaths = 5;
+
+    SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths);
+
+    int numNonDashedPathEffects = fNumPaintWithPathEffectUses -
+                                  fNumFastPathDashEffects;
+
+    bool suitableForDash = (0 == fNumPaintWithPathEffectUses) ||
+                           (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
+                            && 0 == sampleCount);
+
+    bool ret = suitableForDash &&
+                    (fNumAAConcavePaths - fNumAAHairlineConcavePaths)
+                    < kNumAAConcavePaths;
+    if (!ret && NULL != reason) {
+        if (!suitableForDash) {
+            if (0 != sampleCount) {
+                *reason = "Can't use multisample on dash effect.";
+            } else {
+                *reason = "Too many non dashed path effects.";
+            }
+        } else if ((fNumAAConcavePaths - fNumAAHairlineConcavePaths)
+                    >= kNumAAConcavePaths) {
+            *reason = "Too many anti-aliased concave paths.";
+        } else {
+            *reason = "Unknown reason for GPU unsuitability.";
+        }
+    }
+    return ret;
+}
+
+void SkPictureContentInfo::onDrawPoints(size_t count, const SkPaint& paint) {
+    if (paint.getPathEffect() != NULL) {
+        SkPathEffect::DashInfo info;
+        SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info);
+        if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() &&
+            SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
+            ++fNumFastPathDashEffects;
+        }
+    }
+}
+
+void SkPictureContentInfo::onDrawPath(const SkPath& path, const SkPaint& paint) {
+    if (paint.isAntiAlias() && !path.isConvex()) {
+        ++fNumAAConcavePaths;
+
+        if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
+            ++fNumAAHairlineConcavePaths;
+        }
+    }
+}
+
+void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) {
+    if (NULL != paint && NULL != paint->getPathEffect()) {
+        ++fNumPaintWithPathEffectUses;
+    }
+}
+
+void SkPictureContentInfo::set(const SkPictureContentInfo& src) {
+    fNumOperations = src.fNumOperations;
+    fNumTexts = src.fNumTexts;
+    fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
+    fNumFastPathDashEffects = src.fNumFastPathDashEffects;
+    fNumAAConcavePaths = src.fNumAAConcavePaths;
+    fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
+}
+
+void SkPictureContentInfo::reset() {
+    fNumOperations = 0;
+    fNumTexts = 0;
+    fNumPaintWithPathEffectUses = 0;
+    fNumFastPathDashEffects = 0;
+    fNumAAConcavePaths = 0;
+    fNumAAHairlineConcavePaths = 0;
+}
+
+void SkPictureContentInfo::swap(SkPictureContentInfo* other) {
+    SkTSwap(fNumOperations, other->fNumOperations);
+    SkTSwap(fNumTexts, other->fNumTexts);
+    SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
+    SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
+    SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
+    SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
+}
diff --git a/src/core/SkPictureContentInfo.h b/src/core/SkPictureContentInfo.h
new file mode 100644
index 0000000..cfeedcf
--- /dev/null
+++ b/src/core/SkPictureContentInfo.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureContentInfo_DEFINED
+#define SkPictureContentInfo_DEFINED
+
+class GrContext;
+
+class SkPictureContentInfo {
+public:
+    SkPictureContentInfo() { this->reset(); }
+    SkPictureContentInfo(const SkPictureContentInfo& src) { this->set(src); }
+
+    int numOperations() const { return fNumOperations; }
+    bool hasText() const { return fNumTexts > 0; }
+    bool suitableForGpuRasterization(GrContext* context, const char **reason,
+                                     int sampleCount) const;
+
+    void addOperation() { ++fNumOperations; }
+
+    void onDrawPoints(size_t count, const SkPaint& paint);
+    void onDrawPath(const SkPath& path, const SkPaint& paint);
+    void onAddPaintPtr(const SkPaint* paint);
+    void onDrawText() { ++fNumTexts; }
+
+    void set(const SkPictureContentInfo& src);
+    void reset();
+    void swap(SkPictureContentInfo* other);
+
+private:
+    // Raw count of operations in the picture
+    int fNumOperations;
+    // Count of all forms of drawText
+    int fNumTexts;
+
+    // This field is incremented every time a paint with a path effect is
+    // used (i.e., it is not a de-duplicated count)
+    int fNumPaintWithPathEffectUses;
+    // This field is incremented every time a paint with a path effect that is
+    // dashed, we are drawing a line, and we can use the gpu fast path
+    int fNumFastPathDashEffects;
+    // This field is incremented every time an anti-aliased drawPath call is
+    // issued with a concave path
+    int fNumAAConcavePaths;
+    // This field is incremented every time a drawPath call is
+    // issued for a hairline stroked concave path.
+    int fNumAAHairlineConcavePaths;
+};
+
+#endif
diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
index 1553462..123c414 100644
--- a/src/core/SkPictureData.cpp
+++ b/src/core/SkPictureData.cpp
@@ -669,37 +669,8 @@
 
 #if SK_SUPPORT_GPU
 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
-                                                    int sampleCount) const {
-    // TODO: the heuristic used here needs to be refined
-    static const int kNumPaintWithPathEffectUsesTol = 1;
-    static const int kNumAAConcavePaths = 5;
-
-    SkASSERT(fContentInfo.numAAHairlineConcavePaths() <= fContentInfo.numAAConcavePaths());
-
-    int numNonDashedPathEffects = fContentInfo.numPaintWithPathEffectUses() -
-                                  fContentInfo.numFastPathDashEffects();
-
-    bool suitableForDash = (0 == fContentInfo.numPaintWithPathEffectUses()) ||
-                           (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
-                            && 0 == sampleCount);
-
-    bool ret = suitableForDash &&
-                    (fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
-                    < kNumAAConcavePaths;
-    if (!ret && NULL != reason) {
-        if (!suitableForDash) {
-            if (0 != sampleCount) {
-                *reason = "Can't use multisample on dash effect.";
-            } else {
-                *reason = "Too many non dashed path effects.";
-            }
-        } else if ((fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
-                    >= kNumAAConcavePaths)
-            *reason = "Too many anti-aliased concave paths.";
-        else
-            *reason = "Unknown reason for GPU unsuitability.";
-    }
-    return ret;
+                                                int sampleCount) const {
+    return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
 }
 
 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index 6ea0b18..c1cfba3 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -11,6 +11,7 @@
 #include "SkBitmap.h"
 #include "SkPathHeap.h"
 #include "SkPicture.h"
+#include "SkPictureContentInfo.h"
 #include "SkPictureFlat.h"
 #include "SkPictureStateTree.h"
 
@@ -55,65 +56,6 @@
 // Always write this guy last (with no length field afterwards)
 #define SK_PICT_EOF_TAG     SkSetFourByteTag('e', 'o', 'f', ' ')
 
-// SkPictureContentInfo is not serialized! It is intended solely for use
-// with suitableForGpuRasterization.
-class SkPictureContentInfo {
-public:
-    SkPictureContentInfo() { this->reset(); }
-
-    SkPictureContentInfo(const SkPictureContentInfo& src) { this->set(src); }
-
-    void set(const SkPictureContentInfo& src) {
-        fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
-        fNumFastPathDashEffects = src.fNumFastPathDashEffects;
-        fNumAAConcavePaths = src.fNumAAConcavePaths;
-        fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
-    }
-
-    void reset() {
-        fNumPaintWithPathEffectUses = 0;
-        fNumFastPathDashEffects = 0;
-        fNumAAConcavePaths = 0;
-        fNumAAHairlineConcavePaths = 0;
-    }
-
-    void swap(SkPictureContentInfo* other) {
-        SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
-        SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
-        SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
-        SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
-    }
-
-    void incPaintWithPathEffectUses() { ++fNumPaintWithPathEffectUses; }
-    int numPaintWithPathEffectUses() const { return fNumPaintWithPathEffectUses; }
-
-    void incFastPathDashEffects() { ++fNumFastPathDashEffects; }
-    int numFastPathDashEffects() const { return fNumFastPathDashEffects; }
-
-    void incAAConcavePaths() { ++fNumAAConcavePaths; }
-    int numAAConcavePaths() const { return fNumAAConcavePaths; }
-
-    void incAAHairlineConcavePaths() {
-        ++fNumAAHairlineConcavePaths;
-        SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths);
-    }
-    int numAAHairlineConcavePaths() const { return fNumAAHairlineConcavePaths; }
-
-private:
-    // This field is incremented every time a paint with a path effect is
-    // used (i.e., it is not a de-duplicated count)
-    int fNumPaintWithPathEffectUses;
-    // This field is incremented every time a paint with a path effect that is
-    // dashed, we are drawing a line, and we can use the gpu fast path
-    int fNumFastPathDashEffects;
-    // This field is incremented every time an anti-aliased drawPath call is
-    // issued with a concave path
-    int fNumAAConcavePaths;
-    // This field is incremented every time a drawPath call is
-    // issued for a hairline stroked concave path.
-    int fNumAAHairlineConcavePaths;
-};
-
 #ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE
 /**
  * Container for data that is needed to deep copy a SkPicture. The container
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 72c537b..31a66ab 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -972,20 +972,14 @@
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
 #endif
+    fContentInfo.onDrawPoints(count, paint);
 
     // op + paint index + mode + count + point data
     size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
     size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
     SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.bytesWritten());
     this->addPaint(paint);
-    if (paint.getPathEffect() != NULL) {
-        SkPathEffect::DashInfo info;
-        SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info);
-        if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() &&
-            SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
-            fContentInfo.incFastPathDashEffects();
-        }
-    }
+
     this->addInt(mode);
     this->addInt(SkToInt(count));
     fWriter.writeMul4(pts, count * sizeof(SkPoint));
@@ -1062,14 +1056,7 @@
 
 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
 
-    if (paint.isAntiAlias() && !path.isConvex()) {
-        fContentInfo.incAAConcavePaths();
-
-        if (SkPaint::kStroke_Style == paint.getStyle() &&
-            0 == paint.getStrokeWidth()) {
-            fContentInfo.incAAHairlineConcavePaths();
-        }
-    }
+    fContentInfo.onDrawPath(path, paint);
 
 #ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
     fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
@@ -1600,9 +1587,7 @@
 }
 
 const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
-    if (NULL != paint && NULL != paint->getPathEffect()) {
-        fContentInfo.incPaintWithPathEffectUses();
-    }
+    fContentInfo.onAddPaintPtr(paint);
 
     const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
     this->addFlatPaint(data);
@@ -1704,6 +1689,7 @@
 }
 
 void SkPictureRecord::addText(const void* text, size_t byteLength) {
+    fContentInfo.onDrawText();
 #ifdef SK_DEBUG_SIZE
     size_t start = fWriter.bytesWritten();
 #endif
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 140558d..57e6008 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -146,6 +146,7 @@
         size_t offset = fWriter.bytesWritten();
 
         this->predrawNotify();
+        fContentInfo.addOperation();
 
     #ifdef SK_DEBUG_TRACE
         SkDebugf("add %s\n", DrawTypeToString(drawType));