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