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