[skottie] Show load stats in SkottieSlide

TBR=
Change-Id: Ie3a1036d9a90cb16d2795134c453759aeff06e3c
Reviewed-on: https://skia-review.googlesource.com/124461
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp
index a3b6d46..bb98ad7 100644
--- a/experimental/skottie/Skottie.cpp
+++ b/experimental/skottie/Skottie.cpp
@@ -38,6 +38,7 @@
 #include "SkSGTrimEffect.h"
 #include "SkStream.h"
 #include "SkTArray.h"
+#include "SkTime.h"
 #include "SkTHash.h"
 
 #include <cmath>
@@ -1170,13 +1171,20 @@
 
 } // namespace
 
-sk_sp<Animation> Animation::Make(SkStream* stream, const ResourceProvider& res) {
+sk_sp<Animation> Animation::Make(SkStream* stream, const ResourceProvider& res, Stats* stats) {
+    Stats stats_storage;
+    if (!stats)
+        stats = &stats_storage;
+    memset(stats, 0, sizeof(struct Stats));
+
     if (!stream->hasLength()) {
         // TODO: handle explicit buffering?
         LOG("!! cannot parse streaming content\n");
         return nullptr;
     }
 
+    const auto t0 = SkTime::GetMSecs();
+
     Json::Value json;
     {
         auto data = SkData::MakeFromStream(stream, stream->getLength());
@@ -1184,6 +1192,7 @@
             LOG("!! could not read stream\n");
             return nullptr;
         }
+        stats->fJsonSize = data->size();
 
         Json::Reader reader;
 
@@ -1194,6 +1203,9 @@
         }
     }
 
+    const auto t1 = SkTime::GetMSecs();
+    stats->fJsonParseTimeMS = t1 - t0;
+
     const auto version = ParseDefault(json["v"], SkString());
     const auto size    = SkSize::Make(ParseDefault(json["w"], 0.0f),
                                       ParseDefault(json["h"], 0.0f));
@@ -1205,10 +1217,17 @@
         return nullptr;
     }
 
-    return sk_sp<Animation>(new Animation(res, std::move(version), size, fps, json));
+    const auto anim =
+        sk_sp<Animation>(new Animation(res, std::move(version), size, fps, json, stats));
+    const auto t2 = SkTime::GetMSecs();
+    stats->fSceneParseTimeMS = t2 - t1;
+    stats->fTotalLoadTimeMS  = t2 - t0;
+
+    return anim;
 }
 
-sk_sp<Animation> Animation::MakeFromFile(const char path[], const ResourceProvider* res) {
+sk_sp<Animation> Animation::MakeFromFile(const char path[], const ResourceProvider* res,
+                                         Stats* stats) {
     class DirectoryResourceProvider final : public ResourceProvider {
     public:
         explicit DirectoryResourceProvider(SkString dir) : fDir(std::move(dir)) {}
@@ -1231,11 +1250,12 @@
         defaultProvider = skstd::make_unique<DirectoryResourceProvider>(SkOSPath::Dirname(path));
     }
 
-    return Make(jsonStream.get(), res ? *res : *defaultProvider);
+    return Make(jsonStream.get(), res ? *res : *defaultProvider, stats);
 }
 
 Animation::Animation(const ResourceProvider& resources,
-                     SkString version, const SkSize& size, SkScalar fps, const Json::Value& json)
+                     SkString version, const SkSize& size, SkScalar fps, const Json::Value& json,
+                     Stats* stats)
     : fVersion(std::move(version))
     , fSize(size)
     , fFrameRate(fps)
@@ -1255,7 +1275,7 @@
     AttachContext ctx = { resources, assets, fFrameRate, animators };
     auto root = AttachComposition(json, &ctx);
 
-    LOG("** Attached %d animators\n", animators.size());
+    stats->fAnimatorCount = animators.size();
 
     fScene = sksg::Scene::Make(std::move(root), std::move(animators));
 
diff --git a/experimental/skottie/Skottie.h b/experimental/skottie/Skottie.h
index f14c4dc..44541fd 100644
--- a/experimental/skottie/Skottie.h
+++ b/experimental/skottie/Skottie.h
@@ -36,8 +36,17 @@
 
 class Animation : public SkRefCnt {
 public:
-    static sk_sp<Animation> Make(SkStream*, const ResourceProvider&);
-    static sk_sp<Animation> MakeFromFile(const char path[], const ResourceProvider* = nullptr);
+    struct Stats {
+        float  fTotalLoadTimeMS,
+               fJsonParseTimeMS,
+               fSceneParseTimeMS;
+        size_t fJsonSize,
+               fAnimatorCount;
+    };
+
+    static sk_sp<Animation> Make(SkStream*, const ResourceProvider&, Stats* = nullptr);
+    static sk_sp<Animation> MakeFromFile(const char path[], const ResourceProvider* = nullptr,
+                                         Stats* = nullptr);
 
     ~Animation() override;
 
@@ -56,7 +65,7 @@
 private:
     Animation(const ResourceProvider&,
               SkString ver, const SkSize& size, SkScalar fps,
-              const Json::Value&);
+              const Json::Value&, Stats*);
 
     SkString                     fVersion;
     SkSize                       fSize;
