1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottieJson.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottieValue.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkJSON.h"
17*c8dee2aaSAndroid Build Coastguard Worker
18*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
19*c8dee2aaSAndroid Build Coastguard Worker #include <limits>
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker namespace skottie {
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker using namespace skjson;
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,SkScalar * s)26*c8dee2aaSAndroid Build Coastguard Worker bool Parse<SkScalar>(const Value& v, SkScalar* s) {
27*c8dee2aaSAndroid Build Coastguard Worker // Some versions wrap values as single-element arrays.
28*c8dee2aaSAndroid Build Coastguard Worker if (const skjson::ArrayValue* array = v) {
29*c8dee2aaSAndroid Build Coastguard Worker if (array->size() > 0) {
30*c8dee2aaSAndroid Build Coastguard Worker return Parse((*array)[0], s);
31*c8dee2aaSAndroid Build Coastguard Worker }
32*c8dee2aaSAndroid Build Coastguard Worker }
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker if (const skjson::NumberValue* num = v) {
35*c8dee2aaSAndroid Build Coastguard Worker *s = static_cast<SkScalar>(**num);
36*c8dee2aaSAndroid Build Coastguard Worker return true;
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker return false;
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,bool * b)43*c8dee2aaSAndroid Build Coastguard Worker bool Parse<bool>(const Value& v, bool* b) {
44*c8dee2aaSAndroid Build Coastguard Worker switch(v.getType()) {
45*c8dee2aaSAndroid Build Coastguard Worker case Value::Type::kNumber:
46*c8dee2aaSAndroid Build Coastguard Worker *b = SkToBool(*v.as<NumberValue>());
47*c8dee2aaSAndroid Build Coastguard Worker return true;
48*c8dee2aaSAndroid Build Coastguard Worker case Value::Type::kBool:
49*c8dee2aaSAndroid Build Coastguard Worker *b = *v.as<BoolValue>();
50*c8dee2aaSAndroid Build Coastguard Worker return true;
51*c8dee2aaSAndroid Build Coastguard Worker default:
52*c8dee2aaSAndroid Build Coastguard Worker break;
53*c8dee2aaSAndroid Build Coastguard Worker }
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker return false;
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
ParseIntegral(const Value & v,T * result)59*c8dee2aaSAndroid Build Coastguard Worker bool ParseIntegral(const Value& v, T* result) {
60*c8dee2aaSAndroid Build Coastguard Worker if (const skjson::NumberValue* num = v) {
61*c8dee2aaSAndroid Build Coastguard Worker const auto dbl = **num;
62*c8dee2aaSAndroid Build Coastguard Worker if (dbl > static_cast<double>(std::numeric_limits<T>::max()) ||
63*c8dee2aaSAndroid Build Coastguard Worker dbl < static_cast<double>(std::numeric_limits<T>::min())) {
64*c8dee2aaSAndroid Build Coastguard Worker return false;
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker
67*c8dee2aaSAndroid Build Coastguard Worker *result = static_cast<T>(dbl);
68*c8dee2aaSAndroid Build Coastguard Worker return true;
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker return false;
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,int * i)75*c8dee2aaSAndroid Build Coastguard Worker bool Parse<int>(const Value& v, int* i) {
76*c8dee2aaSAndroid Build Coastguard Worker return ParseIntegral(v, i);
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker
79*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,size_t * sz)80*c8dee2aaSAndroid Build Coastguard Worker bool Parse<size_t>(const Value& v, size_t* sz) {
81*c8dee2aaSAndroid Build Coastguard Worker return ParseIntegral(v, sz);
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,SkString * s)85*c8dee2aaSAndroid Build Coastguard Worker bool Parse<SkString>(const Value& v, SkString* s) {
86*c8dee2aaSAndroid Build Coastguard Worker if (const skjson::StringValue* sv = v) {
87*c8dee2aaSAndroid Build Coastguard Worker s->set(sv->begin(), sv->size());
88*c8dee2aaSAndroid Build Coastguard Worker return true;
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker return false;
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,SkV2 * v2)95*c8dee2aaSAndroid Build Coastguard Worker bool Parse<SkV2>(const Value& v, SkV2* v2) {
96*c8dee2aaSAndroid Build Coastguard Worker if (!v.is<ArrayValue>())
97*c8dee2aaSAndroid Build Coastguard Worker return false;
98*c8dee2aaSAndroid Build Coastguard Worker const auto& av = v.as<ArrayValue>();
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker // We need at least two scalars (BM sometimes exports a third value == 0).
101*c8dee2aaSAndroid Build Coastguard Worker return av.size() >= 2
102*c8dee2aaSAndroid Build Coastguard Worker && Parse<SkScalar>(av[0], &v2->x)
103*c8dee2aaSAndroid Build Coastguard Worker && Parse<SkScalar>(av[1], &v2->y);
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,SkPoint * pt)107*c8dee2aaSAndroid Build Coastguard Worker bool Parse<SkPoint>(const Value& v, SkPoint* pt) {
108*c8dee2aaSAndroid Build Coastguard Worker if (!v.is<ObjectValue>())
109*c8dee2aaSAndroid Build Coastguard Worker return false;
110*c8dee2aaSAndroid Build Coastguard Worker const auto& ov = v.as<ObjectValue>();
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker return Parse<SkScalar>(ov["x"], &pt->fX)
113*c8dee2aaSAndroid Build Coastguard Worker && Parse<SkScalar>(ov["y"], &pt->fY);
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker template <>
Parse(const Value & v,VectorValue * vec)117*c8dee2aaSAndroid Build Coastguard Worker bool Parse<VectorValue>(const Value& v, VectorValue* vec) {
118*c8dee2aaSAndroid Build Coastguard Worker if (!v.is<ArrayValue>())
119*c8dee2aaSAndroid Build Coastguard Worker return false;
120*c8dee2aaSAndroid Build Coastguard Worker const auto& av = v.as<ArrayValue>();
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker vec->resize(av.size());
123*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < av.size(); ++i) {
124*c8dee2aaSAndroid Build Coastguard Worker if (!Parse(av[i], vec->data() + i)) {
125*c8dee2aaSAndroid Build Coastguard Worker return false;
126*c8dee2aaSAndroid Build Coastguard Worker }
127*c8dee2aaSAndroid Build Coastguard Worker }
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker return true;
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker
ParseSlotID(const skjson::ObjectValue * jobj)132*c8dee2aaSAndroid Build Coastguard Worker const skjson::StringValue* ParseSlotID(const skjson::ObjectValue* jobj) {
133*c8dee2aaSAndroid Build Coastguard Worker if (jobj) {
134*c8dee2aaSAndroid Build Coastguard Worker if (const skjson::StringValue* sid = (*jobj)["sid"]) {
135*c8dee2aaSAndroid Build Coastguard Worker return sid;
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker }
138*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker } // namespace skottie
142