Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkAnnotation.h"
      9 #include "SkCanvas.h"
     10 #include "SkColorFilter.h"
     11 #include "SkDrawLooper.h"
     12 #include "SkImage.h"
     13 #include "SkImageFilter.h"
     14 #include "SkMaskFilter.h"
     15 #include "SkNinePatchIter.h"
     16 #include "SkPath.h"
     17 #include "SkPathEffect.h"
     18 #include "SkRasterizer.h"
     19 #include "SkRect.h"
     20 #include "SkRemote.h"
     21 #include "SkShader.h"
     22 #include "SkTHash.h"
     23 #include "SkTextBlob.h"
     24 
     25 namespace SkRemote {
     26 
     27     Misc Misc::CreateFrom(const SkPaint& paint) {
     28         Misc misc = {
     29             paint.getColor(),
     30             paint.getFilterQuality(),
     31             paint.isAntiAlias(),
     32             paint.isDither(),
     33         };
     34         return misc;
     35     }
     36 
     37     void Misc::applyTo(SkPaint* paint) const {
     38         paint->setColor        (fColor);
     39         paint->setFilterQuality(fFilterQuality);
     40         paint->setAntiAlias    (fAntiAlias);
     41         paint->setDither       (fDither);
     42     }
     43 
     44     static bool operator==(const Misc& a, const Misc& b) {
     45         return a.fColor         == b.fColor
     46             && a.fFilterQuality == b.fFilterQuality
     47             && a.fAntiAlias     == b.fAntiAlias
     48             && a.fDither        == b.fDither;
     49     }
     50 
     51     // Misc carries 10 bytes of data in a 12 byte struct, so we need a custom hash.
     52     static_assert(sizeof(Misc) > offsetof(Misc, fDither) + sizeof(Misc().fDither), "");
     53     struct MiscHash {
     54         uint32_t operator()(const Misc& misc) {
     55             return SkChecksum::Murmur3(&misc, offsetof(Misc, fDither) + sizeof(Misc().fDither));
     56         }
     57     };
     58 
     59     Stroke Stroke::CreateFrom(const SkPaint& paint) {
     60         Stroke stroke = {
     61             paint.getStrokeWidth(),
     62             paint.getStrokeMiter(),
     63             paint.getStrokeCap(),
     64             paint.getStrokeJoin(),
     65         };
     66         return stroke;
     67     }
     68 
     69     void Stroke::applyTo(SkPaint* paint) const {
     70         paint->setStrokeWidth(fWidth);
     71         paint->setStrokeMiter(fMiter);
     72         paint->setStrokeCap  (fCap);
     73         paint->setStrokeJoin (fJoin);
     74     }
     75 
     76     static bool operator==(const Stroke& a, const Stroke& b) {
     77         return a.fWidth == b.fWidth
     78             && a.fMiter == b.fMiter
     79             && a.fCap   == b.fCap
     80             && a.fJoin  == b.fJoin;
     81     }
     82 
     83     // The default SkGoodHash works fine for Stroke, as it's dense.
     84     static_assert(sizeof(Stroke) == offsetof(Stroke, fJoin) + sizeof(Stroke().fJoin), "");
     85 
     86     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
     87 
     88     class Canvas final : public SkCanvas {
     89     public:
     90         explicit Canvas(Encoder* encoder)
     91             : SkCanvas(1,1)
     92             , fEncoder(encoder) {}
     93 
     94     private:
     95         // Calls Encoder::define() when created, Encoder::undefine() when destroyed.
     96         class AutoID : ::SkNoncopyable {
     97         public:
     98             template <typename T>
     99             explicit AutoID(Encoder* encoder, const T& val)
    100                 : fEncoder(encoder)
    101                 , fID(encoder->define(val)) {}
    102             ~AutoID() { if (fEncoder) fEncoder->undefine(fID); }
    103 
    104             AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) {
    105                 o.fEncoder = nullptr;
    106             }
    107             AutoID& operator=(AutoID&&) = delete;
    108 
    109             operator ID () const { return fID; }
    110 
    111         private:
    112             Encoder* fEncoder;
    113             const ID fID;
    114         };
    115 
    116         // Like AutoID, but for CommonIDs.
    117         class AutoCommonIDs : ::SkNoncopyable {
    118         public:
    119             explicit AutoCommonIDs(Encoder* encoder, const SkPaint& paint)
    120                 : fEncoder(encoder) {
    121                 fIDs.misc        = fEncoder->define(Misc::CreateFrom(paint));
    122                 fIDs.patheffect  = fEncoder->define(paint.getPathEffect());
    123                 fIDs.shader      = fEncoder->define(paint.getShader());
    124                 fIDs.xfermode    = fEncoder->define(paint.getXfermode());
    125                 fIDs.maskfilter  = fEncoder->define(paint.getMaskFilter());
    126                 fIDs.colorfilter = fEncoder->define(paint.getColorFilter());
    127                 fIDs.rasterizer  = fEncoder->define(paint.getRasterizer());
    128                 fIDs.looper      = fEncoder->define(paint.getLooper());
    129                 fIDs.imagefilter = fEncoder->define(paint.getImageFilter());
    130                 fIDs.annotation  = fEncoder->define(paint.getAnnotation());
    131             }
    132             ~AutoCommonIDs() {
    133                 if (fEncoder) {
    134                     fEncoder->undefine(fIDs.misc);
    135                     fEncoder->undefine(fIDs.patheffect);
    136                     fEncoder->undefine(fIDs.shader);
    137                     fEncoder->undefine(fIDs.xfermode);
    138                     fEncoder->undefine(fIDs.maskfilter);
    139                     fEncoder->undefine(fIDs.colorfilter);
    140                     fEncoder->undefine(fIDs.rasterizer);
    141                     fEncoder->undefine(fIDs.looper);
    142                     fEncoder->undefine(fIDs.imagefilter);
    143                     fEncoder->undefine(fIDs.annotation);
    144                 }
    145             }
    146 
    147             AutoCommonIDs(AutoCommonIDs&& o) : fEncoder(o.fEncoder), fIDs(o.fIDs) {
    148                 o.fEncoder = nullptr;
    149             }
    150             AutoID& operator=(AutoID&&) = delete;
    151 
    152             operator Encoder::CommonIDs () const { return fIDs; }
    153 
    154         private:
    155             Encoder*           fEncoder;
    156             Encoder::CommonIDs fIDs;
    157         };
    158 
    159         template <typename T>
    160         AutoID id(const T& val) { return AutoID(fEncoder, val); }
    161 
    162         AutoCommonIDs commonIDs(const SkPaint& paint) { return AutoCommonIDs(fEncoder, paint); }
    163 
    164         void   willSave() override { fEncoder->   save(); }
    165         void didRestore() override { fEncoder->restore(); }
    166         SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
    167             SkPath path;
    168             if (rec.fBounds) {
    169                 path.addRect(*rec.fBounds);
    170             }
    171             const SkPaint defaultPaint;
    172             const SkPaint* paint = rec.fPaint;
    173             if (!paint) {
    174                 paint = &defaultPaint;
    175             }
    176             fEncoder->saveLayer(this->id(path), this->commonIDs(*paint), rec.fSaveLayerFlags);
    177             return kNoLayer_SaveLayerStrategy;
    178         }
    179 
    180         void    didConcat(const SkMatrix&) override { this->didSetMatrix(this->getTotalMatrix()); }
    181         void didSetMatrix(const SkMatrix& matrix) override {
    182             fEncoder->setMatrix(this->id(matrix));
    183         }
    184 
    185         void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
    186             SkPath path;
    187             path.addOval(oval);
    188             this->onDrawPath(path, paint);
    189         }
    190 
    191         void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
    192             SkPath path;
    193             path.addRect(rect);
    194             this->onDrawPath(path, paint);
    195         }
    196 
    197         void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
    198             SkPath path;
    199             path.addRRect(rrect);
    200             this->onDrawPath(path, paint);
    201         }
    202 
    203         void onDrawDRRect(const SkRRect& outside, const SkRRect& inside,
    204                           const SkPaint& paint) override {
    205             SkPath path;
    206             path.addRRect(outside);
    207             path.addRRect(inside, SkPath::kCCW_Direction);
    208             this->onDrawPath(path, paint);
    209         }
    210 
    211         void onDrawPath(const SkPath& path, const SkPaint& paint) override {
    212             auto common = this->commonIDs(paint);
    213             auto p = this->id(path);
    214 
    215             if (paint.getStyle() == SkPaint::kFill_Style) {
    216                 fEncoder->fillPath(p, common);
    217             } else {
    218                 // TODO: handle kStrokeAndFill_Style
    219                 fEncoder->strokePath(p, common, this->id(Stroke::CreateFrom(paint)));
    220             }
    221         }
    222 
    223         void onDrawPaint(const SkPaint& paint) override {
    224             SkPath path;
    225             path.setFillType(SkPath::kInverseWinding_FillType);  // Either inverse FillType is fine.
    226             this->onDrawPath(path, paint);
    227         }
    228 
    229         void onDrawPoints(PointMode mode,
    230                           size_t count,
    231                           const SkPoint pts[],
    232                           const SkPaint& paint) override {
    233             // TODO
    234         }
    235 
    236         void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
    237             // TODO
    238             this->INHERITED::onDrawDrawable(drawable, matrix);
    239         }
    240 
    241         void onDrawPicture(const SkPicture* pic,
    242                            const SkMatrix* matrix,
    243                            const SkPaint* paint) override {
    244             // TODO
    245             this->INHERITED::onDrawPicture(pic, matrix, paint);
    246         }
    247 
    248         void onDrawVertices(VertexMode vmode,
    249                             int vertexCount,
    250                             const SkPoint vertices[],
    251                             const SkPoint texs[],
    252                             const SkColor colors[],
    253                             SkXfermode* xmode,
    254                             const uint16_t indices[],
    255                             int indexCount,
    256                             const SkPaint& paint) override {
    257             // TODO
    258         }
    259 
    260         void onDrawPatch(const SkPoint cubics[12],
    261                          const SkColor colors[4],
    262                          const SkPoint texCoords[4],
    263                          SkXfermode* xmode,
    264                          const SkPaint& paint) override {
    265             // TODO
    266         }
    267 
    268         void onDrawAtlas(const SkImage* atlas,
    269                          const SkRSXform xform[],
    270                          const SkRect tex[],
    271                          const SkColor colors[],
    272                          int count,
    273                          SkXfermode::Mode mode,
    274                          const SkRect* cull,
    275                          const SkPaint* paint) override {
    276             // TODO
    277         }
    278 
    279         void onDrawBitmap(const SkBitmap& bitmap,
    280                           SkScalar left,
    281                           SkScalar top,
    282                           const SkPaint* paint) override {
    283             auto src = SkRect::MakeWH(bitmap.width(), bitmap.height()),
    284                  dst = src.makeOffset(left, top);
    285             this->onDrawBitmapRect(bitmap, &src, dst, paint, kStrict_SrcRectConstraint);
    286         }
    287 
    288         void onDrawBitmapRect(const SkBitmap& bitmap,
    289                               const SkRect* src,
    290                               const SkRect& dst,
    291                               const SkPaint* paint,
    292                               SrcRectConstraint constraint) override {
    293             SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap));
    294             this->onDrawImageRect(image, src, dst, paint, constraint);
    295         }
    296 
    297         void onDrawImage(const SkImage* image,
    298                          SkScalar left,
    299                          SkScalar top,
    300                          const SkPaint* paint) override {
    301             if (!image) {
    302                 return;
    303             }
    304             auto src = SkRect::MakeWH(image->width(), image->height()),
    305                  dst = src.makeOffset(left, top);
    306             this->onDrawImageRect(image, &src, dst, paint, kStrict_SrcRectConstraint);
    307         }
    308 
    309         void onDrawImageRect(const SkImage* image,
    310                              const SkRect* src,
    311                              const SkRect& dst,
    312                              const SkPaint* paint,
    313                              SrcRectConstraint constraint) override {
    314             // TODO: this is all a (likely buggy) hack to get images drawing quickly.
    315             if (!image) {
    316                 return;
    317             }
    318 
    319             auto bounds = SkRect::MakeWH(image->width(), image->height());
    320             if (!src) {
    321                 src = &bounds;
    322             }
    323             auto matrix = SkMatrix::MakeRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit);
    324 
    325             SkAutoTUnref<SkImage> subset;
    326             if (src) {
    327                 if (!bounds.intersect(*src)) {
    328                     return;
    329                 }
    330                 subset.reset(image->newSubset(bounds.roundOut()));
    331                 image = subset;
    332             }
    333 
    334             auto paintWithShader = paint ? *paint : SkPaint();
    335             SkAutoTUnref<SkShader> shader(
    336                 image->newShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix));
    337             paintWithShader.setShader(shader);
    338 
    339             this->onDrawRect(dst, paintWithShader);
    340         }
    341 
    342         void onDrawBitmapNine(const SkBitmap& bitmap,
    343                               const SkIRect& center,
    344                               const SkRect& dst,
    345                               const SkPaint* paint) override {
    346             SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bitmap));
    347             this->onDrawImageNine(image, center, dst, paint);
    348         }
    349 
    350         void onDrawImageNine(const SkImage* image,
    351                              const SkIRect& center,
    352                              const SkRect& dst,
    353                              const SkPaint* paint) override {
    354             SkNinePatchIter iter(image->width(), image->height(), center, dst);
    355             SkRect s,d;
    356             while (iter.next(&s, &d)) {
    357                 this->onDrawImageRect(image, &s, d, paint, kStrict_SrcRectConstraint);
    358             }
    359         }
    360 
    361         void onDrawTextBlob(const SkTextBlob* text,
    362                             SkScalar x,
    363                             SkScalar y,
    364                             const SkPaint& paint) override {
    365             SkPoint offset{x,y};
    366             auto t = this->id(text);
    367             auto common = this->commonIDs(paint);
    368 
    369             if (paint.getStyle() == SkPaint::kFill_Style) {
    370                 fEncoder->fillText(t, offset, common);
    371             } else {
    372                 // TODO: handle kStrokeAndFill_Style
    373                 fEncoder->strokeText(t, offset, common, this->id(Stroke::CreateFrom(paint)));
    374             }
    375         }
    376 
    377         void onDrawText(const void* text, size_t byteLength,
    378                         SkScalar x, SkScalar y, const SkPaint& paint) override {
    379             // Text-as-paths is a temporary hack.
    380             // TODO: send SkTextBlobs and SkTypefaces
    381             SkPath path;
    382             paint.getTextPath(text, byteLength, x, y, &path);
    383             this->onDrawPath(path, paint);
    384         }
    385 
    386         void onDrawPosText(const void* text, size_t byteLength,
    387                            const SkPoint pos[], const SkPaint& paint) override {
    388             // Text-as-paths is a temporary hack.
    389             // TODO: send SkTextBlobs and SkTypefaces
    390             SkPath path;
    391             paint.getPosTextPath(text, byteLength, pos, &path);
    392             this->onDrawPath(path, paint);
    393         }
    394 
    395         void onDrawPosTextH(const void* text, size_t byteLength,
    396                             const SkScalar xpos[], SkScalar constY, const SkPaint& paint) override {
    397             size_t length = paint.countText(text, byteLength);
    398             SkAutoTArray<SkPoint> pos(length);
    399             for(size_t i = 0; i < length; ++i) {
    400                 pos[i].set(xpos[i], constY);
    401             }
    402             this->onDrawPosText(text, byteLength, &pos[0], paint);
    403         }
    404 
    405         // All clip calls need to call their parent method or we'll not get any quick rejects.
    406         void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
    407             this->INHERITED::onClipRect(rect, op, edgeStyle);
    408             SkPath path;
    409             path.addRect(rect);
    410             this->onClipPath(path, op, edgeStyle);
    411         }
    412 
    413         void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
    414             this->INHERITED::onClipRRect(rrect, op, edgeStyle);
    415             SkPath path;
    416             path.addRRect(rrect);
    417             this->onClipPath(path, op, edgeStyle);
    418         }
    419 
    420         void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) override {
    421             this->INHERITED::onClipPath(path, op, edgeStyle);
    422             fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle);
    423         }
    424 
    425         void onClipRegion(const SkRegion& region, SkRegion::Op op) override {
    426             this->INHERITED::onClipRegion(region, op);
    427             // TODO
    428         }
    429 
    430         Encoder* fEncoder;
    431         typedef SkCanvas INHERITED;
    432     };
    433 
    434     SkCanvas* NewCanvas(Encoder* encoder) { return new Canvas(encoder); }
    435 
    436     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
    437 
    438     class Decoder final : public Encoder {
    439     public:
    440         explicit Decoder(SkCanvas* canvas) : fCanvas(canvas) {}
    441 
    442     private:
    443         template <typename Map, typename T>
    444         ID define(Type type, Map* map, const T& val) {
    445             ID id(type, fNextID++);
    446             map->set(id, val);
    447             return id;
    448         }
    449 
    450     #define O override
    451         ID define(const SkMatrix&   v)O{return this->define(Type::kMatrix,      &fMatrix,      v);}
    452         ID define(const Misc&       v)O{return this->define(Type::kMisc,        &fMisc,        v);}
    453         ID define(const SkPath&     v)O{return this->define(Type::kPath,        &fPath,        v);}
    454         ID define(const Stroke&     v)O{return this->define(Type::kStroke,      &fStroke,      v);}
    455         ID define(const SkTextBlob* v)O{return this->define(Type::kTextBlob,    &fTextBlob,    v);}
    456         ID define(SkPathEffect*     v)O{return this->define(Type::kPathEffect,  &fPathEffect,  v);}
    457         ID define(SkShader*         v)O{return this->define(Type::kShader,      &fShader,      v);}
    458         ID define(SkXfermode*       v)O{return this->define(Type::kXfermode,    &fXfermode,    v);}
    459         ID define(SkMaskFilter*     v)O{return this->define(Type::kMaskFilter,  &fMaskFilter,  v);}
    460         ID define(SkColorFilter*    v)O{return this->define(Type::kColorFilter, &fColorFilter, v);}
    461         ID define(SkRasterizer*     v)O{return this->define(Type::kRasterizer,  &fRasterizer,  v);}
    462         ID define(SkDrawLooper*     v)O{return this->define(Type::kDrawLooper,  &fDrawLooper,  v);}
    463         ID define(SkImageFilter*    v)O{return this->define(Type::kImageFilter, &fImageFilter, v);}
    464         ID define(SkAnnotation*     v)O{return this->define(Type::kAnnotation,  &fAnnotation,  v);}
    465     #undef O
    466 
    467 
    468         void undefine(ID id) override {
    469             switch(id.type()) {
    470                 case Type::kMatrix:      return fMatrix     .remove(id);
    471                 case Type::kMisc:        return fMisc       .remove(id);
    472                 case Type::kPath:        return fPath       .remove(id);
    473                 case Type::kStroke:      return fStroke     .remove(id);
    474                 case Type::kTextBlob:    return fTextBlob   .remove(id);
    475                 case Type::kPathEffect:  return fPathEffect .remove(id);
    476                 case Type::kShader:      return fShader     .remove(id);
    477                 case Type::kXfermode:    return fXfermode   .remove(id);
    478                 case Type::kMaskFilter:  return fMaskFilter .remove(id);
    479                 case Type::kColorFilter: return fColorFilter.remove(id);
    480                 case Type::kRasterizer:  return fRasterizer .remove(id);
    481                 case Type::kDrawLooper:  return fDrawLooper .remove(id);
    482                 case Type::kImageFilter: return fImageFilter.remove(id);
    483                 case Type::kAnnotation:  return fAnnotation .remove(id);
    484             };
    485         }
    486 
    487         void applyCommon(const CommonIDs& common, SkPaint* paint) const {
    488             fMisc.find(common.misc).applyTo(paint);
    489             paint->setPathEffect (fPathEffect .find(common.patheffect));
    490             paint->setShader     (fShader     .find(common.shader));
    491             paint->setXfermode   (fXfermode   .find(common.xfermode));
    492             paint->setMaskFilter (fMaskFilter .find(common.maskfilter));
    493             paint->setColorFilter(fColorFilter.find(common.colorfilter));
    494             paint->setRasterizer (fRasterizer .find(common.rasterizer));
    495             paint->setLooper     (fDrawLooper .find(common.looper));
    496             paint->setImageFilter(fImageFilter.find(common.imagefilter));
    497             paint->setAnnotation (fAnnotation .find(common.annotation));
    498         }
    499 
    500         void    save() override { fCanvas->save(); }
    501         void restore() override { fCanvas->restore(); }
    502         void saveLayer(ID bounds, CommonIDs common, SkCanvas::SaveLayerFlags flags) override {
    503             SkPaint paint;
    504             this->applyCommon(common, &paint);
    505             SkRect rect;
    506 
    507             fCanvas->saveLayer({ fPath.find(bounds).isRect(&rect) ? &rect : nullptr,
    508                                  &paint, flags });
    509         }
    510 
    511         void setMatrix(ID matrix) override { fCanvas->setMatrix(fMatrix.find(matrix)); }
    512 
    513         void clipPath(ID path, SkRegion::Op op, bool aa) override {
    514             fCanvas->clipPath(fPath.find(path), op, aa);
    515         }
    516         void fillPath(ID path, CommonIDs common) override {
    517             SkPaint paint;
    518             paint.setStyle(SkPaint::kFill_Style);
    519             this->applyCommon(common, &paint);
    520             fCanvas->drawPath(fPath.find(path), paint);
    521         }
    522         void strokePath(ID path, CommonIDs common, ID stroke) override {
    523             SkPaint paint;
    524             paint.setStyle(SkPaint::kStroke_Style);
    525             this->applyCommon(common, &paint);
    526             fStroke.find(stroke).applyTo(&paint);
    527             fCanvas->drawPath(fPath.find(path), paint);
    528         }
    529         void fillText(ID text, SkPoint offset, CommonIDs common) override {
    530             SkPaint paint;
    531             paint.setStyle(SkPaint::kFill_Style);
    532             this->applyCommon(common, &paint);
    533             fCanvas->drawTextBlob(fTextBlob.find(text), offset.x(), offset.y(), paint);
    534         }
    535         void strokeText(ID text, SkPoint offset, CommonIDs common, ID stroke) override {
    536             SkPaint paint;
    537             this->applyCommon(common, &paint);
    538             fStroke.find(stroke).applyTo(&paint);
    539             fCanvas->drawTextBlob(fTextBlob.find(text), offset.x(), offset.y(), paint);
    540         }
    541 
    542         // Maps ID -> T.
    543         template <typename T, Type kType>
    544         class IDMap {
    545         public:
    546             ~IDMap() {
    547                 // A well-behaved client always cleans up its definitions.
    548                 SkASSERT(fMap.count() == 0);
    549             }
    550 
    551             void set(const ID& id, const T& val) {
    552                 SkASSERT(id.type() == kType);
    553                 fMap.set(id, val);
    554             }
    555 
    556             void remove(const ID& id) {
    557                 SkASSERT(id.type() == kType);
    558                 fMap.remove(id);
    559             }
    560 
    561             const T& find(const ID& id) const {
    562                 SkASSERT(id.type() == kType);
    563                 T* val = fMap.find(id);
    564                 SkASSERT(val != nullptr);
    565                 return *val;
    566             }
    567 
    568         private:
    569             SkTHashMap<ID, T> fMap;
    570         };
    571 
    572         // Maps ID -> T*, and keeps the T alive by reffing it.
    573         template <typename T, Type kType>
    574         class ReffedIDMap {
    575         public:
    576             ReffedIDMap() {}
    577             ~ReffedIDMap() {
    578                 // A well-behaved client always cleans up its definitions.
    579                 SkASSERT(fMap.count() == 0);
    580             }
    581 
    582             void set(const ID& id, T* val) {
    583                 SkASSERT(id.type() == kType);
    584                 fMap.set(id, SkSafeRef(val));
    585             }
    586 
    587             void remove(const ID& id) {
    588                 SkASSERT(id.type() == kType);
    589                 T** val = fMap.find(id);
    590                 SkASSERT(val);
    591                 SkSafeUnref(*val);
    592                 fMap.remove(id);
    593             }
    594 
    595             T* find(const ID& id) const {
    596                 SkASSERT(id.type() == kType);
    597                 T** val = fMap.find(id);
    598                 SkASSERT(val);
    599                 return *val;
    600             }
    601 
    602         private:
    603             SkTHashMap<ID, T*> fMap;
    604         };
    605 
    606 
    607               IDMap<SkMatrix        , Type::kMatrix     > fMatrix;
    608               IDMap<Misc            , Type::kMisc       > fMisc;
    609               IDMap<SkPath          , Type::kPath       > fPath;
    610               IDMap<Stroke          , Type::kStroke     > fStroke;
    611         ReffedIDMap<const SkTextBlob, Type::kTextBlob   > fTextBlob;
    612         ReffedIDMap<SkPathEffect    , Type::kPathEffect > fPathEffect;
    613         ReffedIDMap<SkShader        , Type::kShader     > fShader;
    614         ReffedIDMap<SkXfermode      , Type::kXfermode   > fXfermode;
    615         ReffedIDMap<SkMaskFilter    , Type::kMaskFilter > fMaskFilter;
    616         ReffedIDMap<SkColorFilter   , Type::kColorFilter> fColorFilter;
    617         ReffedIDMap<SkRasterizer    , Type::kRasterizer > fRasterizer;
    618         ReffedIDMap<SkDrawLooper    , Type::kDrawLooper > fDrawLooper;
    619         ReffedIDMap<SkImageFilter   , Type::kImageFilter> fImageFilter;
    620         ReffedIDMap<SkAnnotation    , Type::kAnnotation > fAnnotation;
    621 
    622         SkCanvas* fCanvas;
    623         uint64_t fNextID = 0;
    624     };
    625 
    626     Encoder* NewDecoder(SkCanvas* canvas) { return new Decoder(canvas); }
    627 
    628     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
    629 
    630     class CachingEncoder final : public Encoder {
    631     public:
    632         explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {}
    633 
    634     private:
    635         struct Undef {
    636             Encoder* fEncoder;
    637             template <typename T>
    638             void operator()(const T&, ID* id) const { fEncoder->undefine(*id); }
    639         };
    640 
    641         ~CachingEncoder() override {
    642             Undef undef{fWrapped};
    643             fMatrix     .foreach(undef);
    644             fMisc       .foreach(undef);
    645             fPath       .foreach(undef);
    646             fStroke     .foreach(undef);
    647             fTextBlob   .foreach(undef);
    648             fPathEffect .foreach(undef);
    649             fShader     .foreach(undef);
    650             fXfermode   .foreach(undef);
    651             fMaskFilter .foreach(undef);
    652             fColorFilter.foreach(undef);
    653             fRasterizer .foreach(undef);
    654             fDrawLooper .foreach(undef);
    655             fImageFilter.foreach(undef);
    656             fAnnotation .foreach(undef);
    657         }
    658 
    659         template <typename Map, typename T>
    660         ID define(Map* map, const T& v) {
    661             if (const ID* id = map->find(v)) {
    662                 return *id;
    663             }
    664             ID id = fWrapped->define(v);
    665             map->set(v, id);
    666             return id;
    667         }
    668 
    669         ID define(const SkMatrix&   v) override { return this->define(&fMatrix     , v); }
    670         ID define(const Misc&       v) override { return this->define(&fMisc       , v); }
    671         ID define(const SkPath&     v) override { return this->define(&fPath       , v); }
    672         ID define(const Stroke&     v) override { return this->define(&fStroke     , v); }
    673         ID define(const SkTextBlob* v) override { return this->define(&fTextBlob   , v); }
    674         ID define(SkPathEffect*     v) override { return this->define(&fPathEffect , v); }
    675         ID define(SkShader*         v) override { return this->define(&fShader     , v); }
    676         ID define(SkXfermode*       v) override { return this->define(&fXfermode   , v); }
    677         ID define(SkMaskFilter*     v) override { return this->define(&fMaskFilter , v); }
    678         ID define(SkColorFilter*    v) override { return this->define(&fColorFilter, v); }
    679         ID define(SkRasterizer*     v) override { return this->define(&fRasterizer , v); }
    680         ID define(SkDrawLooper*     v) override { return this->define(&fDrawLooper , v); }
    681         ID define(SkImageFilter*    v) override { return this->define(&fImageFilter, v); }
    682         ID define(SkAnnotation*     v) override { return this->define(&fAnnotation , v); }
    683 
    684         void undefine(ID) override {}
    685 
    686         void    save() override { fWrapped->   save(); }
    687         void restore() override { fWrapped->restore(); }
    688         void saveLayer(ID bounds, CommonIDs common, SkCanvas::SaveLayerFlags flags) override {
    689             fWrapped->saveLayer(bounds, common, flags);
    690         }
    691 
    692         void setMatrix(ID matrix) override { fWrapped->setMatrix(matrix); }
    693 
    694         void clipPath(ID path, SkRegion::Op op, bool aa) override {
    695             fWrapped->clipPath(path, op, aa);
    696         }
    697         void fillPath(ID path, CommonIDs common) override {
    698             fWrapped->fillPath(path, common);
    699         }
    700         void strokePath(ID path, CommonIDs common, ID stroke) override {
    701             fWrapped->strokePath(path, common, stroke);
    702         }
    703         void fillText(ID text, SkPoint offset, CommonIDs common) override {
    704             fWrapped->fillText(text, offset, common);
    705         }
    706         void strokeText(ID text, SkPoint offset, CommonIDs common, ID stroke) override {
    707             fWrapped->strokeText(text, offset, common, stroke);
    708         }
    709 
    710         // Maps const T* -> ID, and refs the key.
    711         template <typename T, Type kType>
    712         class RefKeyMap {
    713         public:
    714             RefKeyMap() {}
    715             ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { SkSafeUnref(key); }); }
    716 
    717             void set(const T* key, ID id) {
    718                 SkASSERT(id.type() == kType);
    719                 fMap.set(SkSafeRef(key), id);
    720             }
    721 
    722             void remove(const T* key) {
    723                 fMap.remove(key);
    724                 SkSafeUnref(key);
    725             }
    726 
    727             const ID* find(const T* key) const {
    728                 return fMap.find(key);
    729             }
    730 
    731             template <typename Fn>
    732             void foreach(const Fn& fn) {
    733                 fMap.foreach(fn);
    734             }
    735         private:
    736             SkTHashMap<const T*, ID> fMap;
    737         };
    738 
    739         SkTHashMap<SkMatrix, ID>                        fMatrix;
    740         SkTHashMap<Misc, ID, MiscHash>                  fMisc;
    741         SkTHashMap<SkPath, ID>                          fPath;
    742         SkTHashMap<Stroke, ID>                          fStroke;
    743         RefKeyMap<const SkTextBlob, Type::kTextBlob   > fTextBlob;
    744         RefKeyMap<SkPathEffect    , Type::kPathEffect > fPathEffect;
    745         RefKeyMap<SkShader        , Type::kShader     > fShader;
    746         RefKeyMap<SkXfermode      , Type::kXfermode   > fXfermode;
    747         RefKeyMap<SkMaskFilter    , Type::kMaskFilter > fMaskFilter;
    748         RefKeyMap<SkColorFilter   , Type::kColorFilter> fColorFilter;
    749         RefKeyMap<SkRasterizer    , Type::kRasterizer > fRasterizer;
    750         RefKeyMap<SkDrawLooper    , Type::kDrawLooper > fDrawLooper;
    751         RefKeyMap<SkImageFilter   , Type::kImageFilter> fImageFilter;
    752         RefKeyMap<SkAnnotation    , Type::kAnnotation > fAnnotation;
    753 
    754         Encoder* fWrapped;
    755     };
    756 
    757     Encoder* NewCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wrapped); }
    758 
    759 } // namespace SkRemote
    760