| Index: src/core/SkRemote.cpp
|
| diff --git a/src/core/SkRemote.cpp b/src/core/SkRemote.cpp
|
| index 21fbdf3d978a078077f2bcba953545f11874d5c7..ff658ff20d146f92158d0b6eb00678bbc31124f7 100644
|
| --- a/src/core/SkRemote.cpp
|
| +++ b/src/core/SkRemote.cpp
|
| @@ -5,9 +5,12 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| +#include "SkCanvas.h"
|
| #include "SkPath.h"
|
| #include "SkRect.h"
|
| #include "SkRemote.h"
|
| +#include "SkShader.h"
|
| +#include "SkTHash.h"
|
|
|
| namespace SkRemote {
|
|
|
| @@ -72,6 +75,278 @@ namespace SkRemote {
|
|
|
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
|
| + class Canvas final : public SkCanvas {
|
| + public:
|
| + explicit Canvas(Encoder* encoder)
|
| + : SkCanvas(1,1)
|
| + , fEncoder(encoder) {}
|
| +
|
| + private:
|
| + // Calls Encoder::define() when created, Encoder::undefine() when destroyed.
|
| + class AutoID : ::SkNoncopyable {
|
| + public:
|
| + template <typename T>
|
| + explicit AutoID(Encoder* encoder, const T& val)
|
| + : fEncoder(encoder)
|
| + , fID(encoder->define(val)) {}
|
| + ~AutoID() { if (fEncoder) fEncoder->undefine(fID); }
|
| +
|
| + AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) {
|
| + o.fEncoder = nullptr;
|
| + }
|
| + AutoID& operator=(AutoID&&) = delete;
|
| +
|
| + operator ID () const { return fID; }
|
| +
|
| + private:
|
| + Encoder* fEncoder;
|
| + const ID fID;
|
| + };
|
| +
|
| + template <typename T>
|
| + AutoID id(const T& val) { return AutoID(fEncoder, val); }
|
| +
|
| + void willSave() override { fEncoder-> save(); }
|
| + void didRestore() override { fEncoder->restore(); }
|
| +
|
| + void didConcat(const SkMatrix&) override { this->didSetMatrix(this->getTotalMatrix()); }
|
| + void didSetMatrix(const SkMatrix& matrix) override {
|
| + fEncoder->setMatrix(this->id(matrix));
|
| + }
|
| +
|
| + void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
|
| + SkPath path;
|
| + path.addOval(oval);
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
|
| + SkPath path;
|
| + path.addRect(rect);
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
|
| + SkPath path;
|
| + path.addRRect(rrect);
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawDRRect(const SkRRect& outside, const SkRRect& inside,
|
| + const SkPaint& paint) override {
|
| + SkPath path;
|
| + path.addRRect(outside);
|
| + path.addRRect(inside, SkPath::kCCW_Direction);
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawPath(const SkPath& path, const SkPaint& paint) override {
|
| + auto p = this->id(path),
|
| + m = this->id(Misc::CreateFrom(paint)),
|
| + s = this->id(paint.getShader()),
|
| + x = this->id(paint.getXfermode());
|
| +
|
| + if (paint.getStyle() == SkPaint::kFill_Style) {
|
| + fEncoder->fillPath(p, m, s, x);
|
| + } else {
|
| + // TODO: handle kStrokeAndFill_Style
|
| + fEncoder->strokePath(p, m, s, x, this->id(Stroke::CreateFrom(paint)));
|
| + }
|
| + }
|
| +
|
| + void onDrawPaint(const SkPaint& paint) override {
|
| + SkPath path;
|
| + path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse FillType is fine.
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawText(const void* text, size_t byteLength,
|
| + SkScalar x, SkScalar y, const SkPaint& paint) override {
|
| + // Text-as-paths is a temporary hack.
|
| + // TODO: send SkTextBlobs and SkTypefaces
|
| + SkPath path;
|
| + paint.getTextPath(text, byteLength, x, y, &path);
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawPosText(const void* text, size_t byteLength,
|
| + const SkPoint pos[], const SkPaint& paint) override {
|
| + // Text-as-paths is a temporary hack.
|
| + // TODO: send SkTextBlobs and SkTypefaces
|
| + SkPath path;
|
| + paint.getPosTextPath(text, byteLength, pos, &path);
|
| + this->onDrawPath(path, paint);
|
| + }
|
| +
|
| + void onDrawPosTextH(const void* text, size_t byteLength,
|
| + const SkScalar xpos[], SkScalar constY, const SkPaint& paint) override {
|
| + size_t length = paint.countText(text, byteLength);
|
| + SkAutoTArray<SkPoint> pos(length);
|
| + for(size_t i = 0; i < length; ++i) {
|
| + pos[i].set(xpos[i], constY);
|
| + }
|
| + this->onDrawPosText(text, byteLength, &pos[0], paint);
|
| + }
|
| +
|
| + void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
|
| + SkPath path;
|
| + path.addRect(rect);
|
| + this->onClipPath(path, op, edgeStyle);
|
| + }
|
| +
|
| + void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
|
| + SkPath path;
|
| + path.addRRect(rrect);
|
| + this->onClipPath(path, op, edgeStyle);
|
| + }
|
| +
|
| + void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
|
| + fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle);
|
| + }
|
| +
|
| + Encoder* fEncoder;
|
| + };
|
| +
|
| + SkCanvas* NewCanvas(Encoder* encoder) { return new Canvas(encoder); }
|
| +
|
| + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
| +
|
| + class Decoder final : public Encoder {
|
| + public:
|
| + explicit Decoder(SkCanvas* canvas) : fCanvas(canvas) {}
|
| +
|
| + private:
|
| + template <typename Map, typename T>
|
| + ID define(Type type, Map* map, const T& val) {
|
| + ID id(type, fNextID++);
|
| + map->set(id, val);
|
| + return id;
|
| + }
|
| +
|
| + ID define(const SkMatrix& v) override {return this->define(Type::kMatrix, &fMatrix, v);}
|
| + ID define(const Misc& v) override {return this->define(Type::kMisc, &fMisc, v);}
|
| + ID define(const SkPath& v) override {return this->define(Type::kPath, &fPath, v);}
|
| + ID define(const Stroke& v) override {return this->define(Type::kStroke, &fStroke, v);}
|
| + ID define(SkShader* v) override {return this->define(Type::kShader, &fShader, v);}
|
| + ID define(SkXfermode* v) override {return this->define(Type::kXfermode, &fXfermode, v);}
|
| +
|
| + void undefine(ID id) override {
|
| + switch(id.type()) {
|
| + case Type::kMatrix: return fMatrix .remove(id);
|
| + case Type::kMisc: return fMisc .remove(id);
|
| + case Type::kPath: return fPath .remove(id);
|
| + case Type::kStroke: return fStroke .remove(id);
|
| + case Type::kShader: return fShader .remove(id);
|
| + case Type::kXfermode: return fXfermode.remove(id);
|
| + };
|
| + }
|
| +
|
| + void save() override { fCanvas->save(); }
|
| + void restore() override { fCanvas->restore(); }
|
| +
|
| + void setMatrix(ID matrix) override { fCanvas->setMatrix(fMatrix.find(matrix)); }
|
| +
|
| + void clipPath(ID path, SkRegion::Op op, bool aa) override {
|
| + fCanvas->clipPath(fPath.find(path), op, aa);
|
| + }
|
| + void fillPath(ID path, ID misc, ID shader, ID xfermode) override {
|
| + SkPaint paint;
|
| + paint.setStyle(SkPaint::kFill_Style);
|
| + fMisc.find(misc).applyTo(&paint);
|
| + paint.setShader (fShader .find(shader));
|
| + paint.setXfermode(fXfermode.find(xfermode));
|
| + fCanvas->drawPath(fPath.find(path), paint);
|
| + }
|
| + void strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke) override {
|
| + SkPaint paint;
|
| + paint.setStyle(SkPaint::kStroke_Style);
|
| + fMisc .find(misc ).applyTo(&paint);
|
| + fStroke.find(stroke).applyTo(&paint);
|
| + paint.setShader (fShader .find(shader));
|
| + paint.setXfermode(fXfermode.find(xfermode));
|
| + fCanvas->drawPath(fPath.find(path), paint);
|
| + }
|
| +
|
| + // Maps ID -> T.
|
| + template <typename T, Type kType>
|
| + class IDMap {
|
| + public:
|
| + ~IDMap() {
|
| + // A well-behaved client always cleans up its definitions.
|
| + SkASSERT(fMap.count() == 0);
|
| + }
|
| +
|
| + void set(const ID& id, const T& val) {
|
| + SkASSERT(id.type() == kType);
|
| + fMap.set(id, val);
|
| + }
|
| +
|
| + void remove(const ID& id) {
|
| + SkASSERT(id.type() == kType);
|
| + fMap.remove(id);
|
| + }
|
| +
|
| + const T& find(const ID& id) const {
|
| + SkASSERT(id.type() == kType);
|
| + T* val = fMap.find(id);
|
| + SkASSERT(val != nullptr);
|
| + return *val;
|
| + }
|
| +
|
| + private:
|
| + SkTHashMap<ID, T> fMap;
|
| + };
|
| +
|
| + // Maps ID -> T*, and keeps the T alive by reffing it.
|
| + template <typename T, Type kType>
|
| + class ReffedIDMap {
|
| + public:
|
| + ReffedIDMap() {}
|
| + ~ReffedIDMap() {
|
| + // A well-behaved client always cleans up its definitions.
|
| + SkASSERT(fMap.count() == 0);
|
| + }
|
| +
|
| + void set(const ID& id, T* val) {
|
| + SkASSERT(id.type() == kType);
|
| + fMap.set(id, SkSafeRef(val));
|
| + }
|
| +
|
| + void remove(const ID& id) {
|
| + SkASSERT(id.type() == kType);
|
| + T** val = fMap.find(id);
|
| + SkASSERT(val);
|
| + SkSafeUnref(*val);
|
| + fMap.remove(id);
|
| + }
|
| +
|
| + T* find(const ID& id) const {
|
| + SkASSERT(id.type() == kType);
|
| + T** val = fMap.find(id);
|
| + SkASSERT(val);
|
| + return *val;
|
| + }
|
| +
|
| + private:
|
| + SkTHashMap<ID, T*> fMap;
|
| + };
|
| +
|
| +
|
| + IDMap<SkMatrix , Type::kMatrix> fMatrix;
|
| + IDMap<Misc , Type::kMisc > fMisc;
|
| + IDMap<SkPath , Type::kPath > fPath;
|
| + IDMap<Stroke , Type::kStroke> fStroke;
|
| + ReffedIDMap<SkShader , Type::kShader> fShader;
|
| + ReffedIDMap<SkXfermode, Type::kXfermode> fXfermode;
|
| +
|
| + SkCanvas* fCanvas;
|
| + uint64_t fNextID = 0;
|
| + };
|
| +
|
| + Encoder* NewDecoder(SkCanvas* canvas) { return new Decoder(canvas); }
|
| +
|
| + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
| +
|
| class CachingEncoder final : public Encoder {
|
| public:
|
| explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {}
|
| @@ -166,194 +441,6 @@ namespace SkRemote {
|
| Encoder* fWrapped;
|
| };
|
|
|
| - Encoder* Encoder::CreateCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wrapped); }
|
| -
|
| - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
| -
|
| - // Calls Encoder::define() when created, Encoder::undefine() when destroyed.
|
| - class Client::AutoID : ::SkNoncopyable {
|
| - public:
|
| - template <typename T>
|
| - explicit AutoID(Encoder* encoder, const T& val)
|
| - : fEncoder(encoder)
|
| - , fID(encoder->define(val)) {}
|
| - ~AutoID() { if (fEncoder) fEncoder->undefine(fID); }
|
| -
|
| - AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) {
|
| - o.fEncoder = nullptr;
|
| - }
|
| - AutoID& operator=(AutoID&&) = delete;
|
| -
|
| - operator ID () const { return fID; }
|
| -
|
| - private:
|
| - Encoder* fEncoder;
|
| - const ID fID;
|
| - };
|
| -
|
| - template <typename T>
|
| - Client::AutoID Client::id(const T& val) { return AutoID(fEncoder, val); }
|
| -
|
| - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
| -
|
| - Client::Client(Encoder* encoder)
|
| - : SkCanvas(1,1)
|
| - , fEncoder(encoder)
|
| - {}
|
| -
|
| - void Client::willSave() { fEncoder->save(); }
|
| - void Client::didRestore() { fEncoder->restore(); }
|
| -
|
| - void Client::didConcat (const SkMatrix&) { this->didSetMatrix(this->getTotalMatrix()); }
|
| - void Client::didSetMatrix(const SkMatrix& matrix) {
|
| - fEncoder->setMatrix(this->id(matrix));
|
| - }
|
| -
|
| - void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) {
|
| - SkPath path;
|
| - path.addOval(oval);
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawRect(const SkRect& rect, const SkPaint& paint) {
|
| - SkPath path;
|
| - path.addRect(rect);
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
|
| - SkPath path;
|
| - path.addRRect(rrect);
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawDRRect(const SkRRect& outside,
|
| - const SkRRect& inside,
|
| - const SkPaint& paint) {
|
| - SkPath path;
|
| - path.addRRect(outside);
|
| - path.addRRect(inside, SkPath::kCCW_Direction);
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawPath(const SkPath& path, const SkPaint& paint) {
|
| - auto p = this->id(path),
|
| - m = this->id(Misc::CreateFrom(paint)),
|
| - s = this->id(paint.getShader()),
|
| - x = this->id(paint.getXfermode());
|
| -
|
| - if (paint.getStyle() == SkPaint::kFill_Style) {
|
| - fEncoder->fillPath(p, m, s, x);
|
| - } else {
|
| - // TODO: handle kStrokeAndFill_Style
|
| - fEncoder->strokePath(p, m, s, x, this->id(Stroke::CreateFrom(paint)));
|
| - }
|
| - }
|
| -
|
| - void Client::onDrawPaint(const SkPaint& paint) {
|
| - SkPath path;
|
| - path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse FillType works fine.
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawText(const void* text, size_t byteLength, SkScalar x,
|
| - SkScalar y, const SkPaint& paint) {
|
| - // Text-as-paths is a temporary hack.
|
| - // TODO: send SkTextBlobs and SkTypefaces
|
| - SkPath path;
|
| - paint.getTextPath(text, byteLength, x, y, &path);
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawPosText(const void* text, size_t byteLength,
|
| - const SkPoint pos[], const SkPaint& paint) {
|
| - // Text-as-paths is a temporary hack.
|
| - // TODO: send SkTextBlobs and SkTypefaces
|
| - SkPath path;
|
| - paint.getPosTextPath(text, byteLength, pos, &path);
|
| - this->onDrawPath(path, paint);
|
| - }
|
| -
|
| - void Client::onDrawPosTextH(const void* text, size_t byteLength,
|
| - const SkScalar xpos[], SkScalar constY,
|
| - const SkPaint& paint) {
|
| - size_t length = paint.countText(text, byteLength);
|
| - SkAutoTArray<SkPoint> pos(length);
|
| - for(size_t i = 0; i < length; ++i) {
|
| - pos[i].set(xpos[i], constY);
|
| - }
|
| - this->onDrawPosText(text, byteLength, &pos[0], paint);
|
| - }
|
| -
|
| - void Client::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
|
| - SkPath path;
|
| - path.addRect(rect);
|
| - this->onClipPath(path, op, edgeStyle);
|
| - }
|
| -
|
| - void Client::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
|
| - SkPath path;
|
| - path.addRRect(rrect);
|
| - this->onClipPath(path, op, edgeStyle);
|
| - }
|
| -
|
| - void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
|
| - fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle);
|
| - }
|
| -
|
| - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
| -
|
| - Server::Server(SkCanvas* canvas) : fCanvas(canvas) {}
|
| -
|
| - template <typename Map, typename T>
|
| - ID Server::define(Type type, Map* map, const T& val) {
|
| - ID id(type, fNextID++);
|
| - map->set(id, val);
|
| - return id;
|
| - }
|
| -
|
| - ID Server::define(const SkMatrix& v) { return this->define(Type::kMatrix, &fMatrix, v); }
|
| - ID Server::define(const Misc& v) { return this->define(Type::kMisc, &fMisc, v); }
|
| - ID Server::define(const SkPath& v) { return this->define(Type::kPath, &fPath, v); }
|
| - ID Server::define(const Stroke& v) { return this->define(Type::kStroke, &fStroke, v); }
|
| - ID Server::define(SkShader* v) { return this->define(Type::kShader, &fShader, v); }
|
| - ID Server::define(SkXfermode* v) { return this->define(Type::kXfermode, &fXfermode, v); }
|
| -
|
| - void Server::undefine(ID id) {
|
| - switch(id.type()) {
|
| - case Type::kMatrix: return fMatrix .remove(id);
|
| - case Type::kMisc: return fMisc .remove(id);
|
| - case Type::kPath: return fPath .remove(id);
|
| - case Type::kStroke: return fStroke .remove(id);
|
| - case Type::kShader: return fShader .remove(id);
|
| - case Type::kXfermode: return fXfermode.remove(id);
|
| - };
|
| - }
|
| -
|
| - void Server:: save() { fCanvas->save(); }
|
| - void Server::restore() { fCanvas->restore(); }
|
| -
|
| - void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix)); }
|
| -
|
| - void Server::clipPath(ID path, SkRegion::Op op, bool aa) {
|
| - fCanvas->clipPath(fPath.find(path), op, aa);
|
| - }
|
| - void Server::fillPath(ID path, ID misc, ID shader, ID xfermode) {
|
| - SkPaint paint;
|
| - paint.setStyle(SkPaint::kFill_Style);
|
| - fMisc.find(misc).applyTo(&paint);
|
| - paint.setShader (fShader .find(shader));
|
| - paint.setXfermode(fXfermode.find(xfermode));
|
| - fCanvas->drawPath(fPath.find(path), paint);
|
| - }
|
| - void Server::strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke) {
|
| - SkPaint paint;
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| - fMisc .find(misc ).applyTo(&paint);
|
| - fStroke.find(stroke).applyTo(&paint);
|
| - paint.setShader (fShader .find(shader));
|
| - paint.setXfermode(fXfermode.find(xfermode));
|
| - fCanvas->drawPath(fPath.find(path), paint);
|
| - }
|
| + Encoder* NewCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wrapped); }
|
|
|
| } // namespace SkRemote
|
|
|