/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkAnnotation.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkDrawLooper.h"
#include "SkImage.h"
#include "SkImageFilter.h"
#include "SkMaskFilter.h"
#include "SkNinePatchIter.h"
#include "SkPath.h"
#include "SkPathEffect.h"
#include "SkRasterizer.h"
#include "SkRect.h"
#include "SkRemote.h"
#include "SkShader.h"
#include "SkTHash.h"
#include "SkTextBlob.h"

namespace SkRemote {

    Misc Misc::CreateFrom(const SkPaint& paint) {
        Misc misc = {
            paint.getColor(),
            paint.getFilterQuality(),
            paint.isAntiAlias(),
            paint.isDither(),
        };
        return misc;
    }

    void Misc::applyTo(SkPaint* paint) const {
        paint->setColor        (fColor);
        paint->setFilterQuality(fFilterQuality);
        paint->setAntiAlias    (fAntiAlias);
        paint->setDither       (fDither);
    }

    static bool operator==(const Misc& a, const Misc& b) {
        return a.fColor         == b.fColor
            && a.fFilterQuality == b.fFilterQuality
            && a.fAntiAlias     == b.fAntiAlias
            && a.fDither        == b.fDither;
    }

    // Misc carries 10 bytes of data in a 12 byte struct, so we need a custom hash.
    static_assert(sizeof(Misc) > offsetof(Misc, fDither) + sizeof(Misc().fDither), "");
    struct MiscHash {
        uint32_t operator()(const Misc& misc) {
            return SkChecksum::Murmur3(&misc, offsetof(Misc, fDither) + sizeof(Misc().fDither));
        }
    };

    Stroke Stroke::CreateFrom(const SkPaint& paint) {
        Stroke stroke = {
            paint.getStrokeWidth(),
            paint.getStrokeMiter(),
            paint.getStrokeCap(),
            paint.getStrokeJoin(),
        };
        return stroke;
    }

    void Stroke::applyTo(SkPaint* paint) const {
        paint->setStrokeWidth(fWidth);
        paint->setStrokeMiter(fMiter);
        paint->setStrokeCap  (fCap);
        paint->setStrokeJoin (fJoin);
    }

    static bool operator==(const Stroke& a, const Stroke& b) {
        return a.fWidth == b.fWidth
            && a.fMiter == b.fMiter
            && a.fCap   == b.fCap
            && a.fJoin  == b.fJoin;
    }

