blob: 946dfd6ee56f60e5983bc9fc104c2ce642b9f5be [file] [log] [blame]
Brian Osman7c979f52019-02-12 13:27:51 -05001/*
2* Copyright 2019 Google LLC
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#ifndef SkParticleSerialization_DEFINED
9#define SkParticleSerialization_DEFINED
10
11#include "SkReflected.h"
12
13#include "SkJSON.h"
14#include "SkJSONWriter.h"
15#include "SkTArray.h"
16
17class SkToJsonVisitor : public SkFieldVisitor {
18public:
19 SkToJsonVisitor(SkJSONWriter& writer) : fWriter(writer) {}
20
21 // Primitives
22 void visit(const char* name, float& f, SkField) override {
23 fWriter.appendFloat(name, f);
24 }
25 void visit(const char* name, int& i, SkField) override {
26 fWriter.appendS32(name, i);
27 }
28 void visit(const char* name, bool& b, SkField) override {
29 fWriter.appendBool(name, b);
30 }
31 void visit(const char* name, SkString& s, SkField) override {
32 fWriter.appendString(name, s.c_str());
33 }
34
35 // Compound types
36 void visit(const char* name, SkPoint& p, SkField) override {
37 fWriter.beginObject(name, false);
38 fWriter.appendFloat("x", p.fX);
39 fWriter.appendFloat("y", p.fY);
40 fWriter.endObject();
41 }
42
43 void visit(const char* name, SkColor4f& c, SkField) override {
44 fWriter.beginArray(name, false);
45 fWriter.appendFloat(c.fR);
46 fWriter.appendFloat(c.fG);
47 fWriter.appendFloat(c.fB);
48 fWriter.appendFloat(c.fA);
49 fWriter.endArray();
50 }
51
52 void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
53 fWriter.appendString("Type", e ? e->getType()->fName : "Null");
54 }
55
56 void enterObject(const char* name) override { fWriter.beginObject(name); }
57 void exitObject() override { fWriter.endObject(); }
58
Brian Osman5de7ea42019-02-14 13:23:51 -050059 int enterArray(const char* name, int oldCount) override {
Brian Osman7c979f52019-02-12 13:27:51 -050060 fWriter.beginArray(name);
Brian Osman5de7ea42019-02-14 13:23:51 -050061 return oldCount;
62 }
63 ArrayEdit exitArray() override {
Brian Osman7c979f52019-02-12 13:27:51 -050064 fWriter.endArray();
Brian Osman5de7ea42019-02-14 13:23:51 -050065 return ArrayEdit();
Brian Osman7c979f52019-02-12 13:27:51 -050066 }
67
68private:
69 SkJSONWriter& fWriter;
70};
71
72class SkFromJsonVisitor : public SkFieldVisitor {
73public:
74 SkFromJsonVisitor(const skjson::Value& v) : fRoot(v) {
75 fStack.push_back(&fRoot);
76 }
77
78 void visit(const char* name, float& f, SkField) override {
79 TryParse(get(name), f);
80 }
81 void visit(const char* name, int& i, SkField) override {
82 TryParse(get(name), i);
83 }
84 void visit(const char* name, bool& b, SkField) override {
85 TryParse(get(name), b);
86 }
87 void visit(const char* name, SkString& s, SkField) override {
88 TryParse(get(name), s);
89 }
90
91 void visit(const char* name, SkPoint& p, SkField) override {
92 if (const skjson::ObjectValue* obj = get(name)) {
93 TryParse((*obj)["x"], p.fX);
94 TryParse((*obj)["y"], p.fY);
95 }
96 }
97
98 void visit(const char* name, SkColor4f& c, SkField) override {
99 const skjson::ArrayValue* arr = get(name);
100 if (arr && arr->size() == 4) {
101 TryParse((*arr)[0], c.fR);
102 TryParse((*arr)[1], c.fG);
103 TryParse((*arr)[2], c.fB);
104 TryParse((*arr)[3], c.fA);
105 }
106 }
107
108 void visit(const char* name, SkCurve& c, SkField field) override {
109 if (get(name).is<skjson::ObjectValue>()) {
110 SkFieldVisitor::visit(name, c, field);
111 }
112 }
113
114 void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
115 const skjson::StringValue* typeString = get("Type");
116 const char* type = typeString ? typeString->begin() : "Null";
117 e = SkReflected::CreateInstance(type);
118 }
119
120 void enterObject(const char* name) override {
121 fStack.push_back((const skjson::ObjectValue*)get(name));
122 }
123 void exitObject() override {
124 fStack.pop_back();
125 }
126
Brian Osman5de7ea42019-02-14 13:23:51 -0500127 int enterArray(const char* name, int oldCount) override {
128 const skjson::ArrayValue* arrVal = get(name);
129 fStack.push_back(arrVal);
130 fArrayIndexStack.push_back(0);
131 return arrVal ? arrVal->size() : 0;
132 }
133 ArrayEdit exitArray() override {
134 fStack.pop_back();
135 fArrayIndexStack.pop_back();
136 return ArrayEdit();
Brian Osman7c979f52019-02-12 13:27:51 -0500137 }
138
139private:
Brian Osman5de7ea42019-02-14 13:23:51 -0500140 const skjson::Value& get(const char* name) {
Brian Osman7c979f52019-02-12 13:27:51 -0500141 if (const skjson::Value* cur = fStack.back()) {
Brian Osman5de7ea42019-02-14 13:23:51 -0500142 if (cur->is<skjson::ArrayValue>()) {
143 SkASSERT(!name);
144 return cur->as<skjson::ArrayValue>()[fArrayIndexStack.back()++];
145 } else if (!name) {
Brian Osman7c979f52019-02-12 13:27:51 -0500146 return *cur;
147 } else if (cur->is<skjson::ObjectValue>()) {
148 return cur->as<skjson::ObjectValue>()[name];
149 }
150 }
151 static skjson::NullValue gNull;
152 return gNull;
153 }
154
155 static bool TryParse(const skjson::Value& v, float& f) {
156 if (const skjson::NumberValue* num = v) {
157 f = static_cast<float>(**num);
158 return true;
159 }
160 return false;
161 }
162
163 static bool TryParse(const skjson::Value& v, int& i) {
164 if (const skjson::NumberValue* num = v) {
165 double dbl = **num;
166 i = static_cast<int>(dbl);
167 return static_cast<double>(i) == dbl;
168 }
169 return false;
170 }
171
172 static bool TryParse(const skjson::Value& v, SkString& s) {
173 if (const skjson::StringValue* str = v) {
174 s.set(str->begin(), str->size());
175 return true;
176 }
177 return false;
178 }
179
180 static bool TryParse(const skjson::Value& v, bool& b) {
181 switch (v.getType()) {
182 case skjson::Value::Type::kNumber:
183 b = SkToBool(*v.as<skjson::NumberValue>());
184 return true;
185 case skjson::Value::Type::kBool:
186 b = *v.as<skjson::BoolValue>();
187 return true;
188 default:
189 break;
190 }
191
192 return false;
193 }
194
195 const skjson::Value& fRoot;
196 SkSTArray<16, const skjson::Value*, true> fStack;
Brian Osman5de7ea42019-02-14 13:23:51 -0500197 SkSTArray<16, size_t, true> fArrayIndexStack;
Brian Osman7c979f52019-02-12 13:27:51 -0500198};
199
200#endif // SkParticleSerialization_DEFINED