1/* 2 * Copyright 2016 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 "SkAutoMalloc.h" 9#include "SkCanvasPriv.h" 10#include "SkColorFilter.h" 11#include "SkDrawLooper.h" 12#include "SkDrawShadowInfo.h" 13#include "SkImageFilter.h" 14#include "SkMaskFilter.h" 15#include "SkPathEffect.h" 16#include "SkPipeCanvas.h" 17#include "SkPipeFormat.h" 18#include "SkRSXform.h" 19#include "SkShader.h" 20#include "SkStream.h" 21#include "SkTextBlob.h" 22#include "SkTypeface.h" 23 24template <typename T> void write_rrect(T* writer, const SkRRect& rrect) { 25 char tmp[SkRRect::kSizeInMemory]; 26 rrect.writeToMemory(tmp); 27 writer->write(tmp, SkRRect::kSizeInMemory); 28} 29 30template <typename T> void write_pad(T* writer, const void* buffer, size_t len) { 31 writer->write(buffer, len & ~3); 32 if (len & 3) { 33 const char* src = (const char*)buffer + (len & ~3); 34 len &= 3; 35 uint32_t tmp = 0; 36 memcpy(&tmp, src, len); 37 writer->write(&tmp, 4); 38 } 39} 40 41/////////////////////////////////////////////////////////////////////////////////////////////////// 42 43static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) { 44 // kRespectsStroke_PaintUsage is only valid if other bits are also set 45 SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage)); 46 47 const SkScalar kTextSize_Default = 12; 48 const SkScalar kTextScaleX_Default = 1; 49 const SkScalar kTextSkewX_Default = 0; 50 const SkScalar kStrokeWidth_Default = 0; 51 const SkScalar kStrokeMiter_Default = 4; 52 const SkColor kColor_Default = SK_ColorBLACK; 53 54 unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0; 55 56 if (usage & kText_PaintUsage) { 57 bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonDef : 0); 58 bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextScaleX_NonDef : 0); 59 bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSkewX_NonDef : 0); 60 bits |= (paint.getTypeface() ? kTypeface_NonDef : 0); 61 } 62 63 // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8 64 65 if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage | 66 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) { 67 bits |= (paint.getShader() ? kShader_NonDef : 0); 68 } 69 70 if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) { 71 bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0); 72 73 if (paint.getStyle() != SkPaint::kFill_Style || (usage & kRespectsStroke_PaintUsage)) { 74 bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWidth_NonDef : 0); 75 bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMiter_NonDef : 0); 76 } 77 } 78 79 if (usage & 80 (kText_PaintUsage | kGeometry_PaintUsage | kImage_PaintUsage | kTextBlob_PaintUsage)) 81 { 82 bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0); 83 } 84 85 bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0); 86 bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0); 87 bits |= (paint.getDrawLooper() ? kDrawLooper_NonDef : 0); 88 89 return SkToU16(bits); 90} 91 92static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align, 93 unsigned filter, unsigned style, unsigned caps, unsigned joins, 94 unsigned encoding) { 95 SkASSERT(kFlags_BPF + kHint_BPF + kAlign_BPF + kFilter_BPF <= 32); 96 97 ASSERT_FITS_IN(flags, kFlags_BPF); 98 ASSERT_FITS_IN(filter, kFilter_BPF); 99 ASSERT_FITS_IN(style, kStyle_BPF); 100 ASSERT_FITS_IN(caps, kCaps_BPF); 101 ASSERT_FITS_IN(joins, kJoins_BPF); 102 ASSERT_FITS_IN(hint, kHint_BPF); 103 ASSERT_FITS_IN(align, kAlign_BPF); 104 ASSERT_FITS_IN(encoding, kEncoding_BPF); 105 106 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly 107 // add more bits in the future. 108 109 uint32_t packed = 0; 110 int shift = 32; 111 112 shift -= kFlags_BPF; packed |= (flags << shift); 113 shift -= kFilter_BPF; packed |= (filter << shift); 114 shift -= kStyle_BPF; packed |= (style << shift); 115 // these are only needed for stroking (geometry or text) 116 shift -= kCaps_BPF; packed |= (caps << shift); 117 shift -= kJoins_BPF; packed |= (joins << shift); 118 // these are only needed for text 119 shift -= kHint_BPF; packed |= (hint << shift); 120 shift -= kAlign_BPF; packed |= (align << shift); 121 shift -= kEncoding_BPF; packed |= (encoding << shift); 122 123 return packed; 124} 125 126#define CHECK_WRITE_SCALAR(writer, nondef, paint, Field) \ 127 do { if (nondef & (k##Field##_NonDef)) { \ 128 writer.writeScalar(paint.get##Field()); \ 129 }} while (0) 130 131#define CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Field) \ 132 do { if (nondef & (k##Field##_NonDef)) { \ 133 SkFlattenable* f = paint.get##Field(); \ 134 SkASSERT(f != nullptr); \ 135 writer.writeFlattenable(f); \ 136 } } while (0) 137 138/* 139 * Header: 140 * paint flags : 32 141 * non_def bits : 16 142 * xfermode enum : 8 143 * pad zeros : 8 144 */ 145static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned usage) { 146 uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting(), 147 paint.getTextAlign(), paint.getFilterQuality(), 148 paint.getStyle(), paint.getStrokeCap(), 149 paint.getStrokeJoin(), paint.getTextEncoding()); 150 writer.write32(packedFlags); 151 152 unsigned nondef = compute_nondef(paint, (PaintUsage)usage); 153 const uint8_t pad = 0; 154 writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad); 155 156 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize); 157 CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX); 158 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSkewX); 159 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeWidth); 160 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeMiter); 161 162 if (nondef & kColor_NonDef) { 163 writer.write32(paint.getColor()); 164 } 165 if (nondef & kTypeface_NonDef) { 166 // TODO: explore idea of writing bits indicating "use the prev (or prev N) face" 167 // e.g. 1-N bits is an index into a ring buffer of typefaces 168 SkTypeface* tf = paint.getTypeface(); 169 SkASSERT(tf); 170 writer.writeTypeface(tf); 171 } 172 173 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect); 174 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader); 175 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter); 176 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter); 177 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter); 178 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper); 179} 180 181class SkPipeWriter : public SkBinaryWriteBuffer { 182 enum { 183 N = 1024/4, 184 }; 185 uint32_t fStorage[N]; 186 SkWStream* fStream; 187 188public: 189 SkPipeWriter(SkWStream* stream, SkDeduper* deduper) 190 : SkBinaryWriteBuffer(fStorage, sizeof(fStorage)) 191 , fStream(stream) 192 { 193 this->setDeduper(deduper); 194 } 195 196 SkPipeWriter(SkPipeCanvas* pc) : SkPipeWriter(pc->fStream, pc->fDeduper) {} 197 198 ~SkPipeWriter() override { 199 SkASSERT(SkIsAlign4(fStream->bytesWritten())); 200 this->writeToStream(fStream); 201 } 202 203 void writePaint(const SkPaint& paint) override { 204 write_paint(*this, paint, kUnknown_PaintUsage); 205 } 206}; 207 208/////////////////////////////////////////////////////////////////////////////////////////////////// 209 210SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream* stream) 211 : INHERITED(cull.roundOut()) 212 , fDeduper(deduper) 213 , fStream(stream) 214{} 215 216SkPipeCanvas::~SkPipeCanvas() {} 217 218void SkPipeCanvas::willSave() { 219 fStream->write32(pack_verb(SkPipeVerb::kSave)); 220 this->INHERITED::willSave(); 221} 222 223SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { 224 SkPipeWriter writer(this); 225 uint32_t extra = rec.fSaveLayerFlags; 226 227 // remap this wacky flag 228 if (extra & (1 << 31)/*SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag*/) { 229 extra &= ~(1 << 31); 230 extra |= kDontClipToLayer_SaveLayerMask; 231 } 232 233 if (rec.fBounds) { 234 extra |= kHasBounds_SaveLayerMask; 235 } 236 if (rec.fPaint) { 237 extra |= kHasPaint_SaveLayerMask; 238 } 239 if (rec.fBackdrop) { 240 extra |= kHasBackdrop_SaveLayerMask; 241 } 242 if (rec.fClipMask) { 243 extra |= kHasClipMask_SaveLayerMask; 244 } 245 if (rec.fClipMatrix) { 246 extra |= kHasClipMatrix_SaveLayerMask; 247 } 248 249 writer.write32(pack_verb(SkPipeVerb::kSaveLayer, extra)); 250 if (rec.fBounds) { 251 writer.writeRect(*rec.fBounds); 252 } 253 if (rec.fPaint) { 254 write_paint(writer, *rec.fPaint, kSaveLayer_PaintUsage); 255 } 256 if (rec.fBackdrop) { 257 writer.writeFlattenable(rec.fBackdrop); 258 } 259 if (rec.fClipMask) { 260 writer.writeImage(rec.fClipMask); 261 } 262 if (rec.fClipMatrix) { 263 writer.writeMatrix(*rec.fClipMatrix); 264 } 265 266 return kNoLayer_SaveLayerStrategy; 267} 268 269void SkPipeCanvas::willRestore() { 270 fStream->write32(pack_verb(SkPipeVerb::kRestore)); 271 this->INHERITED::willRestore(); 272} 273 274template <typename T> void write_sparse_matrix(T* writer, const SkMatrix& matrix) { 275 SkMatrix::TypeMask tm = matrix.getType(); 276 SkScalar tmp[9]; 277 if (tm & SkMatrix::kPerspective_Mask) { 278 matrix.get9(tmp); 279 writer->write(tmp, 9 * sizeof(SkScalar)); 280 } else if (tm & SkMatrix::kAffine_Mask) { 281 tmp[0] = matrix[SkMatrix::kMScaleX]; 282 tmp[1] = matrix[SkMatrix::kMSkewX]; 283 tmp[2] = matrix[SkMatrix::kMTransX]; 284 tmp[3] = matrix[SkMatrix::kMScaleY]; 285 tmp[4] = matrix[SkMatrix::kMSkewY]; 286 tmp[5] = matrix[SkMatrix::kMTransY]; 287 writer->write(tmp, 6 * sizeof(SkScalar)); 288 } else if (tm & SkMatrix::kScale_Mask) { 289 tmp[0] = matrix[SkMatrix::kMScaleX]; 290 tmp[1] = matrix[SkMatrix::kMTransX]; 291 tmp[2] = matrix[SkMatrix::kMScaleY]; 292 tmp[3] = matrix[SkMatrix::kMTransY]; 293 writer->write(tmp, 4 * sizeof(SkScalar)); 294 } else if (tm & SkMatrix::kTranslate_Mask) { 295 tmp[0] = matrix[SkMatrix::kMTransX]; 296 tmp[1] = matrix[SkMatrix::kMTransY]; 297 writer->write(tmp, 2 * sizeof(SkScalar)); 298 } 299 // else write nothing for Identity 300} 301 302static void do_concat(SkWStream* stream, const SkMatrix& matrix, bool isSetMatrix) { 303 unsigned mtype = matrix.getType(); 304 SkASSERT(0 == (mtype & ~kTypeMask_ConcatMask)); 305 unsigned extra = mtype; 306 if (isSetMatrix) { 307 extra |= kSetMatrix_ConcatMask; 308 } 309 if (mtype || isSetMatrix) { 310 stream->write32(pack_verb(SkPipeVerb::kConcat, extra)); 311 write_sparse_matrix(stream, matrix); 312 } 313} 314 315void SkPipeCanvas::didConcat(const SkMatrix& matrix) { 316 do_concat(fStream, matrix, false); 317 this->INHERITED::didConcat(matrix); 318} 319 320void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) { 321 do_concat(fStream, matrix, true); 322 this->INHERITED::didSetMatrix(matrix); 323} 324 325void SkPipeCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) { 326 fStream->write32(pack_verb(SkPipeVerb::kClipRect, ((unsigned)op << 1) | edgeStyle)); 327 fStream->write(&rect, 4 * sizeof(SkScalar)); 328 329 this->INHERITED::onClipRect(rect, op, edgeStyle); 330} 331 332void SkPipeCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) { 333 fStream->write32(pack_verb(SkPipeVerb::kClipRRect, ((unsigned)op << 1) | edgeStyle)); 334 write_rrect(fStream, rrect); 335 336 this->INHERITED::onClipRRect(rrect, op, edgeStyle); 337} 338 339void SkPipeCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) { 340 SkPipeWriter writer(this); 341 writer.write32(pack_verb(SkPipeVerb::kClipPath, ((unsigned)op << 1) | edgeStyle)); 342 writer.writePath(path); 343 344 this->INHERITED::onClipPath(path, op, edgeStyle); 345} 346 347void SkPipeCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) { 348 SkPipeWriter writer(this); 349 writer.write32(pack_verb(SkPipeVerb::kClipRegion, (unsigned)op << 1)); 350 writer.writeRegion(deviceRgn); 351 352 this->INHERITED::onClipRegion(deviceRgn, op); 353} 354 355/////////////////////////////////////////////////////////////////////////////////////////////////// 356 357void SkPipeCanvas::onDrawArc(const SkRect& bounds, SkScalar startAngle, SkScalar sweepAngle, 358 bool useCenter, const SkPaint& paint) { 359 SkPipeWriter writer(this); 360 writer.write32(pack_verb(SkPipeVerb::kDrawArc, (int)useCenter)); 361 writer.writeRect(bounds); 362 writer.writeScalar(startAngle); 363 writer.writeScalar(sweepAngle); 364 write_paint(writer, paint, kGeometry_PaintUsage); 365} 366 367void SkPipeCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], const SkRect rect[], 368 const SkColor colors[], int count, SkBlendMode mode, 369 const SkRect* cull, const SkPaint* paint) { 370 unsigned extra = (unsigned)mode; 371 SkASSERT(0 == (extra & ~kMode_DrawAtlasMask)); 372 if (colors) { 373 extra |= kHasColors_DrawAtlasMask; 374 } 375 if (cull) { 376 extra |= kHasCull_DrawAtlasMask; 377 } 378 if (paint) { 379 extra |= kHasPaint_DrawAtlasMask; 380 } 381 382 SkPipeWriter writer(this); 383 writer.write32(pack_verb(SkPipeVerb::kDrawAtlas, extra)); 384 writer.writeImage(image); 385 writer.write32(count); 386 writer.write(xform, count * sizeof(SkRSXform)); 387 writer.write(rect, count * sizeof(SkRect)); 388 if (colors) { 389 writer.write(colors, count * sizeof(SkColor)); 390 } 391 if (cull) { 392 writer.writeRect(*cull); 393 } 394 if (paint) { 395 write_paint(writer, *paint, kImage_PaintUsage); 396 } 397} 398 399void SkPipeCanvas::onDrawPaint(const SkPaint& paint) { 400 SkPipeWriter writer(this); 401 writer.write32(pack_verb(SkPipeVerb::kDrawPaint)); 402 write_paint(writer, paint, kDrawPaint_PaintUsage); 403} 404 405void SkPipeCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 406 const SkPaint& paint) { 407 SkPipeWriter writer(this); 408 writer.write32(pack_verb(SkPipeVerb::kDrawPoints, mode)); 409 writer.write32(SkToU32(count)); 410 writer.write(pts, count * sizeof(SkPoint)); 411 write_paint(writer, paint, kGeometry_PaintUsage | kRespectsStroke_PaintUsage); 412} 413 414void SkPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { 415 SkPipeWriter writer(this); 416 writer.write32(pack_verb(SkPipeVerb::kDrawRect)); 417 writer.write(&rect, sizeof(SkRect)); 418 write_paint(writer, paint, kGeometry_PaintUsage); 419} 420 421void SkPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { 422 SkPipeWriter writer(this); 423 writer.write32(pack_verb(SkPipeVerb::kDrawOval)); 424 writer.write(&rect, sizeof(SkRect)); 425 write_paint(writer, paint, kGeometry_PaintUsage); 426} 427 428void SkPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 429 SkPipeWriter writer(this); 430 writer.write32(pack_verb(SkPipeVerb::kDrawRRect)); 431 write_rrect(&writer, rrect); 432 write_paint(writer, paint, kGeometry_PaintUsage); 433} 434 435void SkPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 436 SkPipeWriter writer(this); 437 writer.write32(pack_verb(SkPipeVerb::kDrawDRRect)); 438 write_rrect(&writer, outer); 439 write_rrect(&writer, inner); 440 write_paint(writer, paint, kGeometry_PaintUsage); 441} 442 443void SkPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 444 SkPipeWriter writer(this); 445 writer.write32(pack_verb(SkPipeVerb::kDrawPath)); 446 writer.writePath(path); 447 write_paint(writer, paint, kGeometry_PaintUsage); 448} 449 450void SkPipeCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { 451 SkPipeWriter writer(this); 452 writer.write32(pack_verb(SkPipeVerb::kDrawShadowRec)); 453 writer.writePath(path); 454 writer.write(&rec, sizeof(rec)); 455} 456 457/////////////////////////////////////////////////////////////////////////////////////////////////// 458 459static sk_sp<SkImage> make_from_bitmap(const SkBitmap& bitmap) { 460 // If we just "make" an image, it will force a CPU copy (if its mutable), only to have 461 // us then either find it in our cache, or compress and send it. 462 // 463 // Better could be to look it up in our cache first, and only create/compress it if we have to. 464 // 465 // But for now, just do the dumb thing... 466 return SkImage::MakeFromBitmap(bitmap); 467} 468 469void SkPipeCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 470 const SkPaint* paint) { 471 sk_sp<SkImage> image = make_from_bitmap(bitmap); 472 if (image) { 473 this->onDrawImage(image.get(), x, y, paint); 474 } 475} 476 477void SkPipeCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 478 const SkPaint* paint, SrcRectConstraint constraint) { 479 sk_sp<SkImage> image = make_from_bitmap(bitmap); 480 if (image) { 481 this->onDrawImageRect(image.get(), src, dst, paint, constraint); 482 } 483} 484 485void SkPipeCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 486 const SkRect& dst, const SkPaint* paint) { 487 sk_sp<SkImage> image = make_from_bitmap(bitmap); 488 if (image) { 489 this->onDrawImageNine(image.get(), center, dst, paint); 490 } 491} 492 493void SkPipeCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, 494 const SkRect& dst, const SkPaint* paint) { 495 sk_sp<SkImage> image = make_from_bitmap(bitmap); 496 if (image) { 497 this->onDrawImageLattice(image.get(), lattice, dst, paint); 498 } 499} 500 501/////////////////////////////////////////////////////////////////////////////////////////////////// 502 503void SkPipeCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top, 504 const SkPaint* paint) { 505 unsigned extra = 0; 506 if (paint) { 507 extra |= kHasPaint_DrawImageMask; 508 } 509 SkPipeWriter writer(this); 510 writer.write32(pack_verb(SkPipeVerb::kDrawImage, extra)); 511 writer.writeImage(image); 512 writer.writeScalar(left); 513 writer.writeScalar(top); 514 if (paint) { 515 write_paint(writer, *paint, kImage_PaintUsage); 516 } 517} 518 519void SkPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 520 const SkPaint* paint, SrcRectConstraint constraint) { 521 SkASSERT(0 == ((unsigned)constraint & ~1)); 522 unsigned extra = (unsigned)constraint; 523 if (paint) { 524 extra |= kHasPaint_DrawImageRectMask; 525 } 526 if (src) { 527 extra |= kHasSrcRect_DrawImageRectMask; 528 } 529 530 SkPipeWriter writer(this); 531 writer.write32(pack_verb(SkPipeVerb::kDrawImageRect, extra)); 532 writer.writeImage(image); 533 if (src) { 534 writer.write(src, sizeof(*src)); 535 } 536 writer.write(&dst, sizeof(dst)); 537 if (paint) { 538 write_paint(writer, *paint, kImage_PaintUsage); 539 } 540} 541 542void SkPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 543 const SkPaint* paint) { 544 unsigned extra = 0; 545 if (paint) { 546 extra |= kHasPaint_DrawImageNineMask; 547 } 548 SkPipeWriter writer(this); 549 writer.write32(pack_verb(SkPipeVerb::kDrawImageNine, extra)); 550 writer.writeImage(image); 551 writer.write(¢er, sizeof(center)); 552 writer.write(&dst, sizeof(dst)); 553 if (paint) { 554 write_paint(writer, *paint, kImage_PaintUsage); 555 } 556} 557 558void SkPipeCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, 559 const SkRect& dst, const SkPaint* paint) { 560 unsigned extra = 0; 561 if (paint) { 562 extra |= kHasPaint_DrawImageLatticeMask; 563 } 564 SkPipeWriter writer(this); 565 writer.write32(pack_verb(SkPipeVerb::kDrawImageLattice, extra)); 566 writer.writeImage(image); 567 SkCanvasPriv::WriteLattice(writer, lattice); 568 writer.write(&dst, sizeof(dst)); 569 if (paint) { 570 write_paint(writer, *paint, kImage_PaintUsage); 571 } 572} 573 574/////////////////////////////////////////////////////////////////////////////////////////////////// 575 576void SkPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 577 const SkPaint& paint) { 578 SkASSERT(byteLength); 579 580 bool compact = fits_in(byteLength, 24); 581 582 SkPipeWriter writer(this); 583 writer.write32(pack_verb(SkPipeVerb::kDrawText, compact ? (unsigned)byteLength : 0)); 584 if (!compact) { 585 writer.write32(SkToU32(byteLength)); 586 } 587 write_pad(&writer, text, byteLength); 588 writer.writeScalar(x); 589 writer.writeScalar(y); 590 write_paint(writer, paint, kText_PaintUsage); 591} 592 593void SkPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 594 const SkPaint& paint) { 595 SkASSERT(byteLength); 596 597 bool compact = fits_in(byteLength, 24); 598 599 SkPipeWriter writer(this); 600 writer.write32(pack_verb(SkPipeVerb::kDrawPosText, compact ? (unsigned)byteLength : 0)); 601 if (!compact) { 602 writer.write32(SkToU32(byteLength)); 603 } 604 write_pad(&writer, text, byteLength); 605 writer.writePointArray(pos, paint.countText(text, byteLength)); 606 write_paint(writer, paint, kText_PaintUsage); 607} 608 609void SkPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 610 SkScalar constY, const SkPaint& paint) { 611 SkASSERT(byteLength); 612 613 bool compact = fits_in(byteLength, 24); 614 615 SkPipeWriter writer(this); 616 writer.write32(pack_verb(SkPipeVerb::kDrawPosTextH, compact ? (unsigned)byteLength : 0)); 617 if (!compact) { 618 writer.write32(SkToU32(byteLength)); 619 } 620 write_pad(&writer, text, byteLength); 621 writer.writeScalarArray(xpos, paint.countText(text, byteLength)); 622 writer.writeScalar(constY); 623 write_paint(writer, paint, kText_PaintUsage); 624} 625 626void SkPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 627 const SkMatrix* matrix, const SkPaint& paint) { 628 SkASSERT(byteLength > 0); 629 630 unsigned extra = 0; 631 if (byteLength <= kTextLength_DrawTextOnPathMask) { 632 extra |= byteLength; 633 } // else we will write the length after the packedverb 634 SkMatrix::TypeMask tm = matrix ? matrix->getType() : SkMatrix::kIdentity_Mask; 635 extra |= (unsigned)tm << kMatrixType_DrawTextOnPathShift; 636 637 SkPipeWriter writer(this); 638 writer.write32(pack_verb(SkPipeVerb::kDrawTextOnPath, extra)); 639 if (byteLength > kTextLength_DrawTextOnPathMask) { 640 writer.write32(byteLength); 641 } 642 write_pad(&writer, text, byteLength); 643 writer.writePath(path); 644 if (matrix) { 645 write_sparse_matrix(&writer, *matrix); 646 } 647 write_paint(writer, paint, kText_PaintUsage); 648} 649 650void SkPipeCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 651 const SkRect* cull, const SkPaint& paint) { 652 SkASSERT(byteLength); 653 654 bool compact = fits_in(byteLength, 23); 655 unsigned extra = compact ? (byteLength << 1) : 0; 656 if (cull) { 657 extra |= 1; 658 } 659 660 SkPipeWriter writer(this); 661 writer.write32(pack_verb(SkPipeVerb::kDrawTextRSXform, extra)); 662 if (!compact) { 663 writer.write32(SkToU32(byteLength)); 664 } 665 write_pad(&writer, text, byteLength); 666 667 int count = paint.countText(text, byteLength); 668 writer.write32(count); // maybe we can/should store this in extra as well? 669 writer.write(xform, count * sizeof(SkRSXform)); 670 if (cull) { 671 writer.writeRect(*cull); 672 } 673 write_paint(writer, paint, kText_PaintUsage); 674} 675 676void SkPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 677 const SkPaint &paint) { 678 SkPipeWriter writer(this); 679 writer.write32(pack_verb(SkPipeVerb::kDrawTextBlob, 0)); 680 blob->flatten(writer); 681 writer.writeScalar(x); 682 writer.writeScalar(y); 683 write_paint(writer, paint, kTextBlob_PaintUsage); 684} 685 686void SkPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 687 const SkPaint* paint) { 688 unsigned extra = fDeduper->findOrDefinePicture(const_cast<SkPicture*>(picture)); 689 if (matrix) { 690 extra |= kHasMatrix_DrawPictureExtra; 691 } 692 if (paint) { 693 extra |= kHasPaint_DrawPictureExtra; 694 } 695 SkPipeWriter writer(this); 696 writer.write32(pack_verb(SkPipeVerb::kDrawPicture, extra)); 697 if (matrix) { 698 writer.writeMatrix(*matrix); 699 } 700 if (paint) { 701 write_paint(writer, *paint, kSaveLayer_PaintUsage); 702 } 703} 704 705void SkPipeCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { 706 size_t size = region.writeToMemory(nullptr); 707 unsigned extra = 0; 708 if (fits_in(size, 24)) { 709 extra = SkToUInt(size); 710 } 711 712 SkPipeWriter writer(this); 713 writer.write32(pack_verb(SkPipeVerb::kDrawRegion, extra)); 714 if (0 == extra) { 715 writer.write32(size); 716 } 717 SkAutoSMalloc<2048> storage(size); 718 region.writeToMemory(storage.get()); 719 write_pad(&writer, storage.get(), size); 720 write_paint(writer, paint, kGeometry_PaintUsage); 721} 722 723void SkPipeCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode, 724 const SkPaint& paint) { 725 unsigned extra = static_cast<unsigned>(bmode); 726 727 SkPipeWriter writer(this); 728 writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra)); 729 // TODO: dedup vertices? 730 writer.writeDataAsByteArray(vertices->encode().get()); 731 write_paint(writer, paint, kVertices_PaintUsage); 732} 733 734void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 735 const SkPoint texCoords[4], SkBlendMode bmode, 736 const SkPaint& paint) { 737 SkPipeWriter writer(this); 738 unsigned extra = 0; 739 SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask)); 740 extra = (unsigned)bmode; 741 if (colors) { 742 extra |= kHasColors_DrawPatchExtraMask; 743 } 744 if (texCoords) { 745 extra |= kHasTexture_DrawPatchExtraMask; 746 } 747 writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra)); 748 writer.write(cubics, sizeof(SkPoint) * 12); 749 if (colors) { 750 writer.write(colors, sizeof(SkColor) * 4); 751 } 752 if (texCoords) { 753 writer.write(texCoords, sizeof(SkPoint) * 4); 754 } 755 write_paint(writer, paint, kGeometry_PaintUsage); 756} 757 758void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) { 759 const size_t len = strlen(key) + 1; // must write the trailing 0 760 bool compact = fits_in(len, 23); 761 uint32_t extra = compact ? (unsigned)len : 0; 762 extra <<= 1; // make room for has_data_sentinel 763 if (data) { 764 extra |= 1; 765 } 766 767 fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra)); 768 fStream->write(&rect, sizeof(SkRect)); 769 if (!compact) { 770 fStream->write32(SkToU32(len)); 771 } 772 write_pad(fStream, key, len); 773 if (data) { 774 fStream->write32(SkToU32(data->size())); 775 write_pad(fStream, data->data(), data->size()); 776 } 777} 778 779/////////////////////////////////////////////////////////////////////////////////////////////////// 780 781static sk_sp<SkData> encode(SkImage* img, SkSerialImageProc proc, void* ctx) { 782 if (proc) { 783 if (auto data = proc(img, ctx)) { 784 return data; 785 } 786 } 787 return img->encodeToData(); 788} 789 790static bool show_deduper_traffic = false; 791 792int SkPipeDeduper::findOrDefineImage(SkImage* image) { 793 int index = fImages.find(image->uniqueID()); 794 SkASSERT(index >= 0); 795 if (index) { 796 if (show_deduper_traffic) { 797 SkDebugf(" reuseImage(%d)\n", index - 1); 798 } 799 return index; 800 } 801 802 sk_sp<SkData> data = encode(image, fProcs.fImageProc, fProcs.fImageCtx); 803 if (data) { 804 index = fImages.add(image->uniqueID()); 805 SkASSERT(index > 0); 806 SkASSERT(fits_in(index, 24)); 807 fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index)); 808 809 uint32_t len = SkToU32(data->size()); 810 fStream->write32(SkAlign4(len)); 811 write_pad(fStream, data->data(), len); 812 813 if (show_deduper_traffic) { 814 int size = image->width() * image->height() << 2; 815 SkDebugf(" defineImage(%d) %d -> %d\n", index - 1, size, len); 816 } 817 return index; 818 } 819 SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->height()); 820 return 0; // failed to encode 821} 822 823int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) { 824 int index = fPictures.find(picture->uniqueID()); 825 SkASSERT(index >= 0); 826 if (index) { 827 if (show_deduper_traffic) { 828 SkDebugf(" reusePicture(%d)\n", index - 1); 829 } 830 return index; 831 } 832 833 size_t prevWritten = fStream->bytesWritten(); 834 unsigned extra = 0; // 0 means we're defining a new picture, non-zero means undef_index + 1 835 fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, extra)); 836 const SkRect cull = picture->cullRect(); 837 fStream->write(&cull, sizeof(cull)); 838 picture->playback(fPipeCanvas); 839 // call fPictures.add *after* we're written the picture, so that any nested pictures will have 840 // already been defined, and we get the "last" index value. 841 index = fPictures.add(picture->uniqueID()); 842 ASSERT_FITS_IN(index, kObjectDefinitionBits); 843 fStream->write32(pack_verb(SkPipeVerb::kEndPicture, index)); 844 845 if (show_deduper_traffic) { 846 SkDebugf(" definePicture(%d) %d\n", 847 index - 1, SkToU32(fStream->bytesWritten() - prevWritten)); 848 } 849 return index; 850} 851 852static sk_sp<SkData> encode(const SkSerialProcs& procs, SkTypeface* tf) { 853 if (procs.fTypefaceProc) { 854 auto data = procs.fTypefaceProc(tf, procs.fTypefaceCtx); 855 if (data) { 856 return data; 857 } 858 } 859 SkDynamicMemoryWStream stream; 860 tf->serialize(&stream); 861 return sk_sp<SkData>(stream.detachAsData()); 862} 863 864int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) { 865 if (!typeface) { 866 return 0; // default 867 } 868 869 int index = fTypefaces.find(typeface->uniqueID()); 870 SkASSERT(index >= 0); 871 if (index) { 872 if (show_deduper_traffic) { 873 SkDebugf(" reuseTypeface(%d)\n", index - 1); 874 } 875 return index; 876 } 877 878 sk_sp<SkData> data = encode(fProcs, typeface); 879 if (data) { 880 index = fTypefaces.add(typeface->uniqueID()); 881 SkASSERT(index > 0); 882 SkASSERT(fits_in(index, 24)); 883 fStream->write32(pack_verb(SkPipeVerb::kDefineTypeface, index)); 884 885 uint32_t len = SkToU32(data->size()); 886 fStream->write32(SkAlign4(len)); 887 write_pad(fStream, data->data(), len); 888 889 if (show_deduper_traffic) { 890 SkDebugf(" defineTypeface(%d) %d\n", index - 1, len); 891 } 892 return index; 893 } 894 SkDebugf("+++ failed to encode typeface %d\n", typeface->uniqueID()); 895 return 0; // failed to encode 896} 897 898int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) { 899 if (!flattenable) { 900 return 0; 901 } 902 903 int index = fFactories.find(flattenable->getFactory()); 904 SkASSERT(index >= 0); 905 if (index) { 906 if (show_deduper_traffic) { 907 SkDebugf(" reuseFactory(%d)\n", index - 1); 908 } 909 return index; 910 } 911 912 index = fFactories.add(flattenable->getFactory()); 913 ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits); 914 const char* name = flattenable->getTypeName(); 915 size_t len = strlen(name); 916 ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits); 917 unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len; 918 size_t prevWritten = fStream->bytesWritten(); 919 fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra)); 920 write_pad(fStream, name, len + 1); 921 if (false) { 922 SkDebugf(" defineFactory(%d) %d %s\n", 923 index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name); 924 } 925 return index; 926} 927 928/////////////////////////////////////////////////////////////////////////////////////////////////// 929#include "SkPipe.h" 930 931class SkPipeSerializer::Impl { 932public: 933 SkPipeDeduper fDeduper; 934 std::unique_ptr<SkPipeCanvas> fCanvas; 935}; 936 937SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {} 938 939SkPipeSerializer::~SkPipeSerializer() { 940 if (fImpl->fCanvas) { 941 this->endWrite(); 942 } 943} 944 945void SkPipeSerializer::resetCache() { 946 fImpl->fDeduper.resetCaches(); 947} 948 949sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) { 950 SkDynamicMemoryWStream stream; 951 this->writeImage(image, &stream); 952 return stream.detachAsData(); 953} 954 955sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) { 956 SkDynamicMemoryWStream stream; 957 this->writePicture(picture, &stream); 958 return stream.detachAsData(); 959} 960 961void SkPipeSerializer::writePicture(SkPicture* picture, SkWStream* stream) { 962 int index = fImpl->fDeduper.findPicture(picture); 963 if (0 == index) { 964 // Try to define the picture 965 this->beginWrite(picture->cullRect(), stream); 966 index = fImpl->fDeduper.findOrDefinePicture(picture); 967 this->endWrite(); 968 } 969 stream->write32(pack_verb(SkPipeVerb::kWritePicture, index)); 970} 971 972void SkPipeSerializer::writeImage(SkImage* image, SkWStream* stream) { 973 int index = fImpl->fDeduper.findImage(image); 974 if (0 == index) { 975 // Try to define the image 976 fImpl->fDeduper.setStream(stream); 977 index = fImpl->fDeduper.findOrDefineImage(image); 978 } 979 stream->write32(pack_verb(SkPipeVerb::kWriteImage, index)); 980} 981 982SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) { 983 SkASSERT(nullptr == fImpl->fCanvas); 984 fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream)); 985 fImpl->fDeduper.setStream(stream); 986 fImpl->fDeduper.setCanvas(fImpl->fCanvas.get()); 987 return fImpl->fCanvas.get(); 988} 989 990void SkPipeSerializer::endWrite() { 991 fImpl->fCanvas->restoreToCount(1); 992 fImpl->fCanvas.reset(nullptr); 993 fImpl->fDeduper.setCanvas(nullptr); 994} 995