| /* | |
| * Copyright 2018 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "modules/skottie/src/SkottieJson.h" | |
| #include "include/core/SkM44.h" | |
| #include "include/core/SkPoint.h" | |
| #include "include/core/SkScalar.h" | |
| #include "include/core/SkString.h" | |
| #include "include/private/SkTo.h" | |
| #include "modules/jsonreader/SkJSONReader.h" | |
| #include "modules/skottie/src/SkottieValue.h" | |
| #include <cstddef> | |
| #include <limits> | |
| namespace skottie { | |
| using namespace skjson; | |
| template <> | |
| bool Parse<SkScalar>(const Value& v, SkScalar* s) { | |
| // Some versions wrap values as single-element arrays. | |
| if (const skjson::ArrayValue* array = v) { | |
| if (array->size() > 0) { | |
| return Parse((*array)[0], s); | |
| } | |
| } | |
| if (const skjson::NumberValue* num = v) { | |
| *s = static_cast<SkScalar>(**num); | |
| return true; | |
| } | |
| return false; | |
| } | |
| template <> | |
| bool Parse<bool>(const Value& v, bool* b) { | |
| switch(v.getType()) { | |
| case Value::Type::kNumber: | |
| *b = SkToBool(*v.as<NumberValue>()); | |
| return true; | |
| case Value::Type::kBool: | |
| *b = *v.as<BoolValue>(); | |
| return true; | |
| default: | |
| break; | |
| } | |
| return false; | |
| } | |
| template <typename T> | |
| bool ParseIntegral(const Value& v, T* result) { | |
| if (const skjson::NumberValue* num = v) { | |
| const auto dbl = **num; | |
| if (dbl > static_cast<double>(std::numeric_limits<T>::max()) || | |
| dbl < static_cast<double>(std::numeric_limits<T>::min())) { | |
| return false; | |
| } | |
| *result = static_cast<T>(dbl); | |
| return true; | |
| } | |
| return false; | |
| } | |
| template <> | |
| bool Parse<int>(const Value& v, int* i) { | |
| return ParseIntegral(v, i); | |
| } | |
| template <> | |
| bool Parse<size_t>(const Value& v, size_t* sz) { | |
| return ParseIntegral(v, sz); | |
| } | |
| template <> | |
| bool Parse<SkString>(const Value& v, SkString* s) { | |
| if (const skjson::StringValue* sv = v) { | |
| s->set(sv->begin(), sv->size()); | |
| return true; | |
| } | |
| return false; | |
| } | |
| template <> | |
| bool Parse<SkV2>(const Value& v, SkV2* v2) { | |
| if (!v.is<ArrayValue>()) | |
| return false; | |
| const auto& av = v.as<ArrayValue>(); | |
| // We need at least two scalars (BM sometimes exports a third value == 0). | |
| return av.size() >= 2 | |
| && Parse<SkScalar>(av[0], &v2->x) | |
| && Parse<SkScalar>(av[1], &v2->y); | |
| } | |
| template <> | |
| bool Parse<SkPoint>(const Value& v, SkPoint* pt) { | |
| if (!v.is<ObjectValue>()) | |
| return false; | |
| const auto& ov = v.as<ObjectValue>(); | |
| return Parse<SkScalar>(ov["x"], &pt->fX) | |
| && Parse<SkScalar>(ov["y"], &pt->fY); | |
| } | |
| template <> | |
| bool Parse<VectorValue>(const Value& v, VectorValue* vec) { | |
| if (!v.is<ArrayValue>()) | |
| return false; | |
| const auto& av = v.as<ArrayValue>(); | |
| vec->resize(av.size()); | |
| for (size_t i = 0; i < av.size(); ++i) { | |
| if (!Parse(av[i], vec->data() + i)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| const skjson::StringValue* ParseSlotID(const skjson::ObjectValue* jobj) { | |
| if (jobj) { | |
| if (const skjson::StringValue* sid = (*jobj)["sid"]) { | |
| return sid; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| } // namespace skottie |