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