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