Converting more debug code to SkJSONWriter

All of SkDrawCommand / SkDebugCanvas now uses SkJSONWriter.
Also removed the bespoke json generator and pretty-printer
in GrAuditTrail. This was the largest volume of code still
using JsonCPP. (There are other stragglers).

Bug: skia:
Change-Id: I3aee554764689ce50c8e707caf26c76093b9bb8f
Reviewed-on: https://skia-review.googlesource.com/c/187040
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Brian Osman 2019-01-28 13:41:19 -05:00 committed by Skia Commit-Bot
parent 41f0e28fd5
commit d8a90f9be1
15 changed files with 759 additions and 912 deletions

View File

@ -1539,7 +1539,6 @@ if (skia_enable_tools) {
]
public_deps = [
":common_flags",
"//third_party/jsoncpp",
]
}
@ -1762,7 +1761,6 @@ if (skia_enable_tools) {
"modules/skottie",
"modules/skottie:utils",
"modules/sksg",
"//third_party/jsoncpp",
"//third_party/libpng",
]
@ -1897,7 +1895,6 @@ if (skia_enable_tools) {
":gpu_tool_utils",
":skia",
":tool_utils",
"//third_party/jsoncpp",
"//third_party/libmicrohttpd",
"//third_party/libpng",
]
@ -1943,7 +1940,6 @@ if (skia_enable_tools) {
":gpu_tool_utils",
":skia",
"modules/skottie:fuzz",
"//third_party/jsoncpp",
"//third_party/libpng",
]
}
@ -1992,7 +1988,6 @@ if (skia_enable_tools) {
deps = [
":skia",
":tool_utils",
"//third_party/jsoncpp",
]
}
@ -2376,7 +2371,6 @@ if (skia_enable_tools) {
":generate_mocs",
":generate_resources",
":skia",
"//third_party/jsoncpp",
"//third_party/libpng",
]
}

View File

@ -1703,10 +1703,12 @@ Error DebugSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) cons
}
std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
UrlDataManager dataManager(SkString("data"));
Json::Value json = debugCanvas.toJSON(
dataManager, debugCanvas.getSize(), nullCanvas.get());
std::string value = Json::StyledWriter().write(json);
return dst->write(value.c_str(), value.size()) ? "" : "SkWStream Error";
SkJSONWriter writer(dst, SkJSONWriter::Mode::kPretty);
writer.beginObject(); // root
debugCanvas.toJSON(writer, dataManager, debugCanvas.getSize(), nullCanvas.get());
writer.endObject(); // root
writer.flush();
return "";
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

View File

@ -1726,6 +1726,12 @@ DEF_FUZZ(_DumpCanvas, fuzz) {
fuzz_canvas(fuzz, &debugCanvas);
std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
UrlDataManager dataManager(SkString("data"));
Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
Json::StyledStreamWriter(" ").write(std::cout, json);
SkDynamicMemoryWStream stream;
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
writer.beginObject(); // root
debugCanvas.toJSON(writer, dataManager, debugCanvas.getSize(), nullCanvas.get());
writer.endObject(); // root
writer.flush();
sk_sp<SkData> json = stream.detachAsData();
fwrite(json->data(), json->size(), 1, stdout);
}

View File

