2 * Copyright 2019 Google LLC
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkParticleSerialization_DEFINED
9 #define SkParticleSerialization_DEFINED
11 #include "modules/particles/include/SkReflected.h"
13 #include "include/core/SkString.h"
14 #include "include/private/SkTArray.h"
15 #include "src/utils/SkJSON.h"
16 #include "src/utils/SkJSONWriter.h"
18 class SkToJsonVisitor : public SkFieldVisitor {
20 SkToJsonVisitor(SkJSONWriter& writer) : fWriter(writer) {}
23 void visit(const char* name, float& f) override {
24 fWriter.appendFloat(name, f);
26 void visit(const char* name, int& i) override {
27 fWriter.appendS32(name, i);
29 void visit(const char* name, bool& b) override {
30 fWriter.appendBool(name, b);
32 void visit(const char* name, SkString& s) override {
33 if (s.contains('\n')) {
34 SkTArray<SkString> lines;
35 SkStrSplit(s.c_str(), "\n", kStrict_SkStrSplitMode, &lines);
36 fWriter.beginArray(name);
37 for (const auto& line : lines) {
38 fWriter.appendString(line.c_str());
42 fWriter.appendString(name, s.c_str());
47 void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
48 fWriter.appendString("Type", e ? e->getType()->fName : "Null");
51 void enterObject(const char* name) override { fWriter.beginObject(name); }
52 void exitObject() override { fWriter.endObject(); }
54 int enterArray(const char* name, int oldCount) override {
55 fWriter.beginArray(name);
58 ArrayEdit exitArray() override {
64 SkJSONWriter& fWriter;
67 class SkFromJsonVisitor : public SkFieldVisitor {
69 SkFromJsonVisitor(const skjson::Value& v) : fRoot(v) {
70 fStack.push_back(&fRoot);
73 void visit(const char* name, float& f) override {
74 TryParse(get(name), f);
76 void visit(const char* name, int& i) override {
77 TryParse(get(name), i);
79 void visit(const char* name, bool& b) override {
80 TryParse(get(name), b);
82 void visit(const char* name, SkString& s) override {
83 if (const skjson::ArrayValue* lines = get(name)) {
86 for (const skjson::StringValue* line : *lines) {
91 s.append(line->begin(), line->size());
96 TryParse(get(name), s);
100 void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
101 const skjson::StringValue* typeString = get("Type");
102 const char* type = typeString ? typeString->begin() : "Null";
103 e = SkReflected::CreateInstance(type);
106 void enterObject(const char* name) override {
107 fStack.push_back((const skjson::ObjectValue*)get(name));
109 void exitObject() override {
113 int enterArray(const char* name, int oldCount) override {
114 const skjson::ArrayValue* arrVal = get(name);
115 fStack.push_back(arrVal);
116 fArrayIndexStack.push_back(0);
117 return arrVal ? arrVal->size() : 0;
119 ArrayEdit exitArray() override {
121 fArrayIndexStack.pop_back();
126 const skjson::Value& get(const char* name) {
127 if (const skjson::Value* cur = fStack.back()) {
128 if (cur->is<skjson::ArrayValue>()) {
130 return cur->as<skjson::ArrayValue>()[fArrayIndexStack.back()++];
133 } else if (cur->is<skjson::ObjectValue>()) {
134 return cur->as<skjson::ObjectValue>()[name];
137 static skjson::NullValue gNull;
141 static bool TryParse(const skjson::Value& v, float& f) {
142 if (const skjson::NumberValue* num = v) {
143 f = static_cast<float>(**num);
149 static bool TryParse(const skjson::Value& v, int& i) {
150 if (const skjson::NumberValue* num = v) {
152 i = static_cast<int>(dbl);
153 return static_cast<double>(i) == dbl;
158 static bool TryParse(const skjson::Value& v, SkString& s) {
159 if (const skjson::StringValue* str = v) {
160 s.set(str->begin(), str->size());
166 static bool TryParse(const skjson::Value& v, bool& b) {
167 switch (v.getType()) {
168 case skjson::Value::Type::kNumber:
169 b = SkToBool(*v.as<skjson::NumberValue>());
171 case skjson::Value::Type::kBool:
172 b = *v.as<skjson::BoolValue>();
181 const skjson::Value& fRoot;
182 SkSTArray<16, const skjson::Value*, true> fStack;
183 SkSTArray<16, size_t, true> fArrayIndexStack;
186 #endif // SkParticleSerialization_DEFINED