aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-01-25 15:27:33 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-25 21:23:18 +0000
commitcf8ed52895239d59341c1ec555d51749531298b4 (patch)
tree0d88b0ca22515f72da609aa7b9342dcb99b4a117 /experimental
parentca96da7ad87221bfc4603cd03c0cb11b87f1a6ea (diff)
[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>
Diffstat (limited to 'experimental')
-rw-r--r--experimental/skottie/Skottie.cpp84
-rw-r--r--experimental/skottie/SkottieAnimator.cpp22
-rw-r--r--experimental/skottie/SkottieAnimator.h7
-rw-r--r--experimental/skottie/SkottieParser.cpp160
-rw-r--r--experimental/skottie/SkottieParser.h28
-rw-r--r--experimental/skottie/SkottiePriv.h42
-rw-r--r--experimental/skottie/SkottieProperties.cpp101
-rw-r--r--experimental/skottie/SkottieProperties.h4
8 files changed, 245 insertions, 203 deletions
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp
index c8144e446d..53f1c88037 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 @@ bool BindProperty(const Json::Value& jprop, AttachContext* ctx,
// 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 @@ sk_sp<sksg::RenderNode> AttachOpacity(const Json::Value& jtransform, AttachConte
// 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 @@ sk_sp<sksg::GeometryNode> AttachPolystarGeometry(const Json::Value& jstar, Attac
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 @@ sk_sp<sksg::Gradient> AttachGradient(const Json::Value& obj, AttachContext* ctx)
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 @@ sk_sp<sksg::PaintNode> AttachStroke(const Json::Value& jstroke, AttachContext* c
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 @@ sk_sp<sksg::PaintNode> AttachStroke(const Json::Value& jstroke, AttachContext* c
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 @@ std::vector<sk_sp<sksg::GeometryNode>> AttachMergeGeometryEffect(
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 @@ std::vector<sk_sp<sksg::GeometryNode>> AttachTrimGeometryEffect(
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> AttachShape(const Json::Value& jshape, AttachShapeContex
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> AttachCompLayer(const Json::Value& layer, AttachContext*
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> AttachSolidLayer(const Json::Value& jlayer, AttachContex
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> AttachImageAsset(const Json::Value& jimage, AttachContex
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> AttachNullLayer(const Json::Value& layer, AttachContext*
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 @@ struct AttachLayerContext {
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 @@ struct AttachLayerContext {
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 @@ sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask,
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 @@ sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask,
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 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer,
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 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer,
};
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 @@ sk_sp<sksg::RenderNode> AttachComposition(const Json::Value& comp, AttachContext
}
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 @@ std::unique_ptr<Animation> Animation::Make(SkStream* stream, const ResourceProvi
}
}
- 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 @@ Animation::Animation(const ResourceProvider& resources,
: 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 @@ Animation::Animation(const ResourceProvider& resources,
continue;
}
- assets.set(ParseString(asset["id"], ""), &asset);
+ assets.set(ParseDefault(asset["id"], SkString()), &asset);
}
sksg::Scene::AnimatorList animators;
diff --git a/experimental/skottie/SkottieAnimator.cpp b/experimental/skottie/SkottieAnimator.cpp
index 13f14dbf75..5190341f27 100644
--- a/experimental/skottie/SkottieAnimator.cpp
+++ b/experimental/skottie/SkottieAnimator.cpp
@@ -16,31 +16,19 @@ SkScalar lerp_scalar(float v0, float v1, float t) {
return v0 * (1 - t) + v1 * t;
}
-static inline SkPoint ParsePoint(const Json::Value& v, const SkPoint& defaultValue) {
- if (!v.isObject())
- return defaultValue;
-
- const auto& vx = v["x"];
- const auto& vy = v["y"];
-
- // Some BM versions seem to store x/y as single-element arrays.
- return SkPoint::Make(ParseScalar(vx.isArray() ? vx[0] : vx, defaultValue.x()),
- ParseScalar(vy.isArray() ? vy[0] : vy, defaultValue.y()));
-}
-
} // namespace
bool KeyframeIntervalBase::parse(const Json::Value& k, KeyframeIntervalBase* prev) {
SkASSERT(k.isObject());
- fT0 = fT1 = ParseScalar(k["t"], SK_ScalarMin);
+ fT0 = fT1 = ParseDefault(k["t"], SK_ScalarMin);
if (fT0 == SK_ScalarMin) {
return false;
}
if (prev) {
if (prev->fT1 >= fT0) {
- LOG("!! Dropping out-of-order key frame (t: %f < t: %f)\n", fT0, prev->fT1);
+ SkDebugf("!! Dropping out-of-order key frame (t: %f < t: %f)\n", fT0, prev->fT1);
return false;
}
// Back-fill t1 in prev interval. Note: we do this even if we end up discarding
@@ -48,14 +36,14 @@ bool KeyframeIntervalBase::parse(const Json::Value& k, KeyframeIntervalBase* pre
prev->fT1 = fT0;
}
- fHold = ParseBool(k["h"], false);
+ fHold = ParseDefault(k["h"], false);
if (!fHold) {
// default is linear lerp
static constexpr SkPoint kDefaultC0 = { 0, 0 },
kDefaultC1 = { 1, 1 };
- const auto c0 = ParsePoint(k["i"], kDefaultC0),
- c1 = ParsePoint(k["o"], kDefaultC1);
+ const auto c0 = ParseDefault(k["i"], kDefaultC0),
+ c1 = ParseDefault(k["o"], kDefaultC1);
if (c0 != kDefaultC0 || c1 != kDefaultC1) {
fCubicMap = skstd::make_unique<SkCubicMap>();
diff --git a/experimental/skottie/SkottieAnimator.h b/experimental/skottie/SkottieAnimator.h
index 8320ec499e..6e44ebe873 100644
--- a/experimental/skottie/SkottieAnimator.h
+++ b/experimental/skottie/SkottieAnimator.h
@@ -9,8 +9,9 @@
#define SkottieAnimator_DEFINED
#include "SkCubicMap.h"
+#include "SkJSONCPP.h"
#include "SkMakeUnique.h"
-#include "SkottiePriv.h"
+#include "SkottieParser.h"
#include "SkottieProperties.h"
#include "SkSGScene.h"
#include "SkTArray.h"
@@ -62,12 +63,12 @@ public:
SkASSERT(k.isObject());
if (!this->INHERITED::parse(k, prev) ||
- !ValueTraits<T>::Parse(k["s"], &fV0)) {
+ !Parse<T>(k["s"], &fV0)) {
return false;
}
if (!this->isHold() &&
- (!ValueTraits<T>::Parse(k["e"], &fV1) ||
+ (!Parse<T>(k["e"], &fV1) ||
ValueTraits<T>::Cardinality(fV0) != ValueTraits<T>::Cardinality(fV1))) {
return false;
}
diff --git a/experimental/skottie/SkottieParser.cpp b/experimental/skottie/SkottieParser.cpp
new file mode 100644
index 0000000000..a40a9ae8c0
--- /dev/null
+++ b/experimental/skottie/SkottieParser.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkottieParser.h"
+
+#include "SkJSONCPP.h"
+#include "SkScalar.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkString.h"
+
+#include <vector>
+
+namespace skottie {
+
+template <>
+bool Parse<SkScalar>(const Json::Value& jv, SkScalar* v) {
+ // Some versions wrap values as single-element arrays.
+ if (jv.isArray() && jv.size() == 1) {
+ return Parse(jv[0], v);
+ }
+
+ if (jv.isNull() || !jv.isConvertibleTo(Json::realValue))
+ return false;
+
+ *v = jv.asFloat();
+
+ return true;
+}
+
+template <>
+bool Parse<bool>(const Json::Value& jv, bool* v) {
+ if (jv.isNull() || !jv.isConvertibleTo(Json::booleanValue))
+ return false;
+
+ *v = jv.asBool();
+
+ return true;
+}
+
+template <>
+bool Parse<int>(const Json::Value& jv, int* v) {
+ if (jv.isNull() || !jv.isConvertibleTo(Json::intValue))
+ return false;
+
+ *v = jv.asInt();
+
+ return true;
+}
+
+template <>
+bool Parse<SkString>(const Json::Value& jv, SkString* v) {
+ if (jv.isNull() || !jv.isConvertibleTo(Json::stringValue))
+ return false;
+
+ v->set(jv.asCString());
+
+ return true;
+}
+
+template <>
+bool Parse<SkPoint>(const Json::Value& jv, SkPoint* v) {
+ if (!jv.isObject())
+ return false;
+
+ const auto& jvx = jv["x"],
+ jvy = jv["y"];
+
+ // Some BM versions seem to store x/y as single-element arrays.
+ return Parse(jvx.isArray() ? jvx[0] : jvx, &v->fX)
+ && Parse(jvy.isArray() ? jvy[0] : jvy, &v->fY);
+}
+
+template <>
+bool Parse<std::vector<float>>(const Json::Value& jv, std::vector<float>* v) {
+ if (!jv.isArray())
+ return false;
+
+ v->resize(jv.size());
+
+ for (Json::ArrayIndex i = 0; i < jv.size(); ++i) {
+ if (!Parse(jv[i], v->data() + i)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+namespace {
+
+bool ParsePointVec(const Json::Value& jv, std::vector<SkPoint>* pts) {
+ if (!jv.isArray())
+ return false;
+
+ pts->clear();
+ pts->reserve(jv.size());
+
+ std::vector<float> vec;
+ for (Json::ArrayIndex i = 0; i < jv.size(); ++i) {
+ if (!Parse(jv[i], &vec) || vec.size() != 2)
+ return false;
+ pts->push_back(SkPoint::Make(vec[0], vec[1]));
+ }
+
+ return true;
+}
+
+} // namespace
+
+template <>
+bool Parse<SkPath>(const Json::Value& jv, SkPath* v) {
+ SkASSERT(v->isEmpty());
+
+ // Some versions wrap values as single-element arrays.
+ if (jv.isArray() && jv.size() == 1) {
+ return Parse(jv[0], v);
+ }
+
+ std::vector<SkPoint> inPts, // Cubic Bezier "in" control points, relative to vertices.
+ outPts, // Cubic Bezier "out" control points, relative to vertices.
+ verts; // Cubic Bezier vertices.
+
+ if (!jv.isObject() ||
+ !ParsePointVec(jv["i"], &inPts) ||
+ !ParsePointVec(jv["o"], &outPts) ||
+ !ParsePointVec(jv["v"], &verts) ||
+ inPts.size() != outPts.size() ||
+ inPts.size() != verts.size()) {
+
+ return false;
+ }
+
+ if (!verts.empty()) {
+ v->moveTo(verts.front());
+ }
+
+ const auto& addCubic = [&](size_t from, size_t to) {
+ v->cubicTo(verts[from] + outPts[from],
+ verts[to] + inPts[to],
+ verts[to]);
+ };
+
+ for (size_t i = 1; i < verts.size(); ++i) {
+ addCubic(i - 1, i);
+ }
+
+ if (!verts.empty() && ParseDefault(jv["c"], false)) {
+ addCubic(verts.size() - 1, 0);
+ v->close();
+ }
+
+ return true;
+}
+
+} // nasmespace skottie
diff --git a/experimental/skottie/SkottieParser.h b/experimental/skottie/SkottieParser.h
new file mode 100644
index 0000000000..b805484cd0
--- /dev/null
+++ b/experimental/skottie/SkottieParser.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkottieParser_DEFINED
+#define SkottieParser_DEFINED
+
+namespace Json { class Value; }
+
+namespace skottie {
+
+template <typename T>
+bool Parse(const Json::Value&, T*);
+
+template <typename T>
+static inline T ParseDefault(const Json::Value& jv, const T& defaultValue) {
+ T v;
+ if (!Parse<T>(jv, &v))
+ v = defaultValue;
+ return v;
+}
+
+} // nasmespace skottie
+
+#endif // SkottieParser_DEFINED
diff --git a/experimental/skottie/SkottiePriv.h b/experimental/skottie/SkottiePriv.h
deleted file mode 100644
index 663a3f3d4c..0000000000
--- a/experimental/skottie/SkottiePriv.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkottiePriv_DEFINED
-#define SkottiePriv_DEFINED
-
-#include "SkJSONCPP.h"
-#include "SkPoint.h"
-#include "SkScalar.h"
-#include "SkString.h"
-
-namespace skottie {
-
-#define LOG SkDebugf
-
-static inline SkScalar ParseScalar(const Json::Value& v, SkScalar defaultValue) {
- return !v.isNull() && v.isConvertibleTo(Json::realValue)
- ? v.asFloat() : defaultValue;
-}
-
-static inline SkString ParseString(const Json::Value& v, const char defaultValue[]) {
- return SkString(!v.isNull() && v.isConvertibleTo(Json::stringValue)
- ? v.asCString() : defaultValue);
-}
-
-static inline int ParseInt(const Json::Value& v, int defaultValue) {
- return !v.isNull() && v.isConvertibleTo(Json::intValue)
- ? v.asInt() : defaultValue;
-}
-
-static inline bool ParseBool(const Json::Value& v, bool defaultValue) {
- return !v.isNull() && v.isConvertibleTo(Json::booleanValue)
- ? v.asBool() : defaultValue;
-}
-
-} // namespace
-
-#endif // SkottiePriv_DEFINED
diff --git a/experimental/skottie/SkottieProperties.cpp b/experimental/skottie/SkottieProperties.cpp
index b9535c428c..0816e15bca 100644
--- a/experimental/skottie/SkottieProperties.cpp
+++ b/experimental/skottie/SkottieProperties.cpp
@@ -8,7 +8,7 @@
#include "SkottieProperties.h"
#include "SkColor.h"
-#include "SkottiePriv.h"
+#include "SkJSONCPP.h"
#include "SkPath.h"
#include "SkSGColor.h"
#include "SkSGGradient.h"
@@ -22,26 +22,6 @@ namespace skottie {
namespace {
-using PointArray = SkSTArray<64, SkPoint, true>;
-
-bool ParsePoints(const Json::Value& v, PointArray* pts) {
- if (!v.isArray()) {
- return false;
- }
-
- for (Json::ArrayIndex i = 0; i < v.size(); ++i) {
- const auto& pt = v[i];
- if (!pt.isArray() || pt.size() != 2 ||
- !pt[0].isConvertibleTo(Json::realValue) ||
- !pt[1].isConvertibleTo(Json::realValue)) {
- return false;
- }
-
- pts->push_back(SkPoint::Make(ParseScalar(pt[0], 0), ParseScalar(pt[1], 0)));
- }
- return true;
-}
-
SkColor VecToColor(const float* v, size_t size) {
// best effort to turn this into a color
const auto r = size > 0 ? v[0] : 0,
@@ -58,20 +38,6 @@ SkColor VecToColor(const float* v, size_t size) {
} // namespace
template <>
-bool ValueTraits<ScalarValue>::Parse(const Json::Value& v, ScalarValue* scalar) {
- // Some files appear to wrap keyframes in arrays for no reason.
- if (v.isArray() && v.size() == 1) {
- return Parse(v[0], scalar);
- }
-
- if (v.isNull() || !v.isConvertibleTo(Json::realValue))
- return false;
-
- *scalar = v.asFloat();
- return true;
-}
-
-template <>
size_t ValueTraits<ScalarValue>::Cardinality(const ScalarValue&) {
return 1;
}
@@ -83,24 +49,6 @@ SkScalar ValueTraits<ScalarValue>::As<SkScalar>(const ScalarValue& v) {
}
template <>
-bool ValueTraits<VectorValue>::Parse(const Json::Value& v, VectorValue* vec) {
- SkASSERT(vec->empty());
-
- if (!v.isArray())
- return false;
-
- for (Json::ArrayIndex i = 0; i < v.size(); ++i) {
- ScalarValue scalar;
- if (!ValueTraits<ScalarValue>::Parse(v[i], &scalar))
- return false;
-
- vec->push_back(std::move(scalar));
- }
-
- return true;
-}
-
-template <>
size_t ValueTraits<VectorValue>::Cardinality(const VectorValue& vec) {
return vec.size();
}
@@ -127,51 +75,6 @@ SkSize ValueTraits<VectorValue>::As<SkSize>(const VectorValue& vec) {
return SkSize::Make(pt.x(), pt.y());
}
-template<>
-bool ValueTraits<ShapeValue>::Parse(const Json::Value& v, ShapeValue* shape) {
- PointArray inPts, // Cubic Bezier "in" control points, relative to vertices.
- outPts, // Cubic Bezier "out" control points, relative to vertices.
- verts; // Cubic Bezier vertices.
-
- // Some files appear to wrap keyframes in arrays for no reason.
- if (v.isArray() && v.size() == 1) {
- return Parse(v[0], shape);
- }
-
- if (!v.isObject() ||
- !ParsePoints(v["i"], &inPts) ||
- !ParsePoints(v["o"], &outPts) ||
- !ParsePoints(v["v"], &verts) ||
- inPts.count() != outPts.count() ||
- inPts.count() != verts.count()) {
-
- return false;
- }
-
- SkASSERT(shape->isEmpty());
-
- if (!verts.empty()) {
- shape->moveTo(verts.front());
- }
-
- const auto& addCubic = [&](int from, int to) {
- shape->cubicTo(verts[from] + outPts[from],
- verts[to] + inPts[to],
- verts[to]);
- };
-
- for (int i = 1; i < verts.count(); ++i) {
- addCubic(i - 1, i);
- }
-
- if (!verts.empty() && ParseBool(v["c"], false)) {
- addCubic(verts.count() - 1, 0);
- shape->close();
- }
-
- return true;
-}
-
template <>
size_t ValueTraits<ShapeValue>::Cardinality(const ShapeValue& path) {
return SkTo<size_t>(path.countVerbs());
@@ -252,7 +155,7 @@ void CompositeGradient::apply() {
// |fColorStops| holds |fStopCount| x [ pos, r, g, g ] + ? x [ pos, alpha ]
if (fColorStops.size() < fStopCount * 4 || ((fColorStops.size() - fStopCount * 4) % 2)) {
- LOG("!! Invalid gradient stop array size: %zu", fColorStops.size());
+ SkDebugf("!! Invalid gradient stop array size: %zu", fColorStops.size());
return;
}
diff --git a/experimental/skottie/SkottieProperties.h b/experimental/skottie/SkottieProperties.h
index c5e14d14cb..8ca026eaeb 100644
--- a/experimental/skottie/SkottieProperties.h
+++ b/experimental/skottie/SkottieProperties.h
@@ -12,7 +12,6 @@
#include "SkPath.h"
#include "SkPoint.h"
#include "SkSize.h"
-#include "SkottiePriv.h"
#include "SkRefCnt.h"
#include "SkTArray.h"
#include "SkTypes.h"
@@ -31,11 +30,12 @@ class RRect;
class RenderNode;;
}
+namespace Json { class Value; }
+
namespace skottie {
template <typename T>
struct ValueTraits {
- static bool Parse(const Json::Value&, T*);
static size_t Cardinality(const T&);
template <typename U>