@ -17,6 +17,7 @@
#include "SkTHash.h"
class GrOp;
class SkJSONWriter;
/*
* GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them
@ -91,10 +92,10 @@ public:
// this means is that for some sequence of draw calls N, the below toJson calls will only
// produce JSON which reflects N draw calls. This JSON may or may not be accurate for N + 1 or
// N - 1 draws depending on the actual combining algorithm used.
SkString toJson(bool prettyPrint = false) const;
void toJson(SkJSONWriter& writer) const;
// returns a json string of all of the ops associated with a given client id
SkString toJson(int clientID, bool prettyPrint = false) const;
void toJson(SkJSONWriter& writer, int clientID) const;
bool isEnabled() { return fEnabled; }
void setEnabled(bool enabled) { fEnabled = enabled; }
@ -124,7 +125,7 @@ public:
private:
// TODO if performance becomes an issue, we can move to using SkVarAlloc
struct Op {
SkString toJson() const;
void toJson(SkJSONWriter& writer) const;
SkString fName;
SkTArray<SkString> fStackTrace;
SkRect fBounds;
@ -138,7 +139,7 @@ private:
struct OpNode {
OpNode(const GrSurfaceProxy::UniqueID& proxyID) : fProxyUniqueID(proxyID) { }
SkString toJson() const;
void toJson(SkJSONWriter& writer) const;
SkRect fBounds;
Ops fChildren;
@ -149,8 +150,7 @@ private:
void copyOutFromOpList(OpInfo* outOpInfo, int opListID);
template <typename T>
static void JsonifyTArray(SkString* json, const char* name, const T& array,
bool addComma);
static void JsonifyTArray(SkJSONWriter& writer, const char* name, const T& array);
OpPool fOpPool;
SkTHashMap<uint32_t, int> fIDLookup;

View File

@ -7,6 +7,7 @@
#include "GrAuditTrail.h"
#include "ops/GrOp.h"
#include "SkJSONWriter.h"
const int GrAuditTrail::kGrAuditTrailInvalidID = -1;
@ -136,159 +137,64 @@ void GrAuditTrail::fullReset() {
}
template <typename T>
void GrAuditTrail::JsonifyTArray(SkString* json, const char* name, const T& array,
bool addComma) {
void GrAuditTrail::JsonifyTArray(SkJSONWriter& writer, const char* name, const T& array) {
if (array.count()) {
if (addComma) {
json->appendf(",");
}
json->appendf("\"%s\": [", name);
const char* separator = "";
writer.beginArray(name);
for (int i = 0; i < array.count(); i++) {
// Handle sentinel nullptrs
if (array[i]) {
json->appendf("%s", separator);
json->append(array[i]->toJson());
separator = ",";
array[i]->toJson(writer);
}
}
json->append("]");
writer.endArray();
}
}
// This will pretty print a very small subset of json
// The parsing rules are straightforward, aside from the fact that we do not want an extra newline
// before ',' and after '}', so we have a comma exception rule.
class PrettyPrintJson {
public:
SkString prettify(const SkString& json) {
fPrettyJson.reset();
fTabCount = 0;
fFreshLine = false;
fCommaException = false;
for (size_t i = 0; i < json.size(); i++) {
if ('[' == json[i] || '{' == json[i]) {
this->newline();
this->appendChar(json[i]);
fTabCount++;
this->newline();
} else if (']' == json[i] || '}' == json[i]) {
fTabCount--;
this->newline();
this->appendChar(json[i]);
fCommaException = true;
} else if (',' == json[i]) {
this->appendChar(json[i]);
this->newline();
} else {
this->appendChar(json[i]);
}
}
return fPrettyJson;
}
private:
void appendChar(char appendee) {
if (fCommaException && ',' != appendee) {
this->newline();
}
this->tab();
fPrettyJson += appendee;
fFreshLine = false;
fCommaException = false;
}
void tab() {
if (fFreshLine) {
for (int i = 0; i < fTabCount; i++) {
fPrettyJson += '\t';
}
}
}
void newline() {
if (!fFreshLine) {
fFreshLine = true;
fPrettyJson += '\n';
}
}
SkString fPrettyJson;
int fTabCount;
bool fFreshLine;
bool fCommaException;
};
static SkString pretty_print_json(SkString json) {
class PrettyPrintJson prettyPrintJson;
return prettyPrintJson.prettify(json);
void GrAuditTrail::toJson(SkJSONWriter& writer) const {
writer.beginObject();
JsonifyTArray(writer, "Ops", fOpList);
writer.endObject();
}
SkString GrAuditTrail::toJson(bool prettyPrint) const {
SkString json;
json.append("{");
JsonifyTArray(&json, "Ops", fOpList, false);
json.append("}");
if (prettyPrint) {
return pretty_print_json(json);
} else {
return json;
}
}
SkString GrAuditTrail::toJson(int clientID, bool prettyPrint) const {
SkString json;
json.append("{");
void GrAuditTrail::toJson(SkJSONWriter& writer, int clientID) const {
writer.beginObject();
Ops** ops = fClientIDLookup.find(clientID);
if (ops) {
JsonifyTArray(&json, "Ops", **ops, false);
}
json.appendf("}");
if (prettyPrint) {
return pretty_print_json(json);
} else {
return json;
JsonifyTArray(writer, "Ops", **ops);
}
writer.endObject();
}
static void skrect_to_json(SkString* json, const char* name, const SkRect& rect) {
json->appendf("\"%s\": {", name);
json->appendf("\"Left\": %f,", rect.fLeft);
json->appendf("\"Right\": %f,", rect.fRight);
json->appendf("\"Top\": %f,", rect.fTop);
json->appendf("\"Bottom\": %f", rect.fBottom);
json->append("}");
static void skrect_to_json(SkJSONWriter& writer, const char* name, const SkRect& rect) {
writer.beginObject(name);
writer.appendFloat("Left", rect.fLeft);
writer.appendFloat("Right", rect.fRight);
writer.appendFloat("Top", rect.fTop);
writer.appendFloat("Bottom", rect.fBottom);
writer.endObject();
}
SkString GrAuditTrail::Op::toJson() const {
SkString json;
json.append("{");
json.appendf("\"Name\": \"%s\",", fName.c_str());
json.appendf("\"ClientID\": \"%d\",", fClientID);
json.appendf("\"OpListID\": \"%d\",", fOpListID);
json.appendf("\"ChildID\": \"%d\",", fChildID);
skrect_to_json(&json, "Bounds", fBounds);
void GrAuditTrail::Op::toJson(SkJSONWriter& writer) const {
writer.beginObject();
writer.appendString("Name", fName.c_str());
writer.appendS32("ClientID", fClientID);
writer.appendS32("OpListID", fOpListID);
writer.appendS32("ChildID", fChildID);
skrect_to_json(writer, "Bounds", fBounds);
if (fStackTrace.count()) {
json.append(",\"Stack\": [");
writer.beginArray("Stack");
for (int i = 0; i < fStackTrace.count(); i++) {
json.appendf("\"%s\"", fStackTrace[i].c_str());
if (i < fStackTrace.count() - 1) {
json.append(",");
}
writer.appendString(fStackTrace[i].c_str());
}
json.append("]");
writer.endArray();
}
json.append("}");
return json;
writer.endObject();
}
SkString GrAuditTrail::OpNode::toJson() const {
SkString json;
json.append("{");
json.appendf("\"ProxyID\": \"%u\",", fProxyUniqueID.asUInt());
skrect_to_json(&json, "Bounds", fBounds);
JsonifyTArray(&json, "Ops", fChildren, true);
json.append("}");
return json;
void GrAuditTrail::OpNode::toJson(SkJSONWriter& writer) const {
writer.beginObject();
writer.appendU32("ProxyID", fProxyUniqueID.asUInt());
skrect_to_json(writer, "Bounds", fBounds);
JsonifyTArray(writer, "Ops", fChildren);
writer.endObject();
}

View File

@ -199,15 +199,15 @@ public:
void appendS64(int64_t value);
void appendU32(uint32_t value) { this->beginValue(); this->appendf("%u", value); }
void appendU64(uint64_t value);
void appendFloat(float value) { this->beginValue(); this->appendf("%f", value); }
void appendDouble(double value) { this->beginValue(); this->appendf("%f", value); }
void appendFloat(float value) { this->beginValue(); this->appendf("%g", value); }
void appendDouble(double value) { this->beginValue(); this->appendf("%g", value); }
void appendFloatDigits(float value, int digits) {
this->beginValue();
this->appendf("%.*f", digits, value);
this->appendf("%.*g", digits, value);
}
void appendDoubleDigits(double value, int digits) {
this->beginValue();
this->appendf("%.*f", digits, value);
this->appendf("%.*g", digits, value);
}
void appendHexU32(uint32_t value) { this->beginValue(); this->appendf("\"0x%x\"", value); }
void appendHexU64(uint64_t value);

View File

@ -8,6 +8,7 @@
#include "SkCanvasPriv.h"
#include "SkDebugCanvas.h"
#include "SkDrawCommand.h"
#include "SkJSONWriter.h"
#include "SkPaintFilterCanvas.h"
#include "SkPicture.h"
#include "SkRectPriv.h"
@ -248,43 +249,42 @@ void SkDebugCanvas::cleanupAuditTrail(SkCanvas* canvas) {
}
}
Json::Value SkDebugCanvas::toJSON(UrlDataManager& urlDataManager, int n, SkCanvas* canvas) {
void SkDebugCanvas::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager, int n,
SkCanvas* canvas) {
this->drawAndCollectOps(n, canvas);
// now collect json
GrAuditTrail* at = this->getAuditTrail(canvas);
Json::Value result = Json::Value(Json::objectValue);
result[SKDEBUGCANVAS_ATTRIBUTE_VERSION] = Json::Value(SKDEBUGCANVAS_VERSION);
Json::Value commands = Json::Value(Json::arrayValue);
for (int i = 0; i < this->getSize() && i <= n; i++) {
commands[i] = this->getDrawCommandAt(i)->toJSON(urlDataManager);
if (at) {
// TODO if this is inefficient we could add a method to GrAuditTrail which takes
// a Json::Value and is only compiled in this file
Json::Value parsedFromString;
Json::Reader reader;
SkAssertResult(reader.parse(at->toJson(i).c_str(), parsedFromString));
writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_VERSION, SKDEBUGCANVAS_VERSION);
writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_COMMANDS);
commands[i][SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL] = parsedFromString;
for (int i = 0; i < this->getSize() && i <= n; i++) {
writer.beginObject(); // command
this->getDrawCommandAt(i)->toJSON(writer, urlDataManager);
if (at) {
writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL);
at->toJson(writer, i);
}
writer.endObject(); // command
}
writer.endArray(); // commands
this->cleanupAuditTrail(canvas);
result[SKDEBUGCANVAS_ATTRIBUTE_COMMANDS] = commands;
return result;
}
Json::Value SkDebugCanvas::toJSONOpList(int n, SkCanvas* canvas) {
void SkDebugCanvas::toJSONOpList(SkJSONWriter& writer, int n, SkCanvas* canvas) {
this->drawAndCollectOps(n, canvas);
Json::Value parsedFromString;
GrAuditTrail* at = this->getAuditTrail(canvas);
if (at) {
GrAuditTrail::AutoManageOpList enable(at);
Json::Reader reader;
SkAssertResult(reader.parse(at->toJson().c_str(), parsedFromString));
at->toJson(writer);
} else {
writer.beginObject();
writer.endObject();
}
this->cleanupAuditTrail(canvas);
return parsedFromString;
}
void SkDebugCanvas::setOverdrawViz(bool overdrawViz) {

View File

@ -103,9 +103,9 @@ public:
SkDebugCanvas::getSize(). The encoder may use the UrlDataManager to store binary data such
as images, referring to them via URLs embedded in the JSON.
*/
Json::Value toJSON(UrlDataManager &urlDataManager, int n, SkCanvas *);
void toJSON(SkJSONWriter& writer, UrlDataManager &urlDataManager, int n, SkCanvas *);
Json::Value toJSONOpList(int n, SkCanvas*);
void toJSONOpList(SkJSONWriter& writer, int n, SkCanvas*);
void detachCommands(SkTDArray<SkDrawCommand*>* dst) {
fCommandVector.swap(*dst);

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
#include "SkCanvas.h"
#include "SkDrawShadowInfo.h"
#include "SkFlattenable.h"
#include "SkJSONWriter.h"
#include "SkTLazy.h"
#include "SkPath.h"
#include "SkRegion.h"
@ -20,7 +21,6 @@
#include "SkString.h"
#include "SkTDArray.h"
#include "SkVertices.h"
#include "SkJSONCPP.h"
#include "UrlDataManager.h"
class SkDrawCommand {
@ -88,30 +88,29 @@ public:
virtual bool render(SkCanvas* canvas) const { return false; }
virtual Json::Value toJSON(UrlDataManager& urlDataManager) const;
virtual void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const;
static const char* GetCommandString(OpType type);
// Helper methods for converting things to JSON
static Json::Value MakeJsonColor(const SkColor color);
static Json::Value MakeJsonColor4f(const SkColor4f& color);
static Json::Value MakeJsonPoint(const SkPoint& point);
static Json::Value MakeJsonPoint(SkScalar x, SkScalar y);
static Json::Value MakeJsonPoint3(const SkPoint3& point);
static Json::Value MakeJsonRect(const SkRect& rect);
static Json::Value MakeJsonIRect(const SkIRect&);
static Json::Value MakeJsonMatrix(const SkMatrix&);
static Json::Value MakeJsonScalar(SkScalar);
static Json::Value MakeJsonPath(const SkPath& path);
static Json::Value MakeJsonRegion(const SkRegion& region);
static Json::Value MakeJsonPaint(const SkPaint& paint, UrlDataManager& urlDataManager);
static Json::Value MakeJsonLattice(const SkCanvas::Lattice& lattice);
static void MakeJsonColor(SkJSONWriter&, const SkColor color);
static void MakeJsonColor4f(SkJSONWriter&, const SkColor4f& color);
static void MakeJsonPoint(SkJSONWriter&, const SkPoint& point);
static void MakeJsonPoint(SkJSONWriter&, SkScalar x, SkScalar y);
static void MakeJsonPoint3(SkJSONWriter&, const SkPoint3& point);
static void MakeJsonRect(SkJSONWriter&, const SkRect& rect);
static void MakeJsonIRect(SkJSONWriter&, const SkIRect&);
static void MakeJsonMatrix(SkJSONWriter&, const SkMatrix&);
static void MakeJsonPath(SkJSONWriter&, const SkPath& path);
static void MakeJsonRegion(SkJSONWriter&, const SkRegion& region);
static void MakeJsonPaint(SkJSONWriter&, const SkPaint& paint, UrlDataManager& urlDataManager);
static void MakeJsonLattice(SkJSONWriter&, const SkCanvas::Lattice& lattice);
static void flatten(const SkFlattenable* flattenable, Json::Value* target,
static void flatten(const SkFlattenable* flattenable, SkJSONWriter& writer,
UrlDataManager& urlDataManager);
static bool flatten(const SkImage& image, Json::Value* target,
static bool flatten(const SkImage& image, SkJSONWriter& writer,
UrlDataManager& urlDataManager);
static bool flatten(const SkBitmap& bitmap, Json::Value* target,
static bool flatten(const SkBitmap& bitmap, SkJSONWriter& writer,
UrlDataManager& urlDataManager);
private:
@ -132,7 +131,7 @@ class SkClearCommand : public SkDrawCommand {
public:
SkClearCommand(SkColor color);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkColor fColor;
@ -145,7 +144,7 @@ public:
SkClipPathCommand(const SkPath& path, SkClipOp op, bool doAA);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkPath fPath;
@ -159,7 +158,7 @@ class SkClipRegionCommand : public SkDrawCommand {
public:
SkClipRegionCommand(const SkRegion& region, SkClipOp op);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRegion fRegion;
@ -172,7 +171,7 @@ class SkClipRectCommand : public SkDrawCommand {
public:
SkClipRectCommand(const SkRect& rect, SkClipOp op, bool doAA);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRect fRect;
@ -187,7 +186,7 @@ public:
SkClipRRectCommand(const SkRRect& rrect, SkClipOp op, bool doAA);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRRect fRRect;
@ -201,7 +200,7 @@ class SkConcatCommand : public SkDrawCommand {
public:
SkConcatCommand(const SkMatrix& matrix);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkMatrix fMatrix;
@ -213,7 +212,7 @@ class SkDrawAnnotationCommand : public SkDrawCommand {
public:
SkDrawAnnotationCommand(const SkRect&, const char key[], sk_sp<SkData> value);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRect fRect;
@ -229,7 +228,7 @@ public:
const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkBitmap fBitmap;
@ -246,7 +245,7 @@ public:
const SkRect& dst, const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkBitmap fBitmap;
@ -263,7 +262,7 @@ public:
const SkRect& dst, const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkBitmap fBitmap;
@ -281,7 +280,7 @@ public:
SkCanvas::SrcRectConstraint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkBitmap fBitmap;
@ -298,7 +297,7 @@ public:
SkDrawImageCommand(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
sk_sp<const SkImage> fImage;
@ -315,7 +314,7 @@ public:
const SkRect& dst, const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
sk_sp<const SkImage> fImage;
@ -332,7 +331,7 @@ public:
const SkRect& dst, const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
sk_sp<const SkImage> fImage;
@ -349,7 +348,7 @@ public:
const SkPaint* paint, SkCanvas::SrcRectConstraint constraint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
sk_sp<const SkImage> fImage;
@ -380,7 +379,7 @@ public:
SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRect fOval;
@ -395,7 +394,7 @@ public:
const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRect fOval;
@ -412,7 +411,7 @@ public:
SkDrawPaintCommand(const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkPaint fPaint;
@ -425,7 +424,7 @@ public:
SkDrawPathCommand(const SkPath& path, const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkPath fPath;
@ -469,7 +468,7 @@ public:
const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkCanvas::PointMode fMode;
@ -484,7 +483,7 @@ public:
SkDrawRegionCommand(const SkRegion& region, const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRegion fRegion;
@ -499,7 +498,7 @@ public:
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
sk_sp<SkTextBlob> fBlob;
@ -516,7 +515,7 @@ public:
const SkPoint texCoords[4], SkBlendMode bmode,
const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkPoint fCubics[12];
@ -535,7 +534,7 @@ class SkDrawRectCommand : public SkDrawCommand {
public:
SkDrawRectCommand(const SkRect& rect, const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRect fRect;
@ -564,7 +563,7 @@ public:
SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRRect fRRect;
@ -579,7 +578,7 @@ public:
const SkPaint& paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkRRect fOuter;
@ -635,7 +634,7 @@ class SkSaveLayerCommand : public SkDrawCommand {
public:
SkSaveLayerCommand(const SkCanvas::SaveLayerRec&);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkTLazy<SkRect> fBounds;
@ -650,7 +649,7 @@ class SkSetMatrixCommand : public SkDrawCommand {
public:
SkSetMatrixCommand(const SkMatrix& matrix);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkMatrix fMatrix;
@ -663,7 +662,7 @@ public:
SkDrawShadowCommand(const SkPath& path, const SkDrawShadowRec& rec);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
private:
SkPath fPath;

View File

@ -9,155 +9,164 @@
#include "SkDrawCommand.h"
void SkJsonWriteBuffer::append(const char* type, const Json::Value& value) {
SkString fullName = SkStringPrintf("%02d_%s", fJson.size(), type);
fJson[fullName.c_str()] = value;
void SkJsonWriteBuffer::append(const char* type) {
SkString fullName = SkStringPrintf("%02d_%s", fCount++, type);
fWriter->appendName(fullName.c_str());
}
void SkJsonWriteBuffer::writePad32(const void* data, size_t size) {
Json::Value jsonArray(Json::arrayValue);
this->append("rawBytes");
fWriter->beginArray();
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
for (size_t i = 0; i < size; ++i) {
SkString hexByte = SkStringPrintf("%02x", bytes[i]);
jsonArray.append(hexByte.c_str());
fWriter->appendString(hexByte.c_str());
}
this->append("rawBytes", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writeByteArray(const void* data, size_t size) {
Json::Value jsonArray(Json::arrayValue);
this->append("byteArray");
fWriter->beginArray();
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
for (size_t i = 0; i < size; ++i) {
SkString hexByte = SkStringPrintf("%02x", bytes[i]);
jsonArray.append(hexByte.c_str());
fWriter->appendString(hexByte.c_str());
}
this->append("byteArray", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writeBool(bool value) {
this->append("bool", value);
this->append("bool"); fWriter->appendBool(value);
}
void SkJsonWriteBuffer::writeScalar(SkScalar value) {
this->append("scalar", value);
this->append("scalar"); fWriter->appendFloat(value);
}
void SkJsonWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
Json::Value jsonArray(Json::arrayValue);
this->append("scalarArray");
fWriter->beginArray();
for (uint32_t i = 0; i < count; ++i) {
jsonArray.append(value[i]);
fWriter->appendFloat(value[i]);
}
this->append("scalarArray", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writeInt(int32_t value) {
this->append("int", value);
this->append("int"); fWriter->appendS32(value);
}
void SkJsonWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
Json::Value jsonArray(Json::arrayValue);
this->append("intArray");
fWriter->beginArray();
for (uint32_t i = 0; i < count; ++i) {
jsonArray.append(value[i]);
fWriter->appendS32(value[i]);
}
this->append("intArray", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writeUInt(uint32_t value) {
this->append("uint", value);
this->append("uint"); fWriter->appendU32(value);
}
void SkJsonWriteBuffer::writeString(const char* value) {
this->append("string", value);
this->append("string"); fWriter->appendString(value);
}
void SkJsonWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
if (flattenable) {
SkJsonWriteBuffer flattenableBuffer(fUrlDataManager);
this->append(flattenable->getTypeName());
fWriter->beginObject();
SkJsonWriteBuffer flattenableBuffer(fWriter, fUrlDataManager);
flattenable->flatten(flattenableBuffer);
this->append(flattenable->getTypeName(), flattenableBuffer.getValue());
fWriter->endObject();
} else {
this->append("flattenable", Json::Value());
this->append("flattenable"); fWriter->appendPointer(nullptr);
}
}
void SkJsonWriteBuffer::writeColor(SkColor color) {
this->append("color", SkDrawCommand::MakeJsonColor(color));
this->append("color"); SkDrawCommand::MakeJsonColor(*fWriter, color);
}
void SkJsonWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
Json::Value jsonArray(Json::arrayValue);
this->append("colorArray");
fWriter->beginArray();
for (uint32_t i = 0; i < count; ++i) {
jsonArray.append(SkDrawCommand::MakeJsonColor(color[i]));
SkDrawCommand::MakeJsonColor(*fWriter, color[i]);
}
this->append("colorArray", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writeColor4f(const SkColor4f& color) {
this->append("color", SkDrawCommand::MakeJsonColor4f(color));
this->append("color"); SkDrawCommand::MakeJsonColor4f(*fWriter, color);
}
void SkJsonWriteBuffer::writeColor4fArray(const SkColor4f* color, uint32_t count) {
Json::Value jsonArray(Json::arrayValue);
this->append("colorArray");
fWriter->beginArray();
for (uint32_t i = 0; i < count; ++i) {
jsonArray.append(SkDrawCommand::MakeJsonColor4f(color[i]));
SkDrawCommand::MakeJsonColor4f(*fWriter, color[i]);
}
this->append("colorArray", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writePoint(const SkPoint& point) {
this->append("point", SkDrawCommand::MakeJsonPoint(point));
this->append("point"); SkDrawCommand::MakeJsonPoint(*fWriter, point);
}
void SkJsonWriteBuffer::writePoint3(const SkPoint3& point) {
this->append("point3", SkDrawCommand::MakeJsonPoint3(point));
this->append("point3"); SkDrawCommand::MakeJsonPoint3(*fWriter, point);
}
void SkJsonWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
Json::Value jsonArray(Json::arrayValue);
this->append("pointArray");
fWriter->beginArray();
for (uint32_t i = 0; i < count; ++i) {
jsonArray.append(SkDrawCommand::MakeJsonPoint(point[i]));
SkDrawCommand::MakeJsonPoint(*fWriter, point[i]);
}
this->append("pointArray", jsonArray);
fWriter->endArray();
}
void SkJsonWriteBuffer::writeMatrix(const SkMatrix& matrix) {
this->append("matrix", SkDrawCommand::MakeJsonMatrix(matrix));
this->append("matrix"); SkDrawCommand::MakeJsonMatrix(*fWriter, matrix);
}
void SkJsonWriteBuffer::writeIRect(const SkIRect& rect) {
this->append("irect", SkDrawCommand::MakeJsonIRect(rect));
this->append("irect"); SkDrawCommand::MakeJsonIRect(*fWriter, rect);
}
void SkJsonWriteBuffer::writeRect(const SkRect& rect) {
this->append("rect", SkDrawCommand::MakeJsonRect(rect));
this->append("rect"); SkDrawCommand::MakeJsonRect(*fWriter, rect);
}
void SkJsonWriteBuffer::writeRegion(const SkRegion& region) {
this->append("region", SkDrawCommand::MakeJsonRegion(region));
this->append("region"); SkDrawCommand::MakeJsonRegion(*fWriter, region);
}
void SkJsonWriteBuffer::writePath(const SkPath& path) {
this->append("path", SkDrawCommand::MakeJsonPath(path));
this->append("path"); SkDrawCommand::MakeJsonPath(*fWriter, path);
}
size_t SkJsonWriteBuffer::writeStream(SkStream* stream, size_t length) {
// Contents not supported
SkASSERT(length < Json::Value::maxUInt);
this->append("stream", static_cast<Json::UInt>(length));
this->append("stream"); fWriter->appendU64(static_cast<uint64_t>(length));
return 0;
}
void SkJsonWriteBuffer::writeImage(const SkImage* image) {
Json::Value jsonImage;
SkDrawCommand::flatten(*image, &jsonImage, *fUrlDataManager);
this->append("image", jsonImage);
this->append("image");
fWriter->beginObject();
SkDrawCommand::flatten(*image, *fWriter, *fUrlDataManager);
fWriter->endObject();
}
void SkJsonWriteBuffer::writeTypeface(SkTypeface* typeface) {
// Unsupported
this->append("typeface", Json::Value());
this->append("typeface"); fWriter->appendPointer(typeface);
}
void SkJsonWriteBuffer::writePaint(const SkPaint& paint) {
this->append("paint", SkDrawCommand::MakeJsonPaint(paint, *fUrlDataManager));
this->append("paint"); SkDrawCommand::MakeJsonPaint(*fWriter, paint, *fUrlDataManager);
}

View File

@ -10,16 +10,16 @@
#include "SkWriteBuffer.h"
#include "SkJSONCPP.h"
class SkJSONWriter;
class SkPath;
class UrlDataManager;
class SkJsonWriteBuffer final : public SkWriteBuffer {
public:
SkJsonWriteBuffer(UrlDataManager* urlDataManager)
SkJsonWriteBuffer(SkJSONWriter* writer, UrlDataManager* urlDataManager)
: fUrlDataManager(urlDataManager)
, fJson(Json::objectValue) {}
, fWriter(writer)
, fCount(0) {}
void writePad32(const void* buffer, size_t bytes) override;
void writeByteArray(const void* data, size_t size) override;
@ -49,13 +49,12 @@ public:
void writeTypeface(SkTypeface* typeface) override;
void writePaint(const SkPaint& paint) override;
const Json::Value& getValue() const { return fJson; }
private:
void append(const char* type, const Json::Value& value);
void append(const char* type);
UrlDataManager* fUrlDataManager;
Json::Value fJson;
SkJSONWriter* fWriter;
int fCount;
};
#endif

View File

@ -7,6 +7,7 @@
#include "Request.h"
#include "SkJSONWriter.h"
#include "SkPictureRecorder.h"
#include "sk_tool_utils.h"
@ -214,25 +215,29 @@ bool Request::initPictureFromStream(SkStream* stream) {
sk_sp<SkData> Request::getJsonOps(int n) {
SkCanvas* canvas = this->getCanvas();
Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas);
root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu");
root["drawGpuOpBounds"] = Json::Value(fDebugCanvas->getDrawGpuOpBounds());
root["colorMode"] = Json::Value(fColorMode);
SkDynamicMemoryWStream stream;
stream.writeText(Json::FastWriter().write(root).c_str());
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
writer.beginObject(); // root
writer.appendString("mode", fGPUEnabled ? "gpu" : "cpu");
writer.appendBool("drawGpuOpBounds", fDebugCanvas->getDrawGpuOpBounds());
writer.appendS32("colorMode", fColorMode);
fDebugCanvas->toJSON(writer, fUrlDataManager, n, canvas);
writer.endObject(); // root
writer.flush();
return stream.detachAsData();
}
sk_sp<SkData> Request::getJsonOpList(int n) {
SkCanvas* canvas = this->getCanvas();
SkASSERT(fGPUEnabled);
Json::Value result = fDebugCanvas->toJSONOpList(n, canvas);
SkDynamicMemoryWStream stream;
stream.writeText(Json::FastWriter().write(result).c_str());
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
fDebugCanvas->toJSONOpList(writer, n, canvas);
writer.flush();
return stream.detachAsData();
}
@ -245,16 +250,20 @@ sk_sp<SkData> Request::getJsonInfo(int n) {
fDebugCanvas->drawTo(canvas, n);
// make some json
SkDynamicMemoryWStream stream;
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
SkMatrix vm = fDebugCanvas->getCurrentMatrix();
SkIRect clip = fDebugCanvas->getCurrentClip();
Json::Value info(Json::objectValue);
info["ViewMatrix"] = SkDrawCommand::MakeJsonMatrix(vm);
info["ClipRect"] = SkDrawCommand::MakeJsonIRect(clip);
std::string json = Json::FastWriter().write(info);
writer.beginObject(); // root
writer.appendName("ViewMatrix"); SkDrawCommand::MakeJsonMatrix(writer, vm);
writer.appendName("ClipRect"); SkDrawCommand::MakeJsonIRect(writer, clip);
writer.endObject(); // root
// We don't want the null terminator so strlen is correct
return SkData::MakeWithCopy(json.c_str(), strlen(json.c_str()));
// TODO: Old code explicitly avoided the null terminator in the returned data. Important?
writer.flush();
return stream.detachAsData();
}
SkColor Request::getPixel(int x, int y) {

View File

@ -47,15 +47,14 @@ int BreakHandler::handle(Request* request, MHD_Connection* connection,
request->fDebugCanvas->getDrawCommandAt(i)->execute(canvas);
}
SkColor target = request->getPixel(x, y);
Json::Value response(Json::objectValue);
Json::Value startColor(Json::arrayValue);
startColor.append(Json::Value(SkColorGetR(target)));
startColor.append(Json::Value(SkColorGetG(target)));
startColor.append(Json::Value(SkColorGetB(target)));
startColor.append(Json::Value(SkColorGetA(target)));
response["startColor"] = startColor;
response["endColor"] = startColor;
response["endOp"] = Json::Value(n);
SkDynamicMemoryWStream stream;
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
writer.beginObject(); // root
writer.appendName("startColor"); SkDrawCommand::MakeJsonColor(writer, target);
bool changed = false;
for (int i = n + 1; i < n + count; ++i) {
int index = i % count;
if (index == 0) {
@ -67,18 +66,19 @@ int BreakHandler::handle(Request* request, MHD_Connection* connection,
request->fDebugCanvas->getDrawCommandAt(index)->execute(canvas);
SkColor current = request->getPixel(x, y);
if (current != target) {
Json::Value endColor(Json::arrayValue);
endColor.append(Json::Value(SkColorGetR(current)));
endColor.append(Json::Value(SkColorGetG(current)));
endColor.append(Json::Value(SkColorGetB(current)));
endColor.append(Json::Value(SkColorGetA(current)));
response["endColor"] = endColor;
response["endOp"] = Json::Value(index);
writer.appendName("endColor"); SkDrawCommand::MakeJsonColor(writer, current);
writer.appendS32("endOp", index);
changed = true;
break;
}
}
if (!changed) {
writer.appendName("endColor"); SkDrawCommand::MakeJsonColor(writer, target);
writer.appendS32("endOp", n);
}
canvas->restoreToCount(saveCount);
SkDynamicMemoryWStream stream;
stream.writeText(Json::FastWriter().write(response).c_str());
writer.endObject(); // root
writer.flush();
return SendData(connection, stream.detachAsData().get(), "application/json");
}

View File

@ -55,8 +55,12 @@ int main(int argc, char** argv) {
pic->playback(&debugCanvas);
std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
UrlDataManager dataManager(SkString("data"));
Json::Value json = debugCanvas.toJSON(
dataManager, debugCanvas.getSize(), nullCanvas.get());
SkDynamicMemoryWStream stream;
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
writer.beginObject(); // root
debugCanvas.toJSON(writer, dataManager, debugCanvas.getSize(), nullCanvas.get());
writer.endObject(); // root
writer.flush();
if (argc > 2) {
if (UrlDataManager::UrlData* data =
dataManager.getDataFromUrl(SkString(argv[2]))) {
@ -72,7 +76,8 @@ int main(int argc, char** argv) {
return 4;
}
} else {
Json::StyledStreamWriter(" ").write(std::cout, json);
sk_sp<SkData> data = stream.detachAsData();
fwrite(data->data(), data->size(), 1, stdout);
}
return 0;
}