    // The default SkGoodHash works fine for Stroke, as it's dense.
    static_assert(sizeof(Stroke) == offsetof(Stroke, fJoin) + sizeof(Stroke().fJoin), "");

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

    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;
        };

        // Like AutoID, but for CommonIDs.
        class AutoCommonIDs : ::SkNoncopyable {
        public:
            explicit AutoCommonIDs(Encoder* encoder, const SkPaint& paint)
                : fEncoder(encoder) {
                fIDs.misc        = fEncoder->define(Misc::CreateFrom(paint));
                fIDs.patheffect  = fEncoder->define(paint.getPathEffect());
                fIDs.shader      = fEncoder->define(paint.getShader());
                fIDs.xfermode    = fEncoder->define(paint.getXfermode());
                fIDs.maskfilter  = fEncoder->define(paint.getMaskFilter());
                fIDs.colorfilter = fEncoder->define(paint.getColorFilter());
                fIDs.rasterizer  = fEncoder->define(paint.getRasterizer());
                fIDs.looper      = fEncoder->define(paint.getLooper());
                fIDs.imagefilter = fEncoder->define(paint.getImageFilter());
                fIDs.annotation  = fEncoder->define(paint.getAnnotation());
            }
            ~AutoCommonIDs() {
                if (fEncoder) {
                    fEncoder->undefine(fIDs.misc);
                    fEncoder->undefine(fIDs.patheffect);
                    fEncoder->undefine(fIDs.shader);
                    fEncoder->undefine(fIDs.xfermode);
                    fEncoder->undefine(fIDs.maskfilter);
                    fEncoder->undefine(fIDs.colorfilter);
                    fEncoder->undefine(fIDs.rasterizer);
                    fEncoder->undefine(fIDs.looper);
                    fEncoder->undefine(fIDs.imagefilter);
                    fEncoder->undefine(fIDs.annotation);
                }
            }

            AutoCommonIDs(AutoCommonIDs&& o) : fEncoder(o.fEncoder), fIDs(o.fIDs) {
                o.fEncoder = nullptr;
            }
            AutoID& operator=(AutoID&&) = delete;

            operator Encoder::CommonIDs () const { return fIDs; }

        private:
            Encoder*           fEncoder;
            Encoder::CommonIDs fIDs;
        };

        template <typename T>
        AutoID id(const T& val) { return AutoID(fEncoder, val); }

        AutoCommonIDs commonIDs(const SkPaint& paint) { return AutoCommonIDs(fEncoder, paint); }

        void   willSave() override { fEncoder->   save(); }
        void didRestore() override { fEncoder->restore(); }
        SaveLayerStrategy willSaveLayer(const SkRect* bounds,
                                        const SkPaint* paint,
                                        SaveFlags flags) override {
            SkPath path;
            if (bounds) {
                path.addRect(*bounds);
            }
            const SkPaint defaultPaint;
            if (!paint) {
                paint = &defaultPaint;
            }
            fEncoder->saveLayer(this->id(path), this->commonIDs(*paint), flags);
            return kNoLayer_SaveLayerStrategy;
        }

        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 common = this->commonIDs(paint);
            auto p = this->id(path);

            if (paint.getStyle() == SkPaint::kFill_Style) {
                fEncoder->fillPath(p, common);
            } else {
                // TODO: handle kStrokeAndFill_Style
                fEncoder->strokePath(p, common, 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 onDrawPoints(PointMode mode,
                          size_t count,
                          const SkPoint pts[],
                          const SkPaint& paint) override {
            // TODO
        }

        void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
            // TODO
            this->INHERITED::onDrawDrawable(drawable, matrix);
        }

        void onDrawPicture(const SkPicture* pic,
                           const SkMatrix* matrix,
                           const SkPaint* paint) override {
            // TODO
            this->INHERITED::onDrawPicture(pic, matrix, paint);
        }

        void onDrawVertices(VertexMode vmode,
                            int vertexCount,
                            const SkPoint vertices[],
                            const SkPoint texs[],
                            const SkColor colors[],
                            SkXfermode* xmode,
                            const uint16_t indices[],
                            int indexCount,
                            const SkPaint& paint) override {
            // TODO
        }

        void onDrawPatch(const SkPoint cubics[12],
                         const SkColor colors[4],
                         const SkPoint texCoords[4],
                         SkXfermode* xmode,
                         const SkPaint& paint) override {
            // TODO
        }

        void onDrawAtlas(const SkImage* atlas,
                         const SkRSXform xform[],
                         const SkRect tex[],
                         const SkColor colors[],
                         int count,
                         SkXfermode::Mode mode,
                         const SkRect* cull,
                         const SkPaint* paint) override {
            // TODO
        }

        void onDrawBitmap(const SkBitmap& bitmap,
                          SkScalar left,
                          SkScalar top,
                          const SkPaint* paint) override {
            auto src = SkRect::MakeWH(bitmap.width(), bitmap.height()),
                 dst = src.makeOffset(left, top);
            this->onDrawBitmapRect(bitmap, &src, dst, paint, kStrict_SrcRectConstraint);
        }

        void onDrawBitmapRect(const SkBitmap& bitmap,
                              const SkRect* src,
                              const SkRect& dst,
                              const SkPaint* paint,
                              SrcRectConstraint constraint) override {
            SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap));
            this->onDrawImageRect(image, src, dst, paint, constraint);
        }

        void onDrawImage(const SkImage* image,
                         SkScalar left,
                         SkScalar top,
                         const SkPaint* paint) override {
            if (!image) {
                return;
            }
            auto src = SkRect::MakeWH(image->width(), image->height()),
                 dst = src.makeOffset(left, top);
            this->onDrawImageRect(image, &src, dst, paint, kStrict_SrcRectConstraint);
        }

        void onDrawImageRect(const SkImage* image,
                             const SkRect* src,
                             const SkRect& dst,
                             const SkPaint* paint,
                             SrcRectConstraint constraint) override {
            // TODO: this is all a (likely buggy) hack to get images drawing quickly.
            if (!image) {
                return;
            }

            auto bounds = SkRect::MakeWH(image->width(), image->height());
            if (!src) {
                src = &bounds;
            }
            auto matrix = SkMatrix::MakeRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit);

            SkAutoTUnref<SkImage> subset;
            if (src) {
                if (!bounds.intersect(*src)) {
                    return;
                }
                subset.reset(image->newSubset(bounds.roundOut()));
                image = subset;
            }

            auto paintWithShader = paint ? *paint : SkPaint();
            SkAutoTUnref<SkShader> shader(
                image->newShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix));
            paintWithShader.setShader(shader);

            this->onDrawRect(dst, paintWithShader);
        }

        void onDrawBitmapNine(const SkBitmap& bitmap,
                              const SkIRect& center,
                              const SkRect& dst,
                              const SkPaint* paint) override {
            SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap));
            this->onDrawImageNine(image, center, dst, paint);
        }

        void onDrawImageNine(const SkImage* image,
                             const SkIRect& center,
                             const SkRect& dst,
                             const SkPaint* paint) override {
            SkNinePatchIter iter(image->width(), image->height(), center, dst);
            SkRect s,d;
            while (iter.next(&s, &d)) {
                this->onDrawImageRect(image, &s, d, paint, kStrict_SrcRectConstraint);
            }
        }

        void onDrawTextBlob(const SkTextBlob* text,
                            SkScalar x,
                            SkScalar y,
                            const SkPaint& paint) override {
            SkPoint offset{x,y};
            auto t = this->id(text);
            auto common = this->commonIDs(paint);

            if (paint.getStyle() == SkPaint::kFill_Style) {
                fEncoder->fillText(t, offset, common);
            } else {
                // TODO: handle kStrokeAndFill_Style
                fEncoder->strokeText(t, offset, common, this->id(Stroke::CreateFrom(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);
        }

        // All clip calls need to call their parent method or we'll not get any quick rejects.
        void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
            this->INHERITED::onClipRect(rect, op, edgeStyle);
            SkPath path;
            path.addRect(rect);
            this->onClipPath(path, op, edgeStyle);
        }

        void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
            this->INHERITED::onClipRRect(rrect, op, edgeStyle);
            SkPath path;
            path.addRRect(rrect);
            this->onClipPath(path, op, edgeStyle);
        }

        void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
            this->INHERITED::onClipPath(path, op, edgeStyle);
            fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle);
        }

        void onClipRegion(const SkRegion& region, SkRegion::Op op) override {
            this->INHERITED::onClipRegion(region, op);
            // TODO
        }

        Encoder* fEncoder;
        typedef SkCanvas INHERITED;
    };

    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;
        }

    #define O override
        ID define(const SkMatrix&   v)O{return this->define(Type::kMatrix,      &fMatrix,      v);}
        ID define(const Misc&       v)O{return this->define(Type::kMisc,        &fMisc,        v);}
        ID define(const SkPath&     v)O{return this->define(Type::kPath,        &fPath,        v);}
        ID define(const Stroke&     v)O{return this->define(Type::kStroke,      &fStroke,      v);}
        ID define(const SkTextBlob* v)O{return this->define(Type::kTextBlob,    &fTextBlob,    v);}
        ID define(SkPathEffect*     v)O{return this->define(Type::kPathEffect,  &fPathEffect,  v);}
        ID define(SkShader*         v)O{return this->define(Type::kShader,      &fShader,      v);}
        ID define(SkXfermode*       v)O{return this->define(Type::kXfermode,    &fXfermode,    v);}
        ID define(SkMaskFilter*     v)O{return this->define(Type::kMaskFilter,  &fMaskFilter,  v);}
        ID define(SkColorFilter*    v)O{return this->define(Type::kColorFilter, &fColorFilter, v);}
        ID define(SkRasterizer*     v)O{return this->define(Type::kRasterizer,  &fRasterizer,  v);}
        ID define(SkDrawLooper*     v)O{return this->define(Type::kDrawLooper,  &fDrawLooper,  v);}
        ID define(SkImageFilter*    v)O{return this->define(Type::kImageFilter, &fImageFilter, v);}
        ID define(SkAnnotation*     v)O{return this->define(Type::kAnnotation,  &fAnnotation,  v);}
    #undef O


        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::kTextBlob:    return fTextBlob   .remove(id);
                case Type::kPathEffect:  return fPathEffect .remove(id);
                case Type::kShader:      return fShader     .remove(id);
                case Type::kXfermode:    return fXfermode   .remove(id);
                case Type::kMaskFilter:  return fMaskFilter .remove(id);
                case Type::kColorFilter: return fColorFilter.remove(id);
                case Type::kRasterizer:  return fRasterizer .remove(id);
                case Type::kDrawLooper:  return fDrawLooper .remove(id);
                case Type::kImageFilter: return fImageFilter.remove(id);
                case Type::kAnnotation:  return fAnnotation .remove(id);
            };
        }

        void applyCommon(const CommonIDs& common, SkPaint* paint) const {
            fMisc.find(common.misc).applyTo(paint);
            paint->setPathEffect (fPathEffect .find(common.patheffect));
            paint->setShader     (fShader     .find(common.shader));
            paint->setXfermode   (fXfermode   .find(common.xfermode));
            paint->setMaskFilter (fMaskFilter .find(common.maskfilter));
            paint->setColorFilter(fColorFilter.find(common.colorfilter));
            paint->setRasterizer (fRasterizer .find(common.rasterizer));
            paint->setLooper     (fDrawLooper .find(common.looper));
            paint->setImageFilter(fImageFilter.find(common.imagefilter));
            paint->setAnnotation (fAnnotation .find(common.annotation));
        }

        void    save() override { fCanvas->save(); }
        void restore() override { fCanvas->restore(); }
        void saveLayer(ID bounds, CommonIDs common, SkCanvas::SaveFlags flags) override {
            SkPaint paint;
            this->applyCommon(common, &paint);
            SkRect rect;
            fCanvas->saveLayer(fPath.find(bounds).isRect(&rect) ? &rect : nullptr, &paint, flags);
        }

        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, CommonIDs common) override {
            SkPaint paint;
            paint.setStyle(SkPaint::kFill_Style);
            this->applyCommon(common, &paint);
            fCanvas->drawPath(fPath.find(path), paint);
        }
        void strokePath(ID path, CommonIDs common, ID stroke) override {
            SkPaint paint;
            paint.setStyle(SkPaint::kStroke_Style);
            this->applyCommon(common, &paint);
            fStroke.find(stroke).applyTo(&paint);
            fCanvas->drawPath(fPath.find(path), paint);
        }
        void fillText(ID text, SkPoint offset, CommonIDs common) override {
            SkPaint paint;
            paint.setStyle(SkPaint::kFill_Style);
            this->applyCommon(common, &paint);
            fCanvas->drawTextBlob(fTextBlob.find(text), offset.x(), offset.y(), paint);
        }
        void strokeText(ID text, SkPoint offset, CommonIDs common, ID stroke) override {
            SkPaint paint;
            this->applyCommon(common, &paint);
            fStroke.find(stroke).applyTo(&paint);
            fCanvas->drawTextBlob(fTextBlob.find(text), offset.x(), offset.y(), 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<const SkTextBlob, Type::kTextBlob   > fTextBlob;
        ReffedIDMap<SkPathEffect    , Type::kPathEffect > fPathEffect;
        ReffedIDMap<SkShader        , Type::kShader     > fShader;
        ReffedIDMap<SkXfermode      , Type::kXfermode   > fXfermode;
        ReffedIDMap<SkMaskFilter    , Type::kMaskFilter > fMaskFilter;
        ReffedIDMap<SkColorFilter   , Type::kColorFilter> fColorFilter;
        ReffedIDMap<SkRasterizer    , Type::kRasterizer > fRasterizer;
        ReffedIDMap<SkDrawLooper    , Type::kDrawLooper > fDrawLooper;
        ReffedIDMap<SkImageFilter   , Type::kImageFilter> fImageFilter;
        ReffedIDMap<SkAnnotation    , Type::kAnnotation > fAnnotation;

        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) {}

    private:
        struct Undef {
            Encoder* fEncoder;
            template <typename T>
            void operator()(const T&, ID* id) const { fEncoder->undefine(*id); }
        };

        ~CachingEncoder() override {
            Undef undef{fWrapped};
            fMatrix     .foreach(undef);
            fMisc       .foreach(undef);
            fPath       .foreach(undef);
            fStroke     .foreach(undef);
            fTextBlob   .foreach(undef);
            fPathEffect .foreach(undef);
            fShader     .foreach(undef);
            fXfermode   .foreach(undef);
            fMaskFilter .foreach(undef);
            fColorFilter.foreach(undef);
            fRasterizer .foreach(undef);
            fDrawLooper .foreach(undef);
            fImageFilter.foreach(undef);
            fAnnotation .foreach(undef);
        }

        template <typename Map, typename T>
        ID define(Map* map, const T& v) {
            if (const ID* id = map->find(v)) {
                return *id;
            }
            ID id = fWrapped->define(v);
            map->set(v, id);
            return id;
        }

        ID define(const SkMatrix&   v) override { return this->define(&fMatrix     , v); }
        ID define(const Misc&       v) override { return this->define(&fMisc       , v); }
        ID define(const SkPath&     v) override { return this->define(&fPath       , v); }
        ID define(const Stroke&     v) override { return this->define(&fStroke     , v); }
        ID define(const SkTextBlob* v) override { return this->define(&fTextBlob   , v); }
        ID define(SkPathEffect*     v) override { return this->define(&fPathEffect , v); }
        ID define(SkShader*         v) override { return this->define(&fShader     , v); }
        ID define(SkXfermode*       v) override { return this->define(&fXfermode   , v); }
        ID define(SkMaskFilter*     v) override { return this->define(&fMaskFilter , v); }
        ID define(SkColorFilter*    v) override { return this->define(&fColorFilter, v); }
        ID define(SkRasterizer*     v) override { return this->define(&fRasterizer , v); }
        ID define(SkDrawLooper*     v) override { return this->define(&fDrawLooper , v); }
        ID define(SkImageFilter*    v) override { return this->define(&fImageFilter, v); }
        ID define(SkAnnotation*     v) override { return this->define(&fAnnotation , v); }

        void undefine(ID) override {}

        void    save() override { fWrapped->   save(); }
        void restore() override { fWrapped->restore(); }
        void saveLayer(ID bounds, CommonIDs common, SkCanvas::SaveFlags flags) override {
            fWrapped->saveLayer(bounds, common, flags);
        }

        void setMatrix(ID matrix) override { fWrapped->setMatrix(matrix); }

        void clipPath(ID path, SkRegion::Op op, bool aa) override {
            fWrapped->clipPath(path, op, aa);
        }
        void fillPath(ID path, CommonIDs common) override {
            fWrapped->fillPath(path, common);
        }
        void strokePath(ID path, CommonIDs common, ID stroke) override {
            fWrapped->strokePath(path, common, stroke);
        }
        void fillText(ID text, SkPoint offset, CommonIDs common) override {
            fWrapped->fillText(text, offset, common);
        }
        void strokeText(ID text, SkPoint offset, CommonIDs common, ID stroke) override {
            fWrapped->strokeText(text, offset, common, stroke);
        }

        // Maps const T* -> ID, and refs the key.
        template <typename T, Type kType>
        class RefKeyMap {
        public:
            RefKeyMap() {}
            ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { SkSafeUnref(key); }); }

            void set(const T* key, ID id) {
                SkASSERT(id.type() == kType);
                fMap.set(SkSafeRef(key), id);
            }

            void remove(const T* key) {
                fMap.remove(key);
                SkSafeUnref(key);
            }

            const ID* find(const T* key) const {
                return fMap.find(key);
            }

            template <typename Fn>
            void foreach(const Fn& fn) {
                fMap.foreach(fn);
            }
        private:
            SkTHashMap<const T*, ID> fMap;
        };

        SkTHashMap<SkMatrix, ID>                        fMatrix;
        SkTHashMap<Misc, ID, MiscHash>                  fMisc;
        SkTHashMap<SkPath, ID>                          fPath;
        SkTHashMap<Stroke, ID>                          fStroke;
        RefKeyMap<const SkTextBlob, Type::kTextBlob   > fTextBlob;
        RefKeyMap<SkPathEffect    , Type::kPathEffect > fPathEffect;
        RefKeyMap<SkShader        , Type::kShader     > fShader;
        RefKeyMap<SkXfermode      , Type::kXfermode   > fXfermode;
        RefKeyMap<SkMaskFilter    , Type::kMaskFilter > fMaskFilter;
        RefKeyMap<SkColorFilter   , Type::kColorFilter> fColorFilter;
        RefKeyMap<SkRasterizer    , Type::kRasterizer > fRasterizer;
        RefKeyMap<SkDrawLooper    , Type::kDrawLooper > fDrawLooper;
        RefKeyMap<SkImageFilter   , Type::kImageFilter> fImageFilter;
        RefKeyMap<SkAnnotation    , Type::kAnnotation > fAnnotation;

        Encoder* fWrapped;
    };

    Encoder* NewCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wrapped); }

} // namespace SkRemote
