From cf8ed52895239d59341c1ec555d51749531298b4 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Thu, 25 Jan 2018 15:27:33 -0500 Subject: [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 Commit-Queue: Florin Malita --- experimental/skottie/Skottie.cpp | 84 +++++++-------- experimental/skottie/SkottieAnimator.cpp | 22 +--- experimental/skottie/SkottieAnimator.h | 7 +- experimental/skottie/SkottieParser.cpp | 160 +++++++++++++++++++++++++++++ experimental/skottie/SkottieParser.h | 28 +++++ experimental/skottie/SkottiePriv.h | 42 -------- experimental/skottie/SkottieProperties.cpp | 101 +----------------- experimental/skottie/SkottieProperties.h | 4 +- 8 files changed, 245 insertions(+), 203 deletions(-) create mode 100644 experimental/skottie/SkottieParser.cpp create mode 100644 experimental/skottie/SkottieParser.h delete mode 100644 experimental/skottie/SkottiePriv.h (limited to 'experimental') 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; @@ -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::Parse(jpropK, &val)) { + if (Parse(jpropK, &val)) { // Static property. apply(val); return true; @@ -154,8 +156,8 @@ sk_sp 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 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(SK_ARRAY_COUNT(gTypes))) { LogFail(jstar, "Unknown polystar type"); return nullptr; @@ -308,14 +310,14 @@ sk_sp 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 gradient_node; sk_sp composite; - if (ParseInt(obj["t"], 1) == 1) { + if (ParseDefault(obj["t"], 1) == 1) { auto linear_node = sksg::LinearGradient::Make(); composite = sk_make_sp(linear_node, stopCount); gradient_node = std::move(linear_node); @@ -374,14 +376,14 @@ sk_sp 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(ParseInt(jstroke["lj"], 1) - 1, + stroke_node->setStrokeJoin(gJoins[SkTPin(ParseDefault(jstroke["lj"], 1) - 1, 0, SK_ARRAY_COUNT(gJoins) - 1)]); static constexpr SkPaint::Cap gCaps[] = { @@ -389,7 +391,7 @@ sk_sp AttachStroke(const Json::Value& jstroke, AttachContext* c SkPaint::kRound_Cap, SkPaint::kSquare_Cap, }; - stroke_node->setStrokeCap(gCaps[SkTPin(ParseInt(jstroke["lc"], 1) - 1, + stroke_node->setStrokeCap(gCaps[SkTPin(ParseDefault(jstroke["lc"], 1) - 1, 0, SK_ARRAY_COUNT(gCaps) - 1)]); return stroke_node; @@ -431,7 +433,7 @@ std::vector> AttachMergeGeometryEffect( sksg::Merge::Mode::kXOR , // "mm": 5 }; - const auto mode = gModes[SkTPin(ParseInt(jmerge["mm"], 1) - 1, + const auto mode = gModes[SkTPin(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> AttachTrimGeometryEffect( kSeparate, // "m": 2 } gModes[] = { Mode::kMerged, Mode::kSeparate }; - const auto mode = gModes[SkTPin(ParseInt(jtrim["m"], 1) - 1, + const auto mode = gModes[SkTPin(ParseDefault(jtrim["m"], 1) - 1, 0, SK_ARRAY_COUNT(gModes) - 1)]; std::vector> inputs; @@ -714,8 +716,8 @@ sk_sp AttachShape(const Json::Value& jshape, AttachShapeContex sk_sp 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 AttachCompLayer(const Json::Value& layer, AttachContext* sk_sp 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 AttachSolidLayer(const Json::Value& jlayer, AttachContex sk_sp 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 AttachImageAsset(const Json::Value& jimage, AttachContex sk_sp 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 AttachNullLayer(const Json::Value& layer, AttachContext* sk_sp AttachShapeLayer(const Json::Value& layer, AttachContext* ctx) { SkASSERT(layer.isObject()); - LOG("** Attaching shape layer ind: %d\n", ParseInt(layer["ind"], 0)); - std::vector> geometryStack; std::vector 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 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 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 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(SK_ARRAY_COUNT(gLayerAttachers))) { return nullptr; } @@ -989,15 +992,15 @@ sk_sp 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(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 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::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(); 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::Parse(k["s"], &fV0)) { + !Parse(k["s"], &fV0)) { return false; } if (!this->isHold() && - (!ValueTraits::Parse(k["e"], &fV1) || + (!Parse(k["e"], &fV1) || ValueTraits::Cardinality(fV0) != ValueTraits::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 + +namespace skottie { + +template <> +bool Parse(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(const Json::Value& jv, bool* v) { + if (jv.isNull() || !jv.isConvertibleTo(Json::booleanValue)) + return false; + + *v = jv.asBool(); + + return true; +} + +template <> +bool Parse(const Json::Value& jv, int* v) { + if (jv.isNull() || !jv.isConvertibleTo(Json::intValue)) + return false; + + *v = jv.asInt(); + + return true; +} + +template <> +bool Parse(const Json::Value& jv, SkString* v) { + if (jv.isNull() || !jv.isConvertibleTo(Json::stringValue)) + return false; + + v->set(jv.asCString()); + + return true; +} + +template <> +bool Parse(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>(const Json::Value& jv, std::vector* 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* pts) { + if (!jv.isArray()) + return false; + + pts->clear(); + pts->reserve(jv.size()); + + std::vector 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(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 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 +bool Parse(const Json::Value&, T*); + +template +static inline T ParseDefault(const Json::Value& jv, const T& defaultValue) { + T v; + if (!Parse(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, @@ -57,20 +37,6 @@ SkColor VecToColor(const float* v, size_t size) { } // namespace -template <> -bool ValueTraits::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::Cardinality(const ScalarValue&) { return 1; @@ -82,24 +48,6 @@ SkScalar ValueTraits::As(const ScalarValue& v) { return v; } -template <> -bool ValueTraits::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::Parse(v[i], &scalar)) - return false; - - vec->push_back(std::move(scalar)); - } - - return true; -} - template <> size_t ValueTraits::Cardinality(const VectorValue& vec) { return vec.size(); @@ -127,51 +75,6 @@ SkSize ValueTraits::As(const VectorValue& vec) { return SkSize::Make(pt.x(), pt.y()); } -template<> -bool ValueTraits::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::Cardinality(const ShapeValue& path) { return SkTo(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 struct ValueTraits { - static bool Parse(const Json::Value&, T*); static size_t Cardinality(const T&); template -- cgit v1.2.3