• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CreateFrom(const SkPaint & paint)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 
applyTo(SkPaint * paint) const37     void Misc::applyTo(SkPaint* paint) const {
38         paint->setColor        (fColor);
39         paint->setFilterQuality(fFilterQuality);
40         paint->setAntiAlias    (fAntiAlias);
41         paint->setDither       (fDither);
42     }
43 
operator ==(const Misc & a,const Misc & b)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 {
operator ()SkRemote::MiscHash54         uint32_t operator()(const Misc& misc) {
55             return SkChecksum::Murmur3(&misc, offsetof(Misc, fDither) + sizeof(Misc().fDither));
56         }
57     };
58 
CreateFrom(const SkPaint & paint)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 
applyTo(SkPaint * paint) const69     void Stroke::applyTo(SkPaint* paint) const {
70         paint->setStrokeWidth(fWidth);
71         paint->setStrokeMiter(fMiter);
72         paint->setStrokeCap  (fCap);
73         paint->setStrokeJoin (fJoin);
74     }
75 
operator ==(const Stroke & a,const Stroke & b)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:
Canvas(Encoder * encoder)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>
AutoID(Encoder * encoder,const T & val)99             explicit AutoID(Encoder* encoder, const T& val)
100                 : fEncoder(encoder)
101                 , fID(encoder->define(val)) {}
~AutoID()102             ~AutoID() { if (fEncoder) fEncoder->undefine(fID); }
103 
AutoID(AutoID && o)104             AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) {
105                 o.fEncoder = nullptr;
106             }
107             AutoID& operator=(AutoID&&) = delete;
108 
operator ID() const109             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:
AutoCommonIDs(Encoder * encoder,const SkPaint & paint)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             }
~AutoCommonIDs()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 
AutoCommonIDs(AutoCommonIDs && o)147             AutoCommonIDs(AutoCommonIDs&& o) : fEncoder(o.fEncoder), fIDs(o.fIDs) {
148                 o.fEncoder = nullptr;
149             }
150             AutoID& operator=(AutoID&&) = delete;
151 
operator Encoder::CommonIDs() const152             operator Encoder::CommonIDs () const { return fIDs; }
153 
154         private:
155             Encoder*           fEncoder;
156             Encoder::CommonIDs fIDs;
157         };
158 
159         template <typename T>
id(const T & val)160         AutoID id(const T& val) { return AutoID(fEncoder, val); }
161 
commonIDs(const SkPaint & paint)162         AutoCommonIDs commonIDs(const SkPaint& paint) { return AutoCommonIDs(fEncoder, paint); }
163 
willSave()164         void   willSave() override { fEncoder->   save(); }
didRestore()165         void didRestore() override { fEncoder->restore(); }
getSaveLayerStrategy(const SaveLayerRec & rec)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 
didConcat(const SkMatrix &)180         void    didConcat(const SkMatrix&) override { this->didSetMatrix(this->getTotalMatrix()); }
didSetMatrix(const SkMatrix & matrix)181         void didSetMatrix(const SkMatrix& matrix) override {
182             fEncoder->setMatrix(this->id(matrix));
183         }
184 
onDrawOval(const SkRect & oval,const SkPaint & paint)185         void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
186             SkPath path;
187             path.addOval(oval);
188             this->onDrawPath(path, paint);
189         }
190 
onDrawRect(const SkRect & rect,const SkPaint & paint)191         void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
192             SkPath path;
193             path.addRect(rect);
194             this->onDrawPath(path, paint);
195         }
196 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)197         void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
198             SkPath path;
199             path.addRRect(rrect);
200             this->onDrawPath(path, paint);
201         }
202 
onDrawDRRect(const SkRRect & outside,const SkRRect & inside,const SkPaint & paint)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 
onDrawPath(const SkPath & path,const SkPaint & paint)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 
onDrawPaint(const SkPaint & paint)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 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)229         void onDrawPoints(PointMode mode,
230                           size_t count,
231                           const SkPoint pts[],
232                           const SkPaint& paint) override {
233             // TODO
234         }
235 
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)236         void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
237             // TODO
238             this->INHERITED::onDrawDrawable(drawable, matrix);
239         }
240 
onDrawPicture(const SkPicture * pic,const SkMatrix * matrix,const SkPaint * paint)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 
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)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 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)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 
onDrawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkXfermode::Mode mode,const SkRect * cull,const SkPaint * paint)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 
onDrawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)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 
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)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 
onDrawImage(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)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 
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)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 
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)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 
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)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 
onDrawTextBlob(const SkTextBlob * text,SkScalar x,SkScalar y,const SkPaint & paint)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 
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)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 
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)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 
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)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.
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle edgeStyle)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 
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle edgeStyle)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 
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle edgeStyle)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 
onClipRegion(const SkRegion & region,SkRegion::Op op)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 
NewCanvas(Encoder * encoder)434     SkCanvas* NewCanvas(Encoder* encoder) { return new Canvas(encoder); }
435 
436     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
437 
438     class Decoder final : public Encoder {
439     public:
Decoder(SkCanvas * canvas)440         explicit Decoder(SkCanvas* canvas) : fCanvas(canvas) {}
441 
442     private:
443         template <typename Map, typename T>
define(Type type,Map * map,const T & val)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
define(const SkMatrix & v)451         ID define(const SkMatrix&   v)O{return this->define(Type::kMatrix,      &fMatrix,      v);}
define(const Misc & v)452         ID define(const Misc&       v)O{return this->define(Type::kMisc,        &fMisc,        v);}
define(const SkPath & v)453         ID define(const SkPath&     v)O{return this->define(Type::kPath,        &fPath,        v);}
define(const Stroke & v)454         ID define(const Stroke&     v)O{return this->define(Type::kStroke,      &fStroke,      v);}
define(const SkTextBlob * v)455         ID define(const SkTextBlob* v)O{return this->define(Type::kTextBlob,    &fTextBlob,    v);}
define(SkPathEffect * v)456         ID define(SkPathEffect*     v)O{return this->define(Type::kPathEffect,  &fPathEffect,  v);}
define(SkShader * v)457         ID define(SkShader*         v)O{return this->define(Type::kShader,      &fShader,      v);}
define(SkXfermode * v)458         ID define(SkXfermode*       v)O{return this->define(Type::kXfermode,    &fXfermode,    v);}
define(SkMaskFilter * v)459         ID define(SkMaskFilter*     v)O{return this->define(Type::kMaskFilter,  &fMaskFilter,  v);}
define(SkColorFilter * v)460         ID define(SkColorFilter*    v)O{return this->define(Type::kColorFilter, &fColorFilter, v);}
define(SkRasterizer * v)461         ID define(SkRasterizer*     v)O{return this->define(Type::kRasterizer,  &fRasterizer,  v);}
define(SkDrawLooper * v)462         ID define(SkDrawLooper*     v)O{return this->define(Type::kDrawLooper,  &fDrawLooper,  v);}
define(SkImageFilter * v)463         ID define(SkImageFilter*    v)O{return this->define(Type::kImageFilter, &fImageFilter, v);}
define(SkAnnotation * v)464         ID define(SkAnnotation*     v)O{return this->define(Type::kAnnotation,  &fAnnotation,  v);}
465     #undef O
466 
467 
undefine(ID id)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 
applyCommon(const CommonIDs & common,SkPaint * paint) const487         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 
save()500         void    save() override { fCanvas->save(); }
restore()501         void restore() override { fCanvas->restore(); }
saveLayer(ID bounds,CommonIDs common,SkCanvas::SaveLayerFlags flags)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 
setMatrix(ID matrix)511         void setMatrix(ID matrix) override { fCanvas->setMatrix(fMatrix.find(matrix)); }
512 
clipPath(ID path,SkRegion::Op op,bool aa)513         void clipPath(ID path, SkRegion::Op op, bool aa) override {
514             fCanvas->clipPath(fPath.find(path), op, aa);
515         }
fillPath(ID path,CommonIDs common)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         }
strokePath(ID path,CommonIDs common,ID stroke)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         }
fillText(ID text,SkPoint offset,CommonIDs common)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         }
strokeText(ID text,SkPoint offset,CommonIDs common,ID stroke)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:
~IDMap()546             ~IDMap() {
547                 // A well-behaved client always cleans up its definitions.
548                 SkASSERT(fMap.count() == 0);
549             }
550 
set(const ID & id,const T & val)551             void set(const ID& id, const T& val) {
552                 SkASSERT(id.type() == kType);
553                 fMap.set(id, val);
554             }
555 
remove(const ID & id)556             void remove(const ID& id) {
557                 SkASSERT(id.type() == kType);
558                 fMap.remove(id);
559             }
560 
find(const ID & id) const561             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:
ReffedIDMap()576             ReffedIDMap() {}
~ReffedIDMap()577             ~ReffedIDMap() {
578                 // A well-behaved client always cleans up its definitions.
579                 SkASSERT(fMap.count() == 0);
580             }
581 
set(const ID & id,T * val)582             void set(const ID& id, T* val) {
583                 SkASSERT(id.type() == kType);
584                 fMap.set(id, SkSafeRef(val));
585             }
586 
remove(const ID & id)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 
find(const ID & id) const595             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 
NewDecoder(SkCanvas * canvas)626     Encoder* NewDecoder(SkCanvas* canvas) { return new Decoder(canvas); }
627 
628     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
629 
630     class CachingEncoder final : public Encoder {
631     public:
CachingEncoder(Encoder * wrapped)632         explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {}
633 
634     private:
635         struct Undef {
636             Encoder* fEncoder;
637             template <typename T>
operator ()SkRemote::CachingEncoder::Undef638             void operator()(const T&, ID* id) const { fEncoder->undefine(*id); }
639         };
640 
~CachingEncoder()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>
define(Map * map,const T & v)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 
define(const SkMatrix & v)669         ID define(const SkMatrix&   v) override { return this->define(&fMatrix     , v); }
define(const Misc & v)670         ID define(const Misc&       v) override { return this->define(&fMisc       , v); }
define(const SkPath & v)671         ID define(const SkPath&     v) override { return this->define(&fPath       , v); }
define(const Stroke & v)672         ID define(const Stroke&     v) override { return this->define(&fStroke     , v); }
define(const SkTextBlob * v)673         ID define(const SkTextBlob* v) override { return this->define(&fTextBlob   , v); }
define(SkPathEffect * v)674         ID define(SkPathEffect*     v) override { return this->define(&fPathEffect , v); }
define(SkShader * v)675         ID define(SkShader*         v) override { return this->define(&fShader     , v); }
define(SkXfermode * v)676         ID define(SkXfermode*       v) override { return this->define(&fXfermode   , v); }
define(SkMaskFilter * v)677         ID define(SkMaskFilter*     v) override { return this->define(&fMaskFilter , v); }
define(SkColorFilter * v)678         ID define(SkColorFilter*    v) override { return this->define(&fColorFilter, v); }
define(SkRasterizer * v)679         ID define(SkRasterizer*     v) override { return this->define(&fRasterizer , v); }
define(SkDrawLooper * v)680         ID define(SkDrawLooper*     v) override { return this->define(&fDrawLooper , v); }
define(SkImageFilter * v)681         ID define(SkImageFilter*    v) override { return this->define(&fImageFilter, v); }
define(SkAnnotation * v)682         ID define(SkAnnotation*     v) override { return this->define(&fAnnotation , v); }
683 
undefine(ID)684         void undefine(ID) override {}
685 
save()686         void    save() override { fWrapped->   save(); }
restore()687         void restore() override { fWrapped->restore(); }
saveLayer(ID bounds,CommonIDs common,SkCanvas::SaveLayerFlags flags)688         void saveLayer(ID bounds, CommonIDs common, SkCanvas::SaveLayerFlags flags) override {
689             fWrapped->saveLayer(bounds, common, flags);
690         }
691 
setMatrix(ID matrix)692         void setMatrix(ID matrix) override { fWrapped->setMatrix(matrix); }
693 
clipPath(ID path,SkRegion::Op op,bool aa)694         void clipPath(ID path, SkRegion::Op op, bool aa) override {
695             fWrapped->clipPath(path, op, aa);
696         }
fillPath(ID path,CommonIDs common)697         void fillPath(ID path, CommonIDs common) override {
698             fWrapped->fillPath(path, common);
699         }
strokePath(ID path,CommonIDs common,ID stroke)700         void strokePath(ID path, CommonIDs common, ID stroke) override {
701             fWrapped->strokePath(path, common, stroke);
702         }
fillText(ID text,SkPoint offset,CommonIDs common)703         void fillText(ID text, SkPoint offset, CommonIDs common) override {
704             fWrapped->fillText(text, offset, common);
705         }
strokeText(ID text,SkPoint offset,CommonIDs common,ID stroke)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:
RefKeyMap()714             RefKeyMap() {}
~RefKeyMap()715             ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { SkSafeUnref(key); }); }
716 
set(const T * key,ID id)717             void set(const T* key, ID id) {
718                 SkASSERT(id.type() == kType);
719                 fMap.set(SkSafeRef(key), id);
720             }
721 
remove(const T * key)722             void remove(const T* key) {
723                 fMap.remove(key);
724                 SkSafeUnref(key);
725             }
726 
find(const T * key) const727             const ID* find(const T* key) const {
728                 return fMap.find(key);
729             }
730 
731             template <typename Fn>
foreach(const Fn & 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 
NewCachingEncoder(Encoder * wrapped)757     Encoder* NewCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wrapped); }
758 
759 } // namespace SkRemote
760