diff --git a/tools/viewer/SkottieSlide.cpp b/tools/viewer/SkottieSlide.cpp
index 77501d8..78cda5c 100644
--- a/tools/viewer/SkottieSlide.cpp
+++ b/tools/viewer/SkottieSlide.cpp
@@ -11,13 +11,51 @@
 #include "SkCanvas.h"
 #include "Skottie.h"
 
+static void draw_stats_box(SkCanvas* canvas, const skottie::Animation::Stats& stats) {
+    static constexpr SkRect kR = { 10, 10, 280, 120 };
+    static constexpr SkScalar kTextSize = 20;
+
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setColor(0xffeeeeee);
+    paint.setTextSize(kTextSize);
+
+    canvas->drawRect(kR, paint);
+
+    paint.setColor(SK_ColorBLACK);
+
+    const auto json_size = SkStringPrintf("Json size: %lu bytes",
+                                          stats.fJsonSize);
+    canvas->drawText(json_size.c_str(),
+                     json_size.size(), kR.x() + 10, kR.y() + kTextSize * 1, paint);
+    const auto animator_count = SkStringPrintf("Animator count: %lu",
+                                               stats.fAnimatorCount);
+    canvas->drawText(animator_count.c_str(),
+                     animator_count.size(), kR.x() + 10, kR.y() + kTextSize * 2, paint);
+    const auto json_parse_time = SkStringPrintf("Json parse time: %.3f ms",
+                                                stats.fJsonParseTimeMS);
+    canvas->drawText(json_parse_time.c_str(),
+                     json_parse_time.size(), kR.x() + 10, kR.y() + kTextSize * 3, paint);
+    const auto scene_parse_time = SkStringPrintf("Scene build time: %.3f ms",
+                                                 stats.fSceneParseTimeMS);
+    canvas->drawText(scene_parse_time.c_str(),
+                     scene_parse_time.size(), kR.x() + 10, kR.y() + kTextSize * 4, paint);
+    const auto total_load_time = SkStringPrintf("Total load time: %.3f ms",
+                                                stats.fTotalLoadTimeMS);
+    canvas->drawText(total_load_time.c_str(),
+                     total_load_time.size(), kR.x() + 10, kR.y() + kTextSize * 5, paint);
+
+    paint.setStyle(SkPaint::kStroke_Style);
+    canvas->drawRect(kR, paint);
+}
+
 SkottieSlide::SkottieSlide(const SkString& name, const SkString& path)
     : fPath(path) {
     fName = name;
 }
 
 void SkottieSlide::load(SkScalar w, SkScalar h) {
-    fAnimation = skottie::Animation::MakeFromFile(fPath.c_str());
+    fAnimation = skottie::Animation::MakeFromFile(fPath.c_str(), nullptr, &fAnimationStats);
     fWinSize   = SkSize::Make(w, h);
     fTimeBase  = 0; // force a time reset
 
@@ -47,6 +85,10 @@
         SkAutoCanvasRestore acr(canvas, true);
         const auto dstR = SkRect::MakeSize(fWinSize);
         fAnimation->render(canvas, &dstR);
+
+        if (fShowAnimationStats) {
+            draw_stats_box(canvas, fAnimationStats);
+        }
     }
 }
 
@@ -66,10 +108,7 @@
 bool SkottieSlide::onChar(SkUnichar c) {
     switch (c) {
     case 'I':
-        if (fAnimation) {
-            fShowAnimationInval = !fShowAnimationInval;
-            fAnimation->setShowInval(fShowAnimationInval);
-        }
+        fShowAnimationStats = !fShowAnimationStats;
         break;
     default:
         break;
@@ -82,6 +121,7 @@
     switch (state) {
     case sk_app::Window::kUp_InputState:
         fShowAnimationInval = !fShowAnimationInval;
+        fShowAnimationStats = !fShowAnimationStats;
         fAnimation->setShowInval(fShowAnimationInval);
         break;
     default:
diff --git a/tools/viewer/SkottieSlide.h b/tools/viewer/SkottieSlide.h
index b5770a0..0bfe66e 100644
--- a/tools/viewer/SkottieSlide.h
+++ b/tools/viewer/SkottieSlide.h
@@ -9,8 +9,8 @@
 #define SkottieSlide_DEFINED
 
 #include "Slide.h"
+#include "Skottie.h"
 
-namespace skottie { class Animation; }
 namespace sksg    { class Scene;     }
 
 class SkottieSlide : public Slide {
@@ -32,9 +32,11 @@
 private:
     SkString                  fPath;
     sk_sp<skottie::Animation> fAnimation;
+    skottie::Animation::Stats fAnimationStats;
     SkSize                    fWinSize = SkSize::MakeEmpty();
     SkMSec                    fTimeBase  = 0;
-    bool                      fShowAnimationInval = false;
+    bool                      fShowAnimationInval = false,
+                              fShowAnimationStats = false;
 
     typedef Slide INHERITED;
 };