/* * 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 "SkottieJson.h" #include "SkData.h" #include "SkScalar.h" #include "SkPath.h" #include "SkPoint.h" #include "SkStream.h" #include "SkString.h" #include "SkottieValue.h" #include namespace skottie { using namespace skjson; template <> bool Parse(const Value& v, SkScalar* s) { // Some versions wrap values as single-element arrays. if (const skjson::ArrayValue* array = v) { if (array->size() == 1) { return Parse((*array)[0], s); } } if (const skjson::NumberValue* num = v) { *s = static_cast(**num); return true; } return false; } template <> bool Parse(const Value& v, bool* b) { switch(v.getType()) { case Value::Type::kNumber: *b = SkToBool(*v.as()); return true; case Value::Type::kBool: *b = *v.as(); return true; default: break; } return false; } template <> bool Parse(const Value& v, int* i) { if (const skjson::NumberValue* num = v) { const auto dbl = **num; *i = dbl; return *i == dbl; } return false; } template <> bool Parse(const Value& v, SkString* s) { if (const skjson::StringValue* sv = v) { s->set(sv->begin(), sv->size()); return true; } return false; } template <> bool Parse(const Value& v, SkPoint* pt) { if (!v.is()) return false; const auto& ov = v.as(); const auto& jvx = ov["x"]; const auto& jvy = ov["y"]; // Some BM versions seem to store x/y as single-element arrays. return Parse(jvx.is() ? jvx.as()[0] : jvx, &pt->fX) && Parse(jvy.is() ? jvy.as()[0] : jvy, &pt->fY); } template <> bool Parse>(const Value& v, std::vector* vec) { if (!v.is()) return false; const auto& av = v.as(); vec->resize(av.size()); for (size_t i = 0; i < av.size(); ++i) { if (!Parse(av[i], vec->data() + i)) { return false; } } return true; } namespace { bool ParsePointVec(const Value& v, std::vector* pts) { if (!v.is()) return false; const auto& av = v.as(); pts->clear(); pts->reserve(av.size()); std::vector vec; for (size_t i = 0; i < av.size(); ++i) { if (!Parse(av[i], &vec) || vec.size() != 2) return false; pts->push_back(SkPoint::Make(vec[0], vec[1])); } return true; } } // namespace template <> bool Parse(const Value& v, ShapeValue* sh) { SkASSERT(sh->fVertices.empty()); // Some versions wrap values as single-element arrays. if (const skjson::ArrayValue* av = v) { if (av->size() == 1) { return Parse((*av)[0], sh); } } if (!v.is()) return false; const auto& ov = v.as(); 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 (!ParsePointVec(ov["i"], &inPts) || !ParsePointVec(ov["o"], &outPts) || !ParsePointVec(ov["v"], &verts) || inPts.size() != outPts.size() || inPts.size() != verts.size()) { return false; } sh->fVertices.reserve(inPts.size()); for (size_t i = 0; i < inPts.size(); ++i) { sh->fVertices.push_back(BezierVertex({inPts[i], outPts[i], verts[i]})); } sh->fClosed = ParseDefault(ov["c"], false); return true; } } // namespace skottie