[skottie] Parser cleanup

Consolidate parsing utils into their own CU.

TBR=

Change-Id: Idbf6db5220135ba91df6ebefce3a241c6ec4af15
Reviewed-on: https://skia-review.googlesource.com/99721
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 c8144e4..53f1c88 100644
--- a/experimental/skottie/Skottie.cpp
+++ b/experimental/skottie/Skottie.cpp
@@ -9,7 +9,7 @@
 
 #include "SkCanvas.h"
 #include "SkottieAnimator.h"
-#include "SkottiePriv.h"
+#include "SkottieParser.h"
 #include "SkottieProperties.h"
 #include "SkData.h"
 #include "SkImage.h"
@@ -46,6 +46,8 @@
 
 namespace skottie {
 
+#define LOG SkDebugf
+
 namespace {
 
 using AssetMap = SkTHashMap<SkString, const Json::Value*>;
@@ -75,9 +77,9 @@
 
     // Older Json versions don't have an "a" animation marker.
     // For those, we attempt to parse both ways.
-    if (jpropA.isNull() || !ParseBool(jpropA, "false")) {
+    if (!ParseDefault(jpropA, false)) {
         T val;
-        if (ValueTraits<T>::Parse(jpropK, &val)) {
+        if (Parse<T>(jpropK, &val)) {
             // Static property.
             apply(val);
             return true;
@@ -154,8 +156,8 @@
     // nodes for the extremely common case of static opaciy == 100.
     const auto& opacity = jtransform["o"];
     if (opacity.isObject() &&
-        !ParseBool(opacity["a"], true) &&
-        ParseScalar(opacity["k"], -1) == 100) {
+        !ParseDefault(opacity["a"], true) &&
+        ParseDefault(opacity["k"], -1) == 100) {
         // Ignoring static full opacity.
         return childNode;
     }
@@ -248,7 +250,7 @@
         CompositePolyStar::Type::kPoly, // "sy": 2
     };
 
-    const auto type = ParseInt(jstar["sy"], 0) - 1;
+    const auto type = ParseDefault(jstar["sy"], 0) - 1;
     if (type < 0 || type >= SkTo<int>(SK_ARRAY_COUNT(gTypes))) {
         LogFail(jstar, "Unknown polystar type");
         return nullptr;
@@ -308,14 +310,14 @@
     if (!stops.isObject())
         return nullptr;
 
-    const auto stopCount = ParseInt(stops["p"], -1);
+    const auto stopCount = ParseDefault(stops["p"], -1);
     if (stopCount < 0)
         return nullptr;
 
     sk_sp<sksg::Gradient> gradient_node;
     sk_sp<CompositeGradient> composite;
 
-    if (ParseInt(obj["t"], 1) == 1) {
+    if (ParseDefault(obj["t"], 1) == 1) {
         auto linear_node = sksg::LinearGradient::Make();
         composite = sk_make_sp<CompositeLinearGradient>(linear_node, stopCount);
         gradient_node = std::move(linear_node);
@@ -374,14 +376,14 @@
     if (!width_attached)
         return nullptr;
 
-    stroke_node->setStrokeMiter(ParseScalar(jstroke["ml"], 4));
+    stroke_node->setStrokeMiter(ParseDefault(jstroke["ml"], 4.0f));
 
     static constexpr SkPaint::Join gJoins[] = {
         SkPaint::kMiter_Join,
         SkPaint::kRound_Join,
         SkPaint::kBevel_Join,
     };
-    stroke_node->setStrokeJoin(gJoins[SkTPin<int>(ParseInt(jstroke["lj"], 1) - 1,
+    stroke_node->setStrokeJoin(gJoins[SkTPin<int>(ParseDefault(jstroke["lj"], 1) - 1,
                                                   0, SK_ARRAY_COUNT(gJoins) - 1)]);
 
     static constexpr SkPaint::Cap gCaps[] = {
@@ -389,7 +391,7 @@
         SkPaint::kRound_Cap,
         SkPaint::kSquare_Cap,
     };
-    stroke_node->setStrokeCap(gCaps[SkTPin<int>(ParseInt(jstroke["lc"], 1) - 1,
+    stroke_node->setStrokeCap(gCaps[SkTPin<int>(ParseDefault(jstroke["lc"], 1) - 1,
                                                 0, SK_ARRAY_COUNT(gCaps) - 1)]);
 
     return stroke_node;
@@ -431,7 +433,7 @@
         sksg::Merge::Mode::kXOR      ,  // "mm": 5
     };
 
-    const auto mode = gModes[SkTPin<int>(ParseInt(jmerge["mm"], 1) - 1,
+    const auto mode = gModes[SkTPin<int>(ParseDefault(jmerge["mm"], 1) - 1,
                                          0, SK_ARRAY_COUNT(gModes) - 1)];
     merged.push_back(sksg::Merge::Make(std::move(geos), mode));
 
@@ -448,7 +450,7 @@
         kSeparate, // "m": 2
     } gModes[] = { Mode::kMerged, Mode::kSeparate };
 
-    const auto mode = gModes[SkTPin<int>(ParseInt(jtrim["m"], 1) - 1,
+    const auto mode = gModes[SkTPin<int>(ParseDefault(jtrim["m"], 1) - 1,
                                          0, SK_ARRAY_COUNT(gModes) - 1)];
 
     std::vector<sk_sp<sksg::GeometryNode>> inputs;
@@ -714,8 +716,8 @@
 sk_sp<sksg::RenderNode> AttachCompLayer(const Json::Value& layer, AttachContext* ctx) {
     SkASSERT(layer.isObject());
 
-    auto refId = ParseString(layer["refId"], "");
-    if (refId.isEmpty()) {
+    SkString refId;
+    if (!Parse(layer["refId"], &refId) || refId.isEmpty()) {
         LOG("!! Comp layer missing refId\n");
         return nullptr;
     }
@@ -733,9 +735,9 @@
 sk_sp<sksg::RenderNode> AttachSolidLayer(const Json::Value& jlayer, AttachContext*) {
     SkASSERT(jlayer.isObject());
 
-    const auto size = SkSize::Make(ParseScalar(jlayer["sw"], -1),
-                                   ParseScalar(jlayer["sh"], -1));
-    const auto hex = ParseString(jlayer["sc"], "");
+    const auto size = SkSize::Make(ParseDefault(jlayer["sw"], 0.0f),
+                                   ParseDefault(jlayer["sh"], 0.0f));
+    const auto hex = ParseDefault(jlayer["sc"], SkString());
     uint32_t c;
     if (size.isEmpty() ||
         !hex.startsWith("#") ||
@@ -753,8 +755,8 @@
 sk_sp<sksg::RenderNode> AttachImageAsset(const Json::Value& jimage, AttachContext* ctx) {
     SkASSERT(jimage.isObject());
 
-    const auto name = ParseString(jimage["p"], ""),
-               path = ParseString(jimage["u"], "");
+    const auto name = ParseDefault(jimage["p"], SkString()),
+               path = ParseDefault(jimage["u"], SkString());
     if (name.isEmpty())
         return nullptr;
 
@@ -774,8 +776,8 @@
 sk_sp<sksg::RenderNode> AttachImageLayer(const Json::Value& layer, AttachContext* ctx) {
     SkASSERT(layer.isObject());
 
-    auto refId = ParseString(layer["refId"], "");
-    if (refId.isEmpty()) {
+    SkString refId;
+    if (!Parse(layer["refId"], &refId) || refId.isEmpty()) {
         LOG("!! Image layer missing refId\n");
         return nullptr;
     }
@@ -800,8 +802,6 @@
 sk_sp<sksg::RenderNode> AttachShapeLayer(const Json::Value& layer, AttachContext* ctx) {
     SkASSERT(layer.isObject());
 
-    LOG("** Attaching shape layer ind: %d\n", ParseInt(layer["ind"], 0));
-
     std::vector<sk_sp<sksg::GeometryNode>> geometryStack;
     std::vector<GeometryEffectRec> geometryEffectStack;
     AttachShapeContext shapeCtx(ctx, &geometryStack, &geometryEffectStack, ctx->fAnimators.size());
@@ -851,7 +851,7 @@
                 continue;
             }
 
-            if (ParseInt(l["ind"], -1) == index) {
+            if (ParseDefault(l["ind"], -1) == index) {
                 fLayerIndexCache.insert(std::make_pair(index, &l));
                 return &l;
             }
@@ -868,7 +868,7 @@
             return cached->second;
         }
 
-        const auto* parentLayer = this->findLayer(ParseInt(jlayer["parent"], -1));
+        const auto* parentLayer = this->findLayer(ParseDefault(jlayer["parent"], -1));
 
         // TODO: cycle detection?
         auto parentMatrix = (parentLayer && parentLayer != &jlayer)
@@ -907,7 +907,7 @@
         if (!m.isObject())
             continue;
 
-        const auto inverted = ParseBool(m["inv"], false);
+        const auto inverted = ParseDefault(m["inv"], false);
         // TODO
         if (inverted) {
             LogFail(m, "Unsupported inverse mask");
@@ -920,9 +920,12 @@
             continue;
         }
 
-        auto mode = ParseString(m["mode"], "");
-        if (mode.size() != 1 || !strcmp(mode.c_str(), "n")) // "None" masks have no effect.
+        SkString mode;
+        if (!Parse(m["mode"], &mode) ||
+            mode.size() != 1 ||
+            !strcmp(mode.c_str(), "n")) { // "None" masks have no effect.
             continue;
+        }
 
         auto mask_paint = sksg::Color::Make(SK_ColorBLACK);
         mask_paint->setBlendMode(MaskBlendMode(mode.c_str()[0]));
@@ -952,7 +955,7 @@
         AttachTextLayer,  // 'ty': 5
     };
 
-    int type = ParseInt(jlayer["ty"], -1);
+    int type = ParseDefault(jlayer["ty"], -1);
     if (type < 0 || type >= SkTo<int>(SK_ARRAY_COUNT(gLayerAttachers))) {
         return nullptr;
     }
@@ -989,15 +992,15 @@
     };
 
     auto layerControl = sksg::OpacityEffect::Make(std::move(layer));
-    const auto  in = ParseScalar(jlayer["ip"], 0),
-               out = ParseScalar(jlayer["op"], in);
+    const auto  in = ParseDefault(jlayer["ip"], 0.0f),
+               out = ParseDefault(jlayer["op"], in);
 
     if (in >= out || ! layerControl)
         return nullptr;
 
     layerCtx->fCtx->fAnimators.push_back(skstd::make_unique<Activator>(layerControl, in, out));
 
-    if (ParseBool(jlayer["td"], false)) {
+    if (ParseDefault(jlayer["td"], false)) {
         // This layer is a matte.  We apply it as a mask to the next layer.
         layerCtx->fCurrentMatte = std::move(layerControl);
         return nullptr;
@@ -1039,7 +1042,7 @@
     }
 
     LOG("** Attached composition '%s': %d layers.\n",
-        ParseString(comp["id"], "").c_str(), layers.count());
+        ParseDefault(comp["id"], SkString()).c_str(), layers.count());
 
     return comp_group;
 }
@@ -1070,9 +1073,10 @@
         }
     }
 
-    const auto version = ParseString(json["v"], "");
-    const auto size    = SkSize::Make(ParseScalar(json["w"], -1), ParseScalar(json["h"], -1));
-    const auto fps     = ParseScalar(json["fr"], -1);
+    const auto version = ParseDefault(json["v"], SkString());
+    const auto size    = SkSize::Make(ParseDefault(json["w"], 0.0f),
+                                      ParseDefault(json["h"], 0.0f));
+    const auto fps     = ParseDefault(json["fr"], -1.0f);
 
     if (size.isEmpty() || version.isEmpty() || fps < 0) {
         LOG("!! invalid animation params (version: %s, size: [%f %f], frame rate: %f)",
@@ -1114,8 +1118,8 @@
     : fVersion(std::move(version))
     , fSize(size)
     , fFrameRate(fps)
-    , fInPoint(ParseScalar(json["ip"], 0))
-    , fOutPoint(SkTMax(ParseScalar(json["op"], SK_ScalarMax), fInPoint)) {
+    , fInPoint(ParseDefault(json["ip"], 0.0f))
+    , fOutPoint(SkTMax(ParseDefault(json["op"], SK_ScalarMax), fInPoint)) {
 
     AssetMap assets;
     for (const auto& asset : json["assets"]) {
@@ -1123,7 +1127,7 @@
             continue;
         }
 
-        assets.set(ParseString(asset["id"], ""), &asset);
+        assets.set(ParseDefault(asset["id"], SkString()), &asset);
     }
 
     sksg::Scene::AnimatorList animators;