blob: 23221af99ee6ebf73c1ea9df3abffede94e44015 [file] [log] [blame]
Florin Malitafa7e9a82018-05-04 15:10:54 -04001/*
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 "SkottieJson.h"
9
10#include "SkData.h"
11#include "SkScalar.h"
12#include "SkPath.h"
13#include "SkPoint.h"
14#include "SkStream.h"
15#include "SkString.h"
16#include "SkottieValue.h"
Florin Malitafa7e9a82018-05-04 15:10:54 -040017#include <vector>
18
19namespace skottie {
20
Florin Malita7d42c442018-06-14 16:16:01 -040021using namespace skjson;
Florin Malitafa7e9a82018-05-04 15:10:54 -040022
23template <>
Florin Malita7d42c442018-06-14 16:16:01 -040024bool Parse<SkScalar>(const Value& v, SkScalar* s) {
Florin Malitafa7e9a82018-05-04 15:10:54 -040025 // Some versions wrap values as single-element arrays.
Florin Malita7d42c442018-06-14 16:16:01 -040026 if (const skjson::ArrayValue* array = v) {
Florin Malitaf5ac9062018-06-19 12:55:53 -040027 if (array->size() > 0) {
Florin Malita7d42c442018-06-14 16:16:01 -040028 return Parse((*array)[0], s);
29 }
Florin Malitafa7e9a82018-05-04 15:10:54 -040030 }
31
Florin Malita7d42c442018-06-14 16:16:01 -040032 if (const skjson::NumberValue* num = v) {
33 *s = static_cast<SkScalar>(**num);
34 return true;
35 }
Florin Malitafa7e9a82018-05-04 15:10:54 -040036
Florin Malita7d42c442018-06-14 16:16:01 -040037 return false;
Florin Malitafa7e9a82018-05-04 15:10:54 -040038}
39
40template <>
Florin Malita7d42c442018-06-14 16:16:01 -040041bool Parse<bool>(const Value& v, bool* b) {
42 switch(v.getType()) {
43 case Value::Type::kNumber:
44 *b = SkToBool(*v.as<NumberValue>());
Florin Malitafa7e9a82018-05-04 15:10:54 -040045 return true;
Florin Malita7d42c442018-06-14 16:16:01 -040046 case Value::Type::kBool:
47 *b = *v.as<BoolValue>();
Florin Malitafa7e9a82018-05-04 15:10:54 -040048 return true;
49 default:
50 break;
51 }
52
53 return false;
54}
55
56template <>
Florin Malita7d42c442018-06-14 16:16:01 -040057bool Parse<int>(const Value& v, int* i) {
58 if (const skjson::NumberValue* num = v) {
59 const auto dbl = **num;
60 *i = dbl;
61 return *i == dbl;
62 }
Florin Malitafa7e9a82018-05-04 15:10:54 -040063
Florin Malita7d42c442018-06-14 16:16:01 -040064 return false;
Florin Malitafa7e9a82018-05-04 15:10:54 -040065}
66
67template <>
Florin Malita7d42c442018-06-14 16:16:01 -040068bool Parse<SkString>(const Value& v, SkString* s) {
69 if (const skjson::StringValue* sv = v) {
70 s->set(sv->begin(), sv->size());
71 return true;
72 }
Florin Malitafa7e9a82018-05-04 15:10:54 -040073
Florin Malita7d42c442018-06-14 16:16:01 -040074 return false;
Florin Malitafa7e9a82018-05-04 15:10:54 -040075}
76
77template <>
Florin Malita7d42c442018-06-14 16:16:01 -040078bool Parse<SkPoint>(const Value& v, SkPoint* pt) {
79 if (!v.is<ObjectValue>())
Florin Malitafa7e9a82018-05-04 15:10:54 -040080 return false;
Florin Malita7d42c442018-06-14 16:16:01 -040081 const auto& ov = v.as<ObjectValue>();
Florin Malitafa7e9a82018-05-04 15:10:54 -040082
Florin Malitaf5ac9062018-06-19 12:55:53 -040083 return Parse<SkScalar>(ov["x"], &pt->fX)
84 && Parse<SkScalar>(ov["y"], &pt->fY);
Florin Malitafa7e9a82018-05-04 15:10:54 -040085}
86
87template <>
Florin Malita7d42c442018-06-14 16:16:01 -040088bool Parse<std::vector<float>>(const Value& v, std::vector<float>* vec) {
89 if (!v.is<ArrayValue>())
Florin Malitafa7e9a82018-05-04 15:10:54 -040090 return false;
Florin Malita7d42c442018-06-14 16:16:01 -040091 const auto& av = v.as<ArrayValue>();
Florin Malitafa7e9a82018-05-04 15:10:54 -040092
Florin Malita7d42c442018-06-14 16:16:01 -040093 vec->resize(av.size());
94 for (size_t i = 0; i < av.size(); ++i) {
95 if (!Parse(av[i], vec->data() + i)) {
Florin Malitafa7e9a82018-05-04 15:10:54 -040096 return false;
97 }
98 }
99
100 return true;
101}
102
103namespace {
104
Florin Malita7d42c442018-06-14 16:16:01 -0400105bool ParsePointVec(const Value& v, std::vector<SkPoint>* pts) {
106 if (!v.is<ArrayValue>())
Florin Malitafa7e9a82018-05-04 15:10:54 -0400107 return false;
Florin Malita7d42c442018-06-14 16:16:01 -0400108 const auto& av = v.as<ArrayValue>();
Florin Malitafa7e9a82018-05-04 15:10:54 -0400109
110 pts->clear();
Florin Malita7d42c442018-06-14 16:16:01 -0400111 pts->reserve(av.size());
Florin Malitafa7e9a82018-05-04 15:10:54 -0400112
113 std::vector<float> vec;
Florin Malita7d42c442018-06-14 16:16:01 -0400114 for (size_t i = 0; i < av.size(); ++i) {
115 if (!Parse(av[i], &vec) || vec.size() != 2)
Florin Malitafa7e9a82018-05-04 15:10:54 -0400116 return false;
117 pts->push_back(SkPoint::Make(vec[0], vec[1]));
118 }
119
120 return true;
121}
122
123} // namespace
124
125template <>
Florin Malita7d42c442018-06-14 16:16:01 -0400126bool Parse<ShapeValue>(const Value& v, ShapeValue* sh) {
127 SkASSERT(sh->fVertices.empty());
Florin Malitafa7e9a82018-05-04 15:10:54 -0400128
129 // Some versions wrap values as single-element arrays.
Florin Malita7d42c442018-06-14 16:16:01 -0400130 if (const skjson::ArrayValue* av = v) {
131 if (av->size() == 1) {
132 return Parse((*av)[0], sh);
133 }
Florin Malitafa7e9a82018-05-04 15:10:54 -0400134 }
135
Florin Malita7d42c442018-06-14 16:16:01 -0400136 if (!v.is<skjson::ObjectValue>())
137 return false;
138 const auto& ov = v.as<ObjectValue>();
139
Florin Malitafa7e9a82018-05-04 15:10:54 -0400140 std::vector<SkPoint> inPts, // Cubic Bezier "in" control points, relative to vertices.
141 outPts, // Cubic Bezier "out" control points, relative to vertices.
142 verts; // Cubic Bezier vertices.
143
Florin Malita7d42c442018-06-14 16:16:01 -0400144 if (!ParsePointVec(ov["i"], &inPts) ||
145 !ParsePointVec(ov["o"], &outPts) ||
146 !ParsePointVec(ov["v"], &verts) ||
Florin Malitafa7e9a82018-05-04 15:10:54 -0400147 inPts.size() != outPts.size() ||
148 inPts.size() != verts.size()) {
149
150 return false;
151 }
152
Florin Malita7d42c442018-06-14 16:16:01 -0400153 sh->fVertices.reserve(inPts.size());
Florin Malitafa7e9a82018-05-04 15:10:54 -0400154 for (size_t i = 0; i < inPts.size(); ++i) {
Florin Malita7d42c442018-06-14 16:16:01 -0400155 sh->fVertices.push_back(BezierVertex({inPts[i], outPts[i], verts[i]}));
Florin Malitafa7e9a82018-05-04 15:10:54 -0400156 }
Florin Malita7d42c442018-06-14 16:16:01 -0400157 sh->fClosed = ParseDefault<bool>(ov["c"], false);
Florin Malitafa7e9a82018-05-04 15:10:54 -0400158
159 return true;
160}
161
Florin Malitafa7e9a82018-05-04 15:10:54 -0400162} // namespace skottie