skia2/modules/particles/include/SkParticleSerialization.h
Brian Osman 90507286cc Shuffle SkSL sources around so compiler and bytecode can be used w/o GPU
Change-Id: I7236a30040ab532086e68d6e9de2898dd7acaa32
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221098
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
2019-06-17 21:16:18 +00:00

205 lines
6.0 KiB
C++

/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkParticleSerialization_DEFINED
#define SkParticleSerialization_DEFINED
#include "modules/particles/include/SkReflected.h"
#include "include/core/SkString.h"
#include "include/private/SkTArray.h"
#include "src/utils/SkJSON.h"
#include "src/utils/SkJSONWriter.h"
class SkToJsonVisitor : public SkFieldVisitor {
public:
SkToJsonVisitor(SkJSONWriter& writer) : fWriter(writer) {}
// Primitives
void visit(const char* name, float& f) override {
fWriter.appendFloat(name, f);
}
void visit(const char* name, int& i) override {
fWriter.appendS32(name, i);
}
void visit(const char* name, bool& b) override {
fWriter.appendBool(name, b);
}
void visit(const char* name, SkString& s) override {
fWriter.appendString(name, s.c_str());
}
void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
fWriter.appendString(name, EnumToString(i, map, count));
}
// Compound types
void visit(const char* name, SkPoint& p) override {
fWriter.beginObject(name, false);
fWriter.appendFloat("x", p.fX);
fWriter.appendFloat("y", p.fY);
fWriter.endObject();
}
void visit(const char* name, SkColor4f& c) override {
fWriter.beginArray(name, false);
fWriter.appendFloat(c.fR);
fWriter.appendFloat(c.fG);
fWriter.appendFloat(c.fB);
fWriter.appendFloat(c.fA);
fWriter.endArray();
}
void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
fWriter.appendString("Type", e ? e->getType()->fName : "Null");
}
void enterObject(const char* name) override { fWriter.beginObject(name); }
void exitObject() override { fWriter.endObject(); }
int enterArray(const char* name, int oldCount) override {
fWriter.beginArray(name);
return oldCount;
}
ArrayEdit exitArray() override {
fWriter.endArray();
return ArrayEdit();
}
private:
SkJSONWriter& fWriter;
};
class SkFromJsonVisitor : public SkFieldVisitor {
public:
SkFromJsonVisitor(const skjson::Value& v) : fRoot(v) {
fStack.push_back(&fRoot);
}
void visit(const char* name, float& f) override {
TryParse(get(name), f);
}
void visit(const char* name, int& i) override {
TryParse(get(name), i);
}
void visit(const char* name, bool& b) override {
TryParse(get(name), b);
}
void visit(const char* name, SkString& s) override {
TryParse(get(name), s);
}
void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
SkString str;
if (TryParse(get(name), str)) {
i = StringToEnum(str.c_str(), map, count);
}
}
void visit(const char* name, SkPoint& p) override {
if (const skjson::ObjectValue* obj = get(name)) {
TryParse((*obj)["x"], p.fX);
TryParse((*obj)["y"], p.fY);
}
}
void visit(const char* name, SkColor4f& c) override {
const skjson::ArrayValue* arr = get(name);
if (arr && arr->size() == 4) {
TryParse((*arr)[0], c.fR);
TryParse((*arr)[1], c.fG);
TryParse((*arr)[2], c.fB);
TryParse((*arr)[3], c.fA);
}
}
void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
const skjson::StringValue* typeString = get("Type");
const char* type = typeString ? typeString->begin() : "Null";
e = SkReflected::CreateInstance(type);
}
void enterObject(const char* name) override {
fStack.push_back((const skjson::ObjectValue*)get(name));
}
void exitObject() override {
fStack.pop_back();
}
int enterArray(const char* name, int oldCount) override {
const skjson::ArrayValue* arrVal = get(name);
fStack.push_back(arrVal);
fArrayIndexStack.push_back(0);
return arrVal ? arrVal->size() : 0;
}
ArrayEdit exitArray() override {
fStack.pop_back();
fArrayIndexStack.pop_back();
return ArrayEdit();
}
private:
const skjson::Value& get(const char* name) {
if (const skjson::Value* cur = fStack.back()) {
if (cur->is<skjson::ArrayValue>()) {
SkASSERT(!name);
return cur->as<skjson::ArrayValue>()[fArrayIndexStack.back()++];
} else if (!name) {
return *cur;
} else if (cur->is<skjson::ObjectValue>()) {
return cur->as<skjson::ObjectValue>()[name];
}
}
static skjson::NullValue gNull;
return gNull;
}
static bool TryParse(const skjson::Value& v, float& f) {
if (const skjson::NumberValue* num = v) {
f = static_cast<float>(**num);
return true;
}
return false;
}
static bool TryParse(const skjson::Value& v, int& i) {
if (const skjson::NumberValue* num = v) {
double dbl = **num;
i = static_cast<int>(dbl);
return static_cast<double>(i) == dbl;
}
return false;
}
static bool TryParse(const skjson::Value& v, SkString& s) {
if (const skjson::StringValue* str = v) {
s.set(str->begin(), str->size());
return true;
}
return false;
}
static bool TryParse(const skjson::Value& v, bool& b) {
switch (v.getType()) {
case skjson::Value::Type::kNumber:
b = SkToBool(*v.as<skjson::NumberValue>());
return true;
case skjson::Value::Type::kBool:
b = *v.as<skjson::BoolValue>();
return true;
default:
break;
}
return false;
}
const skjson::Value& fRoot;
SkSTArray<16, const skjson::Value*, true> fStack;
SkSTArray<16, size_t, true> fArrayIndexStack;
};
#endif // SkParticleSerialization_DEFINED