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 | |
19 | namespace skottie { |
20 | |
21 | using namespace skjson; |
22 | |
23 | template <> |
24 | bool 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 | |
40 | template <> |
41 | bool 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 | |
56 | template <typename T> |
57 | bool 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 | |
67 | template <> |
68 | bool Parse<int>(const Value& v, int* i) { |
69 | return ParseIntegral(v, i); |
70 | } |
71 | |
72 | template <> |
73 | bool Parse<size_t>(const Value& v, size_t* sz) { |
74 | return ParseIntegral(v, sz); |
75 | } |
76 | |
77 | template <> |
78 | bool 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 | |
87 | template <> |
88 | bool 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 | |
99 | template <> |
100 | bool 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 | |
109 | template <> |
110 | bool 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 | |