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