diff options
Diffstat (limited to 'experimental/skottie/Skottie.cpp')
-rw-r--r-- | experimental/skottie/Skottie.cpp | 236 |
1 files changed, 109 insertions, 127 deletions
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp index c4e964d4ee..99549bfccd 100644 --- a/experimental/skottie/Skottie.cpp +++ b/experimental/skottie/Skottie.cpp @@ -8,10 +8,9 @@ #include "Skottie.h" #include "SkCanvas.h" -#include "SkJSONCPP.h" #include "SkottieAdapter.h" #include "SkottieAnimator.h" -#include "SkottieParser.h" +#include "SkottieJson.h" #include "SkottieValue.h" #include "SkData.h" #include "SkImage.h" @@ -53,7 +52,7 @@ namespace skottie { namespace { -using AssetMap = SkTHashMap<SkString, const Json::Value*>; +using AssetMap = SkTHashMap<SkString, json::ValueRef>; struct AttachContext { const ResourceProvider& fResources; @@ -62,13 +61,13 @@ struct AttachContext { sksg::AnimatorList& fAnimators; }; -bool LogFail(const Json::Value& json, const char* msg) { - const auto dump = json.toStyledString(); +bool LogFail(const json::ValueRef& json, const char* msg) { + const auto dump = json.toString(); LOG("!! %s: %s", msg, dump.c_str()); return false; } -sk_sp<sksg::Matrix> AttachMatrix(const Json::Value& t, AttachContext* ctx, +sk_sp<sksg::Matrix> AttachMatrix(const json::ValueRef& t, AttachContext* ctx, sk_sp<sksg::Matrix> parentMatrix) { if (!t.isObject()) return nullptr; @@ -88,13 +87,13 @@ sk_sp<sksg::Matrix> AttachMatrix(const Json::Value& t, AttachContext* ctx, adapter->setScale(ValueTraits<VectorValue>::As<SkVector>(s)); }); - auto* jrotation = &t["r"]; - if (jrotation->isNull()) { + auto jrotation = t["r"]; + if (jrotation.isNull()) { // 3d rotations have separate rx,ry,rz components. While we don't fully support them, // we can still make use of rz. - jrotation = &t["rz"]; + jrotation = t["rz"]; } - auto rotation_attached = BindProperty<ScalarValue>(*jrotation, &ctx->fAnimators, + auto rotation_attached = BindProperty<ScalarValue>(jrotation, &ctx->fAnimators, [adapter](const ScalarValue& r) { adapter->setRotation(r); }); @@ -120,7 +119,7 @@ sk_sp<sksg::Matrix> AttachMatrix(const Json::Value& t, AttachContext* ctx, return matrix; } -sk_sp<sksg::RenderNode> AttachOpacity(const Json::Value& jtransform, AttachContext* ctx, +sk_sp<sksg::RenderNode> AttachOpacity(const json::ValueRef& jtransform, AttachContext* ctx, sk_sp<sksg::RenderNode> childNode) { if (!jtransform.isObject() || !childNode) return childNode; @@ -129,8 +128,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() && - !ParseDefault(opacity["a"], true) && - ParseDefault(opacity["k"], -1) == 100) { + !opacity["a"].toDefault(true) && + opacity["k"].toDefault<int>(-1) == 100) { // Ignoring static full opacity. return childNode; } @@ -145,9 +144,9 @@ sk_sp<sksg::RenderNode> AttachOpacity(const Json::Value& jtransform, AttachConte return std::move(opacityNode); } -sk_sp<sksg::RenderNode> AttachComposition(const Json::Value&, AttachContext* ctx); +sk_sp<sksg::RenderNode> AttachComposition(const json::ValueRef&, AttachContext* ctx); -sk_sp<sksg::Path> AttachPath(const Json::Value& jpath, AttachContext* ctx) { +sk_sp<sksg::Path> AttachPath(const json::ValueRef& jpath, AttachContext* ctx) { auto path_node = sksg::Path::Make(); return BindProperty<ShapeValue>(jpath, &ctx->fAnimators, [path_node](const ShapeValue& p) { @@ -157,13 +156,13 @@ sk_sp<sksg::Path> AttachPath(const Json::Value& jpath, AttachContext* ctx) { : nullptr; } -sk_sp<sksg::GeometryNode> AttachPathGeometry(const Json::Value& jpath, AttachContext* ctx) { +sk_sp<sksg::GeometryNode> AttachPathGeometry(const json::ValueRef& jpath, AttachContext* ctx) { SkASSERT(jpath.isObject()); return AttachPath(jpath["ks"], ctx); } -sk_sp<sksg::GeometryNode> AttachRRectGeometry(const Json::Value& jrect, AttachContext* ctx) { +sk_sp<sksg::GeometryNode> AttachRRectGeometry(const json::ValueRef& jrect, AttachContext* ctx) { SkASSERT(jrect.isObject()); auto rect_node = sksg::RRect::Make(); @@ -189,7 +188,7 @@ sk_sp<sksg::GeometryNode> AttachRRectGeometry(const Json::Value& jrect, AttachCo return std::move(rect_node); } -sk_sp<sksg::GeometryNode> AttachEllipseGeometry(const Json::Value& jellipse, AttachContext* ctx) { +sk_sp<sksg::GeometryNode> AttachEllipseGeometry(const json::ValueRef& jellipse, AttachContext* ctx) { SkASSERT(jellipse.isObject()); auto rect_node = sksg::RRect::Make(); @@ -213,7 +212,7 @@ sk_sp<sksg::GeometryNode> AttachEllipseGeometry(const Json::Value& jellipse, Att return std::move(rect_node); } -sk_sp<sksg::GeometryNode> AttachPolystarGeometry(const Json::Value& jstar, AttachContext* ctx) { +sk_sp<sksg::GeometryNode> AttachPolystarGeometry(const json::ValueRef& jstar, AttachContext* ctx) { SkASSERT(jstar.isObject()); static constexpr PolyStarAdapter::Type gTypes[] = { @@ -221,7 +220,7 @@ sk_sp<sksg::GeometryNode> AttachPolystarGeometry(const Json::Value& jstar, Attac PolyStarAdapter::Type::kPoly, // "sy": 2 }; - const auto type = ParseDefault(jstar["sy"], 0) - 1; + const auto type = jstar["sy"].toDefault<int>(0) - 1; if (type < 0 || type >= SkTo<int>(SK_ARRAY_COUNT(gTypes))) { LogFail(jstar, "Unknown polystar type"); return nullptr; @@ -262,7 +261,7 @@ sk_sp<sksg::GeometryNode> AttachPolystarGeometry(const Json::Value& jstar, Attac return std::move(path_node); } -sk_sp<sksg::Color> AttachColor(const Json::Value& obj, AttachContext* ctx) { +sk_sp<sksg::Color> AttachColor(const json::ValueRef& obj, AttachContext* ctx) { SkASSERT(obj.isObject()); auto color_node = sksg::Color::Make(SK_ColorBLACK); @@ -274,21 +273,21 @@ sk_sp<sksg::Color> AttachColor(const Json::Value& obj, AttachContext* ctx) { return color_attached ? color_node : nullptr; } -sk_sp<sksg::Gradient> AttachGradient(const Json::Value& obj, AttachContext* ctx) { +sk_sp<sksg::Gradient> AttachGradient(const json::ValueRef& obj, AttachContext* ctx) { SkASSERT(obj.isObject()); const auto& stops = obj["g"]; if (!stops.isObject()) return nullptr; - const auto stopCount = ParseDefault(stops["p"], -1); + const auto stopCount = stops["p"].toDefault<int>(-1); if (stopCount < 0) return nullptr; sk_sp<sksg::Gradient> gradient_node; sk_sp<GradientAdapter> adapter; - if (ParseDefault(obj["t"], 1) == 1) { + if (obj["t"].toDefault<int>(1) == 1) { auto linear_node = sksg::LinearGradient::Make(); adapter = sk_make_sp<LinearGradientAdapter>(linear_node, stopCount); gradient_node = std::move(linear_node); @@ -316,7 +315,7 @@ sk_sp<sksg::Gradient> AttachGradient(const Json::Value& obj, AttachContext* ctx) return gradient_node; } -sk_sp<sksg::PaintNode> AttachPaint(const Json::Value& jpaint, AttachContext* ctx, +sk_sp<sksg::PaintNode> AttachPaint(const json::ValueRef& jpaint, AttachContext* ctx, sk_sp<sksg::PaintNode> paint_node) { if (paint_node) { paint_node->setAntiAlias(true); @@ -331,7 +330,7 @@ sk_sp<sksg::PaintNode> AttachPaint(const Json::Value& jpaint, AttachContext* ctx return paint_node; } -sk_sp<sksg::PaintNode> AttachStroke(const Json::Value& jstroke, AttachContext* ctx, +sk_sp<sksg::PaintNode> AttachStroke(const json::ValueRef& jstroke, AttachContext* ctx, sk_sp<sksg::PaintNode> stroke_node) { SkASSERT(jstroke.isObject()); @@ -347,14 +346,14 @@ sk_sp<sksg::PaintNode> AttachStroke(const Json::Value& jstroke, AttachContext* c if (!width_attached) return nullptr; - stroke_node->setStrokeMiter(ParseDefault(jstroke["ml"], 4.0f)); + stroke_node->setStrokeMiter(jstroke["ml"].toDefault(4.0f)); static constexpr SkPaint::Join gJoins[] = { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join, }; - stroke_node->setStrokeJoin(gJoins[SkTPin<int>(ParseDefault(jstroke["lj"], 1) - 1, + stroke_node->setStrokeJoin(gJoins[SkTPin<int>(jstroke["lj"].toDefault<int>(1) - 1, 0, SK_ARRAY_COUNT(gJoins) - 1)]); static constexpr SkPaint::Cap gCaps[] = { @@ -362,38 +361,38 @@ sk_sp<sksg::PaintNode> AttachStroke(const Json::Value& jstroke, AttachContext* c SkPaint::kRound_Cap, SkPaint::kSquare_Cap, }; - stroke_node->setStrokeCap(gCaps[SkTPin<int>(ParseDefault(jstroke["lc"], 1) - 1, + stroke_node->setStrokeCap(gCaps[SkTPin<int>(jstroke["lc"].toDefault<int>(1) - 1, 0, SK_ARRAY_COUNT(gCaps) - 1)]); return stroke_node; } -sk_sp<sksg::PaintNode> AttachColorFill(const Json::Value& jfill, AttachContext* ctx) { +sk_sp<sksg::PaintNode> AttachColorFill(const json::ValueRef& jfill, AttachContext* ctx) { SkASSERT(jfill.isObject()); return AttachPaint(jfill, ctx, AttachColor(jfill, ctx)); } -sk_sp<sksg::PaintNode> AttachGradientFill(const Json::Value& jfill, AttachContext* ctx) { +sk_sp<sksg::PaintNode> AttachGradientFill(const json::ValueRef& jfill, AttachContext* ctx) { SkASSERT(jfill.isObject()); return AttachPaint(jfill, ctx, AttachGradient(jfill, ctx)); } -sk_sp<sksg::PaintNode> AttachColorStroke(const Json::Value& jstroke, AttachContext* ctx) { +sk_sp<sksg::PaintNode> AttachColorStroke(const json::ValueRef& jstroke, AttachContext* ctx) { SkASSERT(jstroke.isObject()); return AttachStroke(jstroke, ctx, AttachPaint(jstroke, ctx, AttachColor(jstroke, ctx))); } -sk_sp<sksg::PaintNode> AttachGradientStroke(const Json::Value& jstroke, AttachContext* ctx) { +sk_sp<sksg::PaintNode> AttachGradientStroke(const json::ValueRef& jstroke, AttachContext* ctx) { SkASSERT(jstroke.isObject()); return AttachStroke(jstroke, ctx, AttachPaint(jstroke, ctx, AttachGradient(jstroke, ctx))); } std::vector<sk_sp<sksg::GeometryNode>> AttachMergeGeometryEffect( - const Json::Value& jmerge, AttachContext* ctx, std::vector<sk_sp<sksg::GeometryNode>>&& geos) { + const json::ValueRef& jmerge, AttachContext* ctx, std::vector<sk_sp<sksg::GeometryNode>>&& geos) { std::vector<sk_sp<sksg::GeometryNode>> merged; static constexpr sksg::Merge::Mode gModes[] = { @@ -404,7 +403,7 @@ std::vector<sk_sp<sksg::GeometryNode>> AttachMergeGeometryEffect( sksg::Merge::Mode::kXOR , // "mm": 5 }; - const auto mode = gModes[SkTPin<int>(ParseDefault(jmerge["mm"], 1) - 1, + const auto mode = gModes[SkTPin<int>(jmerge["mm"].toDefault(1) - 1, 0, SK_ARRAY_COUNT(gModes) - 1)]; merged.push_back(sksg::Merge::Make(std::move(geos), mode)); @@ -412,14 +411,14 @@ std::vector<sk_sp<sksg::GeometryNode>> AttachMergeGeometryEffect( } std::vector<sk_sp<sksg::GeometryNode>> AttachTrimGeometryEffect( - const Json::Value& jtrim, AttachContext* ctx, std::vector<sk_sp<sksg::GeometryNode>>&& geos) { + const json::ValueRef& jtrim, AttachContext* ctx, std::vector<sk_sp<sksg::GeometryNode>>&& geos) { enum class Mode { kMerged, // "m": 1 kSeparate, // "m": 2 } gModes[] = { Mode::kMerged, Mode::kSeparate }; - const auto mode = gModes[SkTPin<int>(ParseDefault(jtrim["m"], 1) - 1, + const auto mode = gModes[SkTPin<int>(jtrim["m"].toDefault(1) - 1, 0, SK_ARRAY_COUNT(gModes) - 1)]; std::vector<sk_sp<sksg::GeometryNode>> inputs; @@ -454,7 +453,7 @@ std::vector<sk_sp<sksg::GeometryNode>> AttachTrimGeometryEffect( } std::vector<sk_sp<sksg::GeometryNode>> AttachRoundGeometryEffect( - const Json::Value& jtrim, AttachContext* ctx, std::vector<sk_sp<sksg::GeometryNode>>&& geos) { + const json::ValueRef& jtrim, AttachContext* ctx, std::vector<sk_sp<sksg::GeometryNode>>&& geos) { std::vector<sk_sp<sksg::GeometryNode>> rounded; rounded.reserve(geos.size()); @@ -472,7 +471,7 @@ std::vector<sk_sp<sksg::GeometryNode>> AttachRoundGeometryEffect( return rounded; } -using GeometryAttacherT = sk_sp<sksg::GeometryNode> (*)(const Json::Value&, AttachContext*); +using GeometryAttacherT = sk_sp<sksg::GeometryNode> (*)(const json::ValueRef&, AttachContext*); static constexpr GeometryAttacherT gGeometryAttachers[] = { AttachPathGeometry, AttachRRectGeometry, @@ -480,7 +479,7 @@ static constexpr GeometryAttacherT gGeometryAttachers[] = { AttachPolystarGeometry, }; -using PaintAttacherT = sk_sp<sksg::PaintNode> (*)(const Json::Value&, AttachContext*); +using PaintAttacherT = sk_sp<sksg::PaintNode> (*)(const json::ValueRef&, AttachContext*); static constexpr PaintAttacherT gPaintAttachers[] = { AttachColorFill, AttachColorStroke, @@ -489,7 +488,7 @@ static constexpr PaintAttacherT gPaintAttachers[] = { }; using GeometryEffectAttacherT = - std::vector<sk_sp<sksg::GeometryNode>> (*)(const Json::Value&, + std::vector<sk_sp<sksg::GeometryNode>> (*)(const json::ValueRef&, AttachContext*, std::vector<sk_sp<sksg::GeometryNode>>&&); static constexpr GeometryEffectAttacherT gGeometryEffectAttachers[] = { @@ -512,7 +511,7 @@ struct ShapeInfo { uint32_t fAttacherIndex; // index into respective attacher tables }; -const ShapeInfo* FindShapeInfo(const Json::Value& shape) { +const ShapeInfo* FindShapeInfo(const json::ValueRef& shape) { static constexpr ShapeInfo gShapeInfo[] = { { "el", ShapeType::kGeometry , 2 }, // ellipse -> AttachEllipseGeometry { "fl", ShapeType::kPaint , 0 }, // fill -> AttachColorFill @@ -532,11 +531,11 @@ const ShapeInfo* FindShapeInfo(const Json::Value& shape) { if (!shape.isObject()) return nullptr; - const auto& type = shape["ty"]; - if (!type.isString()) + const auto type = shape["ty"].toDefault(SkString()); + if (type.isEmpty()) return nullptr; - const auto* info = bsearch(type.asCString(), + const auto* info = bsearch(type.c_str(), gShapeInfo, SK_ARRAY_COUNT(gShapeInfo), sizeof(ShapeInfo), @@ -549,7 +548,7 @@ const ShapeInfo* FindShapeInfo(const Json::Value& shape) { } struct GeometryEffectRec { - const Json::Value& fJson; + const json::ValueRef fJson; GeometryEffectAttacherT fAttach; }; @@ -569,7 +568,7 @@ struct AttachShapeContext { size_t fCommittedAnimators; }; -sk_sp<sksg::RenderNode> AttachShape(const Json::Value& jshape, AttachShapeContext* shapeCtx) { +sk_sp<sksg::RenderNode> AttachShape(const json::ValueRef& jshape, AttachShapeContext* shapeCtx) { if (!jshape.isArray()) return nullptr; @@ -580,7 +579,7 @@ sk_sp<sksg::RenderNode> AttachShape(const Json::Value& jshape, AttachShapeContex sk_sp<sksg::Matrix> shape_matrix; struct ShapeRec { - const Json::Value& fJson; + const json::ValueRef fJson; const ShapeInfo& fInfo; }; @@ -591,8 +590,8 @@ sk_sp<sksg::RenderNode> AttachShape(const Json::Value& jshape, AttachShapeContex // * store recs for next pass // std::vector<ShapeRec> recs; - for (Json::ArrayIndex i = 0; i < jshape.size(); ++i) { - const auto& s = jshape[jshape.size() - 1 - i]; + for (size_t i = 0; i < jshape.size(); ++i) { + const auto s = jshape[jshape.size() - 1 - i]; const auto* info = FindShapeInfo(s); if (!info) { LogFail(s.isObject() ? s["ty"] : s, "Unknown shape"); @@ -765,18 +764,18 @@ sk_sp<sksg::RenderNode> AttachNestedAnimation(const char* path, AttachContext* c return sk_make_sp<SkottieSGAdapter>(std::move(animation)); } -sk_sp<sksg::RenderNode> AttachCompLayer(const Json::Value& jlayer, AttachContext* ctx, +sk_sp<sksg::RenderNode> AttachCompLayer(const json::ValueRef& jlayer, AttachContext* ctx, float* time_bias, float* time_scale) { SkASSERT(jlayer.isObject()); SkString refId; - if (!Parse(jlayer["refId"], &refId) || refId.isEmpty()) { + if (!jlayer["refId"].to(&refId) || refId.isEmpty()) { LOG("!! Comp layer missing refId\n"); return nullptr; } - const auto start_time = ParseDefault(jlayer["st"], 0.0f), - stretch_time = ParseDefault(jlayer["sr"], 1.0f); + const auto start_time = jlayer["st"].toDefault(0.0f), + stretch_time = jlayer["sr"].toDefault(1.0f); *time_bias = -start_time; *time_scale = 1 / stretch_time; @@ -795,16 +794,16 @@ sk_sp<sksg::RenderNode> AttachCompLayer(const Json::Value& jlayer, AttachContext } // TODO: cycle detection - return AttachComposition(**comp, ctx); + return AttachComposition(*comp, ctx); } -sk_sp<sksg::RenderNode> AttachSolidLayer(const Json::Value& jlayer, AttachContext*, +sk_sp<sksg::RenderNode> AttachSolidLayer(const json::ValueRef& jlayer, AttachContext*, float*, float*) { SkASSERT(jlayer.isObject()); - const auto size = SkSize::Make(ParseDefault(jlayer["sw"], 0.0f), - ParseDefault(jlayer["sh"], 0.0f)); - const auto hex = ParseDefault(jlayer["sc"], SkString()); + const auto size = SkSize::Make(jlayer["sw"].toDefault(0.0f), + jlayer["sh"].toDefault(0.0f)); + const auto hex = jlayer["sc"].toDefault(SkString()); uint32_t c; if (size.isEmpty() || !hex.startsWith("#") || @@ -819,11 +818,11 @@ sk_sp<sksg::RenderNode> AttachSolidLayer(const Json::Value& jlayer, AttachContex sksg::Color::Make(color)); } -sk_sp<sksg::RenderNode> AttachImageAsset(const Json::Value& jimage, AttachContext* ctx) { +sk_sp<sksg::RenderNode> AttachImageAsset(const json::ValueRef& jimage, AttachContext* ctx) { SkASSERT(jimage.isObject()); - const auto name = ParseDefault(jimage["p"], SkString()), - path = ParseDefault(jimage["u"], SkString()); + const auto name = jimage["p"].toDefault(SkString()), + path = jimage["u"].toDefault(SkString()); if (name.isEmpty()) return nullptr; @@ -840,12 +839,12 @@ sk_sp<sksg::RenderNode> AttachImageAsset(const Json::Value& jimage, AttachContex SkImage::MakeFromEncoded(SkData::MakeFromStream(resStream.get(), resStream->getLength()))); } -sk_sp<sksg::RenderNode> AttachImageLayer(const Json::Value& layer, AttachContext* ctx, +sk_sp<sksg::RenderNode> AttachImageLayer(const json::ValueRef& layer, AttachContext* ctx, float*, float*) { SkASSERT(layer.isObject()); SkString refId; - if (!Parse(layer["refId"], &refId) || refId.isEmpty()) { + if (!layer["refId"].to(&refId) || refId.isEmpty()) { LOG("!! Image layer missing refId\n"); return nullptr; } @@ -856,10 +855,10 @@ sk_sp<sksg::RenderNode> AttachImageLayer(const Json::Value& layer, AttachContext return nullptr; } - return AttachImageAsset(**jimage, ctx); + return AttachImageAsset(*jimage, ctx); } -sk_sp<sksg::RenderNode> AttachNullLayer(const Json::Value& layer, AttachContext*, float*, float*) { +sk_sp<sksg::RenderNode> AttachNullLayer(const json::ValueRef& layer, AttachContext*, float*, float*) { SkASSERT(layer.isObject()); // Null layers are used solely to drive dependent transforms, @@ -867,7 +866,7 @@ sk_sp<sksg::RenderNode> AttachNullLayer(const Json::Value& layer, AttachContext* return nullptr; } -sk_sp<sksg::RenderNode> AttachShapeLayer(const Json::Value& layer, AttachContext* ctx, +sk_sp<sksg::RenderNode> AttachShapeLayer(const json::ValueRef& layer, AttachContext* ctx, float*, float*) { SkASSERT(layer.isObject()); @@ -886,7 +885,7 @@ sk_sp<sksg::RenderNode> AttachShapeLayer(const Json::Value& layer, AttachContext return shapeNode; } -sk_sp<sksg::RenderNode> AttachTextLayer(const Json::Value& layer, AttachContext*, float*, float*) { +sk_sp<sksg::RenderNode> AttachTextLayer(const json::ValueRef& layer, AttachContext*, float*, float*) { SkASSERT(layer.isObject()); LOG("?? Text layer stub\n"); @@ -894,42 +893,40 @@ sk_sp<sksg::RenderNode> AttachTextLayer(const Json::Value& layer, AttachContext* } struct AttachLayerContext { - AttachLayerContext(const Json::Value& jlayers, AttachContext* ctx) + AttachLayerContext(const json::ValueRef& jlayers, AttachContext* ctx) : fLayerList(jlayers), fCtx(ctx) {} - const Json::Value& fLayerList; + const json::ValueRef fLayerList; AttachContext* fCtx; SkTHashMap<int, sk_sp<sksg::Matrix>> fLayerMatrixMap; sk_sp<sksg::RenderNode> fCurrentMatte; - sk_sp<sksg::Matrix> AttachParentLayerMatrix(const Json::Value& jlayer) { + sk_sp<sksg::Matrix> AttachParentLayerMatrix(const json::ValueRef& jlayer) { SkASSERT(jlayer.isObject()); SkASSERT(fLayerList.isArray()); - const auto parent_index = ParseDefault(jlayer["parent"], -1); + const auto parent_index = jlayer["parent"].toDefault<int>(-1); if (parent_index < 0) return nullptr; if (auto* m = fLayerMatrixMap.find(parent_index)) return *m; - for (const auto& l : fLayerList) { - if (!l.isObject()) { - continue; - } - - if (ParseDefault(l["ind"], -1) == parent_index) { - return this->AttachLayerMatrix(l); + sk_sp<sksg::Matrix> matrix; + for (const json::ValueRef l : fLayerList) { + if (l["ind"].toDefault<int>(-1) == parent_index) { + matrix = this->AttachLayerMatrix(l); + break; } } return nullptr; } - sk_sp<sksg::Matrix> AttachLayerMatrix(const Json::Value& jlayer) { + sk_sp<sksg::Matrix> AttachLayerMatrix(const json::ValueRef& jlayer) { SkASSERT(jlayer.isObject()); - const auto layer_index = ParseDefault(jlayer["ind"], -1); + const auto layer_index = jlayer["ind"].toDefault<int>(-1); if (layer_index < 0) return nullptr; @@ -962,7 +959,7 @@ SkBlendMode MaskBlendMode(char mode) { return SkBlendMode::kSrcOver; } -sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask, +sk_sp<sksg::RenderNode> AttachMask(const json::ValueRef& jmask, AttachContext* ctx, sk_sp<sksg::RenderNode> childNode) { if (!jmask.isArray()) @@ -977,7 +974,7 @@ sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask, bool opaque_mask = true; - for (const auto& m : jmask) { + for (const json::ValueRef m : jmask) { if (!m.isObject()) continue; @@ -987,12 +984,12 @@ sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask, continue; } - mask_path->setFillType(ParseDefault(m["inv"], false) + mask_path->setFillType(m["inv"].toDefault(false) ? SkPath::kInverseWinding_FillType : SkPath::kWinding_FillType); SkString mode; - if (!Parse(m["mode"], &mode) || + if (!m["mode"].to(&mode) || mode.size() != 1 || !strcmp(mode.c_str(), "n")) { // "None" masks have no effect. continue; @@ -1031,12 +1028,11 @@ sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask, return sksg::MaskEffect::Make(std::move(childNode), std::move(mask_group)); } -sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, - AttachLayerContext* layerCtx) { +sk_sp<sksg::RenderNode> AttachLayer(const json::ValueRef& jlayer, AttachLayerContext* layerCtx) { if (!jlayer.isObject()) return nullptr; - using LayerAttacher = sk_sp<sksg::RenderNode> (*)(const Json::Value&, AttachContext*, + using LayerAttacher = sk_sp<sksg::RenderNode> (*)(const json::ValueRef&, AttachContext*, float* time_bias, float* time_scale); static constexpr LayerAttacher gLayerAttachers[] = { AttachCompLayer, // 'ty': 0 @@ -1047,7 +1043,7 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, AttachTextLayer, // 'ty': 5 }; - int type = ParseDefault(jlayer["ty"], -1); + int type = jlayer["ty"].toDefault<int>(-1); if (type < 0 || type >= SkTo<int>(SK_ARRAY_COUNT(gLayerAttachers))) { return nullptr; } @@ -1066,8 +1062,8 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, auto layer = gLayerAttachers[type](jlayer, &local_ctx, &time_bias, &time_scale); // Clip layers with explicit dimensions. - float w, h; - if (Parse(jlayer["w"], &w) && Parse(jlayer["h"], &h)) { + float w = 0, h = 0; + if (jlayer["w"].to(&w) && jlayer["h"].to(&h)) { layer = sksg::ClipEffect::Make(std::move(layer), sksg::Rect::Make(SkRect::MakeWH(w, h)), true); @@ -1120,8 +1116,8 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, }; auto controller_node = sksg::OpacityEffect::Make(std::move(layer)); - const auto in = ParseDefault(jlayer["ip"], 0.0f), - out = ParseDefault(jlayer["op"], in); + const auto in = jlayer["ip"].toDefault(0.0f), + out = jlayer["op"].toDefault(in); if (!jlayer["tm"].isNull()) { LogFail(jlayer["tm"], "Unsupported time remapping"); @@ -1138,7 +1134,7 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, time_bias, time_scale)); - if (ParseDefault(jlayer["td"], false)) { + if (jlayer["td"].toDefault(false)) { // This layer is a matte. We apply it as a mask to the next layer. layerCtx->fCurrentMatte = std::move(controller_node); return nullptr; @@ -1150,7 +1146,7 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, sksg::MaskEffect::Mode::kNormal, // tt: 1 sksg::MaskEffect::Mode::kInvert, // tt: 2 }; - const auto matteType = ParseDefault(jlayer["tt"], 1) - 1; + const auto matteType = jlayer["tt"].toDefault<int>(1) - 1; if (matteType >= 0 && matteType < SkTo<int>(SK_ARRAY_COUNT(gMaskModes))) { return sksg::MaskEffect::Make(std::move(controller_node), @@ -1163,18 +1159,18 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, return std::move(controller_node); } -sk_sp<sksg::RenderNode> AttachComposition(const Json::Value& comp, AttachContext* ctx) { +sk_sp<sksg::RenderNode> AttachComposition(const json::ValueRef& comp, AttachContext* ctx) { if (!comp.isObject()) return nullptr; - const auto& jlayers = comp["layers"]; + const auto jlayers = comp["layers"]; if (!jlayers.isArray()) return nullptr; SkSTArray<16, sk_sp<sksg::RenderNode>, true> layers; AttachLayerContext layerCtx(jlayers, ctx); - for (const auto& l : jlayers) { + for (const json::ValueRef l : jlayers) { if (auto layer_fragment = AttachLayer(l, &layerCtx)) { layers.push_back(std::move(layer_fragment)); } @@ -1207,33 +1203,21 @@ sk_sp<Animation> Animation::Make(SkStream* stream, const ResourceProvider& res, return nullptr; } + stats->fJsonSize = stream->getLength(); const auto t0 = SkTime::GetMSecs(); - Json::Value json; - { - auto data = SkData::MakeFromStream(stream, stream->getLength()); - if (!data) { - LOG("!! could not read stream\n"); - return nullptr; - } - stats->fJsonSize = data->size(); - - Json::Reader reader; - - auto dataStart = static_cast<const char*>(data->data()); - if (!reader.parse(dataStart, dataStart + data->size(), json, false) || !json.isObject()) { - LOG("!! failed to parse json: %s\n", reader.getFormattedErrorMessages().c_str()); - return nullptr; - } - } + const json::Document doc(stream); + const auto json = doc.root(); + if (!json.isObject()) + return nullptr; 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)); - const auto fps = ParseDefault(json["fr"], -1.0f); + const auto version = json["v"].toDefault(SkString()); + const auto size = SkSize::Make(json["w"].toDefault(0.0f), + json["h"].toDefault(0.0f)); + const auto fps = json["fr"].toDefault(-1.0f); if (size.isEmpty() || version.isEmpty() || fps <= 0) { LOG("!! invalid animation params (version: %s, size: [%f %f], frame rate: %f)", @@ -1278,21 +1262,19 @@ sk_sp<Animation> Animation::MakeFromFile(const char path[], const ResourceProvid } 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::ValueRef& json, Stats* stats) : fVersion(std::move(version)) , fSize(size) , fFrameRate(fps) - , fInPoint(ParseDefault(json["ip"], 0.0f)) - , fOutPoint(SkTMax(ParseDefault(json["op"], SK_ScalarMax), fInPoint)) { + , fInPoint(json["ip"].toDefault(0.0f)) + , fOutPoint(SkTMax(json["op"].toDefault(SK_ScalarMax), fInPoint)) { AssetMap assets; - for (const auto& asset : json["assets"]) { - if (!asset.isObject()) { - continue; + for (const json::ValueRef asset : json["assets"]) { + if (asset.isObject()) { + assets.set(asset["id"].toDefault(SkString()), asset); } - - assets.set(ParseDefault(asset["id"], SkString()), &asset); } sksg::AnimatorList animators; |