skia2/tests/FlattenDrawableTest.cpp
brianosman fad98562d8 Prototype code that turns any/every flattenable into JSON
This makes inspecting things in SkDebugger far more useful - any filter
or other complex object on the paint is ultimately visible. You still
have to do some guess work to figure out what the fields actually mean,
but you can at least cross-reference with the code in flatten().

Screenshots:
Before: https://screenshot.googleplex.com/a6JM5HBBe6G.png
After : https://screenshot.googleplex.com/XQfr4YJ6mnH.png

Changes to public API are just removals and changes to make
some functions virtual.

TBR=reed@google.com

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1920423002

Review-Url: https://codereview.chromium.org/1920423002
2016-05-04 11:06:28 -07:00

288 lines
10 KiB
C++

/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCanvas.h"
#include "SkDrawable.h"
#include "SkOnce.h"
#include "SkPictureRecorder.h"
#include "SkReadBuffer.h"
#include "SkRect.h"
#include "SkStream.h"
#include "SkWriteBuffer.h"
#include "Test.h"
class IntDrawable : public SkDrawable {
public:
IntDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
: fA(a)
, fB(b)
, fC(c)
, fD(d)
{}
void flatten(SkWriteBuffer& buffer) const override {
buffer.writeUInt(fA);
buffer.writeUInt(fB);
buffer.writeUInt(fC);
buffer.writeUInt(fD);
}
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
uint32_t a = buffer.readUInt();
uint32_t b = buffer.readUInt();
uint32_t c = buffer.readUInt();
uint32_t d = buffer.readUInt();
return sk_sp<IntDrawable>(new IntDrawable(a, b, c, d));
}
Factory getFactory() const override { return CreateProc; }
uint32_t a() const { return fA; }
uint32_t b() const { return fB; }
uint32_t c() const { return fC; }
uint32_t d() const { return fD; }
const char* getTypeName() const override { return "IntDrawable"; }
protected:
SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
void onDraw(SkCanvas*) override {}
private:
uint32_t fA;
uint32_t fB;
uint32_t fC;
uint32_t fD;
};
class PaintDrawable : public SkDrawable {
public:
PaintDrawable(const SkPaint& paint)
: fPaint(paint)
{}
void flatten(SkWriteBuffer& buffer) const override {
buffer.writePaint(fPaint);
}
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
SkPaint paint;
buffer.readPaint(&paint);
return sk_sp<PaintDrawable>(new PaintDrawable(paint));
}
Factory getFactory() const override { return CreateProc; }
const SkPaint& paint() const { return fPaint; }
const char* getTypeName() const override { return "PaintDrawable"; }
protected:
SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
void onDraw(SkCanvas*) override {}
private:
SkPaint fPaint;
};
class CompoundDrawable : public SkDrawable {
public:
CompoundDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint)
: fIntDrawable(new IntDrawable(a, b, c, d))
, fPaintDrawable(new PaintDrawable(paint))
{}
CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
: fIntDrawable(SkRef(intDrawable))
, fPaintDrawable(SkRef(paintDrawable))
{}
void flatten(SkWriteBuffer& buffer) const override {
buffer.writeFlattenable(fIntDrawable);
buffer.writeFlattenable(fPaintDrawable);
}
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
SkAutoTUnref<SkFlattenable> intDrawable(
buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
SkASSERT(intDrawable);
SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
SkAutoTUnref<SkFlattenable> paintDrawable(
buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
SkASSERT(paintDrawable);
SkASSERT(!strcmp("PaintDrawable", paintDrawable->getTypeName()));
return sk_sp<CompoundDrawable>(new CompoundDrawable((IntDrawable*) intDrawable.get(),
(PaintDrawable*) paintDrawable.get()));
}
Factory getFactory() const override { return CreateProc; }
IntDrawable* intDrawable() const { return fIntDrawable; }
PaintDrawable* paintDrawable() const { return fPaintDrawable; }
const char* getTypeName() const override { return "CompoundDrawable"; }
protected:
SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
void onDraw(SkCanvas*) override {}
private:
SkAutoTUnref<IntDrawable> fIntDrawable;
SkAutoTUnref<PaintDrawable> fPaintDrawable;
};
class RootDrawable : public SkDrawable {
public:
RootDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint,
uint32_t e, uint32_t f, uint32_t g, uint32_t h, SkDrawable* drawable)
: fCompoundDrawable(new CompoundDrawable(a, b, c, d, paint))
, fIntDrawable(new IntDrawable(e, f, g, h))
, fDrawable(SkRef(drawable))
{}
RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
SkDrawable* drawable)
: fCompoundDrawable(SkRef(compoundDrawable))
, fIntDrawable(SkRef(intDrawable))
, fDrawable(SkRef(drawable))
{}
void flatten(SkWriteBuffer& buffer) const override {
buffer.writeFlattenable(fCompoundDrawable);
buffer.writeFlattenable(fIntDrawable);
buffer.writeFlattenable(fDrawable);
}
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
SkAutoTUnref<SkFlattenable> compoundDrawable(
buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
SkASSERT(compoundDrawable);
SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
SkAutoTUnref<SkFlattenable> intDrawable(
buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
SkASSERT(intDrawable);
SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
SkAutoTUnref<SkFlattenable> drawable(
buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
SkASSERT(drawable);
return sk_sp<RootDrawable>(new RootDrawable((CompoundDrawable*) compoundDrawable.get(),
(IntDrawable*) intDrawable.get(),
(SkDrawable*) drawable.get()));
}
Factory getFactory() const override { return CreateProc; }
CompoundDrawable* compoundDrawable() const { return fCompoundDrawable; }
IntDrawable* intDrawable() const { return fIntDrawable; }
SkDrawable* drawable() const { return fDrawable; }
const char* getTypeName() const override { return "RootDrawable"; }
protected:
SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
void onDraw(SkCanvas*) override {}
private:
SkAutoTUnref<CompoundDrawable> fCompoundDrawable;
SkAutoTUnref<IntDrawable> fIntDrawable;
SkAutoTUnref<SkDrawable> fDrawable;
};
static void register_test_drawables(SkReadBuffer& buffer) {
buffer.setCustomFactory(SkString("IntDrawable"), IntDrawable::CreateProc);
buffer.setCustomFactory(SkString("PaintDrawable"), PaintDrawable::CreateProc);
buffer.setCustomFactory(SkString("CompoundDrawable"), CompoundDrawable::CreateProc);
buffer.setCustomFactory(SkString("RootDrawable"), RootDrawable::CreateProc);
}
DEF_TEST(FlattenDrawable, r) {
// Create and serialize the test drawable
SkAutoTUnref<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
SkPaint paint;
paint.setColor(SK_ColorBLUE);
SkAutoTUnref<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable));
SkBinaryWriteBuffer writeBuffer;
writeBuffer.writeFlattenable(root);
// Copy the contents of the write buffer into a read buffer
sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
writeBuffer.writeToMemory(data->writable_data());
SkReadBuffer readBuffer(data->data(), data->size());
register_test_drawables(readBuffer);
// Deserialize and verify the drawable
SkAutoTUnref<SkDrawable> out((SkDrawable*)
readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
REPORTER_ASSERT(r, out);
REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName()));
RootDrawable* rootOut = (RootDrawable*) out.get();
REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a());
REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b());
REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c());
REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d());
REPORTER_ASSERT(r, SK_ColorBLUE ==
rootOut->compoundDrawable()->paintDrawable()->paint().getColor());
REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a());
REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b());
REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c());
REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d());
// Note that we can still recognize the generic drawable as an IntDrawable
SkDrawable* generic = rootOut->drawable();
REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName()));
IntDrawable* integer = (IntDrawable*) generic;
REPORTER_ASSERT(r, 1 == integer->a());
REPORTER_ASSERT(r, 2 == integer->b());
REPORTER_ASSERT(r, 3 == integer->c());
REPORTER_ASSERT(r, 4 == integer->d());
}
DEF_TEST(FlattenRecordedDrawable, r) {
// Record a set of canvas draw commands
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
canvas->drawPoint(42.0f, 17.0f, SK_ColorGREEN);
SkPaint paint;
paint.setColor(SK_ColorRED);
canvas->drawPaint(paint);
SkPaint textPaint;
textPaint.setColor(SK_ColorBLUE);
canvas->drawText("TEXT", 4, 467.0f, 100.0f, textPaint);
// Draw some drawables as well
SkAutoTUnref<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
SkAutoTUnref<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable));
canvas->drawDrawable(root, 747.0f, 242.0f);
SkAutoTUnref<PaintDrawable> paintDrawable(new PaintDrawable(paint));
canvas->drawDrawable(paintDrawable, 500.0, 500.0f);
SkAutoTUnref<CompoundDrawable> comDrawable(new CompoundDrawable(13, 14, 15, 16, textPaint));
canvas->drawDrawable(comDrawable, 10.0f, 10.0f);
// Serialize the recorded drawable
sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
SkBinaryWriteBuffer writeBuffer;
writeBuffer.writeFlattenable(recordedDrawable.get());
// Copy the contents of the write buffer into a read buffer
sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
writeBuffer.writeToMemory(data->writable_data());
SkReadBuffer readBuffer(data->data(), data->size());
register_test_drawables(readBuffer);
// Deserialize and verify the drawable
SkAutoTUnref<SkDrawable> out((SkDrawable*)
readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
REPORTER_ASSERT(r, out);
REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
}