SkPipeCanvas.cpp revision 95e3c058ef633782f7549e9e1c2727d60dbc8ee5
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 "SkColorFilter.h" 10#include "SkDrawLooper.h" 11#include "SkImageFilter.h" 12#include "SkMaskFilter.h" 13#include "SkPathEffect.h" 14#include "SkPipeCanvas.h" 15#include "SkPipeFormat.h" 16#include "SkRSXform.h" 17#include "SkRasterizer.h" 18#include "SkShader.h" 19#include "SkStream.h" 20#include "SkTextBlob.h" 21#include "SkTypeface.h" 22 23template <typename T> void write_rrect(T* writer, const SkRRect& rrect) { 24 char tmp[SkRRect::kSizeInMemory]; 25 rrect.writeToMemory(tmp); 26 writer->write(tmp, SkRRect::kSizeInMemory); 27} 28 29template <typename T> void write_pad(T* writer, const void* buffer, size_t len) { 30 writer->write(buffer, len & ~3); 31 if (len & 3) { 32 const char* src = (const char*)buffer + (len & ~3); 33 len &= 3; 34 uint32_t tmp = 0; 35 memcpy(&tmp, src, len); 36 writer->write(&tmp, 4); 37 } 38} 39 40/////////////////////////////////////////////////////////////////////////////////////////////////// 41 42static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) { 43 // kRespectsStroke_PaintUsage is only valid if other bits are also set 44 SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage)); 45 46 const SkScalar kTextSize_Default = 12; 47 const SkScalar kTextScaleX_Default = 1; 48 const SkScalar kTextSkewX_Default = 0; 49 const SkScalar kStrokeWidth_Default = 0; 50 const SkScalar kStrokeMiter_Default = 4; 51 const SkColor kColor_Default = SK_ColorBLACK; 52 53 unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0; 54 55 if (usage & kText_PaintUsage) { 56 bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonDef : 0); 57 bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextScaleX_NonDef : 0); 58 bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSkewX_NonDef : 0); 59 bits |= (paint.getTypeface() ? kTypeface_NonDef : 0); 60 } 61 62 // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8 63 64 if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage | 65 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) { 66 bits |= (paint.getShader() ? kShader_NonDef : 0); 67 } 68 69 if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) { 70 bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0); 71 bits |= (paint.getRasterizer() ? kRasterizer_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, Rasterizer); 178 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter); 179 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper); 180} 181 182class SkPipeWriter : public SkBinaryWriteBuffer { 183 enum { 184 N = 1024/4, 185 }; 186 uint32_t fStorage[N]; 187 SkWStream* fStream; 188 189public: 190 SkPipeWriter(SkWStream* stream, SkDeduper* deduper) 191 : SkBinaryWriteBuffer(fStorage, sizeof(fStorage)) 192 , fStream(stream) 193 { 194 this->setDeduper(deduper); 195 } 196 197 SkPipeWriter(SkPipeCanvas* pc) : SkPipeWriter(pc->fStream, pc->fDeduper) {} 198 199 ~SkPipeWriter() override { 200 SkASSERT(SkIsAlign4(fStream->bytesWritten())); 201 this->writeToStream(fStream); 202 } 203 204 void writePaint(const SkPaint& paint) override { 205 write_paint(*this, paint, kUnknown_PaintUsage); 206 } 207}; 208 209/////////////////////////////////////////////////////////////////////////////////////////////////// 210 211SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream* stream) 212 : INHERITED(cull.roundOut()) 213 , fDeduper(deduper) 214 , fStream(stream) 215{} 216 217SkPipeCanvas::~SkPipeCanvas() {} 218 219void SkPipeCanvas::willSave() { 220 fStream->write32(pack_verb(SkPipeVerb::kSave)); 221 this->INHERITED::willSave(); 222} 223 224SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { 225 SkPipeWriter writer(this); 226 uint32_t extra = rec.fSaveLayerFlags; 227 228 // remap this wacky flag 229 if (extra & (1 << 31)/*SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag*/) { 230 extra &= ~(1 << 31); 231 extra |= kDontClipToLayer_SaveLayerMask; 232 } 233 234 if (rec.fBounds) { 235 extra |= kHasBounds_SaveLayerMask; 236 } 237 if (rec.fPaint) { 238 extra |= kHasPaint_SaveLayerMask; 239 } 240 if (rec.fBackdrop) { 241 extra |= kHasBackdrop_SaveLayerMask; 242 } 243 244 writer.write32(pack_verb(SkPipeVerb::kSaveLayer, extra)); 245 if (rec.fBounds) { 246 writer.writeRect(*rec.fBounds); 247 } 248 if (rec.fPaint) { 249 write_paint(writer, *rec.fPaint, kSaveLayer_PaintUsage); 250 } 251 if (rec.fBackdrop) { 252 writer.writeFlattenable(rec.fBackdrop); 253 } 254 return kNoLayer_SaveLayerStrategy; 255} 256 257void SkPipeCanvas::willRestore() { 258 fStream->write32(pack_verb(SkPipeVerb::kRestore)); 259 this->INHERITED::willRestore(); 260} 261 262template <typename T> void write_sparse_matrix(T* writer, const SkMatrix& matrix) { 263 SkMatrix::TypeMask tm = matrix.getType(); 264 SkScalar tmp[9]; 265 if (tm & SkMatrix::kPerspective_Mask) { 266 matrix.get9(tmp); 267 writer->write(tmp, 9 * sizeof(SkScalar)); 268 } else if (tm & SkMatrix::kAffine_Mask) { 269 tmp[0] = matrix[SkMatrix::kMScaleX]; 270 tmp[1] = matrix[SkMatrix::kMSkewX]; 271 tmp[2] = matrix[SkMatrix::kMTransX]; 272 tmp[3] = matrix[SkMatrix::kMScaleY]; 273 tmp[4] = matrix[SkMatrix::kMSkewY]; 274 tmp[5] = matrix[SkMatrix::kMTransY]; 275 writer->write(tmp, 6 * sizeof(SkScalar)); 276 } else if (tm & SkMatrix::kScale_Mask) { 277 tmp[0] = matrix[SkMatrix::kMScaleX]; 278 tmp[1] = matrix[SkMatrix::kMTransX]; 279 tmp[2] = matrix[SkMatrix::kMScaleY]; 280 tmp[3] = matrix[SkMatrix::kMTransY]; 281 writer->write(tmp, 4 * sizeof(SkScalar)); 282 } else if (tm & SkMatrix::kTranslate_Mask) { 283 tmp[0] = matrix[SkMatrix::kMTransX]; 284 tmp[1] = matrix[SkMatrix::kMTransY]; 285 writer->write(tmp, 2 * sizeof(SkScalar)); 286 } 287 // else write nothing for Identity 288} 289 290static void do_concat(SkWStream* stream, const SkMatrix& matrix, bool isSetMatrix) { 291 unsigned mtype = matrix.getType(); 292 SkASSERT(0 == (mtype & ~kTypeMask_ConcatMask)); 293 unsigned extra = mtype; 294 if (isSetMatrix) { 295 extra |= kSetMatrix_ConcatMask; 296 } 297 if (mtype || isSetMatrix) { 298 stream->write32(pack_verb(SkPipeVerb::kConcat, extra)); 299 write_sparse_matrix(stream, matrix); 300 } 301} 302 303void SkPipeCanvas::didConcat(const SkMatrix& matrix) { 304 do_concat(fStream, matrix, false); 305 this->INHERITED::didConcat(matrix); 306} 307 308void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) { 309 do_concat(fStream, matrix, true); 310 this->INHERITED::didSetMatrix(matrix); 311} 312 313void SkPipeCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) { 314 fStream->write32(pack_verb(SkPipeVerb::kClipRect, ((unsigned)op << 1) | edgeStyle)); 315 fStream->write(&rect, 4 * sizeof(SkScalar)); 316 317 this->INHERITED::onClipRect(rect, op, edgeStyle); 318} 319 320void SkPipeCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) { 321 fStream->write32(pack_verb(SkPipeVerb::kClipRRect, ((unsigned)op << 1) | edgeStyle)); 322 write_rrect(fStream, rrect); 323 324 this->INHERITED::onClipRRect(rrect, op, edgeStyle); 325} 326 327void SkPipeCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) { 328 SkPipeWriter writer(this); 329 writer.write32(pack_verb(SkPipeVerb::kClipPath, ((unsigned)op << 1) | edgeStyle)); 330 writer.writePath(path); 331 332 this->INHERITED::onClipPath(path, op, edgeStyle); 333} 334 335void SkPipeCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) { 336 SkPipeWriter writer(this); 337 writer.write32(pack_verb(SkPipeVerb::kClipRegion, (unsigned)op << 1)); 338 writer.writeRegion(deviceRgn); 339 340 this->INHERITED::onClipRegion(deviceRgn, op); 341} 342 343/////////////////////////////////////////////////////////////////////////////////////////////////// 344 345void SkPipeCanvas::onDrawArc(const SkRect& bounds, SkScalar startAngle, SkScalar sweepAngle, 346 bool useCenter, const SkPaint& paint) { 347 SkPipeWriter writer(this); 348 writer.write32(pack_verb(SkPipeVerb::kDrawArc, (int)useCenter)); 349 writer.writeRect(bounds); 350 writer.writeScalar(startAngle); 351 writer.writeScalar(sweepAngle); 352 write_paint(writer, paint, kGeometry_PaintUsage); 353} 354 355void SkPipeCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], const SkRect rect[], 356 const SkColor colors[], int count, SkBlendMode mode, 357 const SkRect* cull, const SkPaint* paint) { 358 unsigned extra = (unsigned)mode; 359 SkASSERT(0 == (extra & ~kMode_DrawAtlasMask)); 360 if (colors) { 361 extra |= kHasColors_DrawAtlasMask; 362 } 363 if (cull) { 364 extra |= kHasCull_DrawAtlasMask; 365 } 366 if (paint) { 367 extra |= kHasPaint_DrawAtlasMask; 368 } 369 370 SkPipeWriter writer(this); 371 writer.write32(pack_verb(SkPipeVerb::kDrawAtlas, extra)); 372 writer.writeImage(image); 373 writer.write32(count); 374 writer.write(xform, count * sizeof(SkRSXform)); 375 writer.write(rect, count * sizeof(SkRect)); 376 if (colors) { 377 writer.write(colors, count * sizeof(SkColor)); 378 } 379 if (cull) { 380 writer.writeRect(*cull); 381 } 382 if (paint) { 383 write_paint(writer, *paint, kImage_PaintUsage); 384 } 385} 386 387void SkPipeCanvas::onDrawPaint(const SkPaint& paint) { 388 SkPipeWriter writer(this); 389 writer.write32(pack_verb(SkPipeVerb::kDrawPaint)); 390 write_paint(writer, paint, kDrawPaint_PaintUsage); 391} 392 393void SkPipeCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 394 const SkPaint& paint) { 395 SkPipeWriter writer(this); 396 writer.write32(pack_verb(SkPipeVerb::kDrawPoints, mode)); 397 writer.write32(SkToU32(count)); 398 writer.write(pts, count * sizeof(SkPoint)); 399 write_paint(writer, paint, kGeometry_PaintUsage | kRespectsStroke_PaintUsage); 400} 401 402void SkPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { 403 SkPipeWriter writer(this); 404 writer.write32(pack_verb(SkPipeVerb::kDrawRect)); 405 writer.write(&rect, sizeof(SkRect)); 406 write_paint(writer, paint, kGeometry_PaintUsage); 407} 408 409void SkPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { 410 SkPipeWriter writer(this); 411 writer.write32(pack_verb(SkPipeVerb::kDrawOval)); 412 writer.write(&rect, sizeof(SkRect)); 413 write_paint(writer, paint, kGeometry_PaintUsage); 414} 415 416void SkPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 417 SkPipeWriter writer(this); 418 writer.write32(pack_verb(SkPipeVerb::kDrawRRect)); 419 write_rrect(&writer, rrect); 420 write_paint(writer, paint, kGeometry_PaintUsage); 421} 422 423void SkPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 424 SkPipeWriter writer(this); 425 writer.write32(pack_verb(SkPipeVerb::kDrawDRRect)); 426 write_rrect(&writer, outer); 427 write_rrect(&writer, inner); 428 write_paint(writer, paint, kGeometry_PaintUsage); 429} 430 431void SkPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 432 SkPipeWriter writer(this); 433 writer.write32(pack_verb(SkPipeVerb::kDrawPath)); 434 writer.writePath(path); 435 write_paint(writer, paint, kGeometry_PaintUsage); 436} 437 438/////////////////////////////////////////////////////////////////////////////////////////////////// 439 440static sk_sp<SkImage> make_from_bitmap(const SkBitmap& bitmap) { 441 // If we just "make" an image, it will force a CPU copy (if its mutable), only to have 442 // us then either find it in our cache, or compress and send it. 443 // 444 // Better could be to look it up in our cache first, and only create/compress it if we have to. 445 // 446 // But for now, just do the dumb thing... 447 return SkImage::MakeFromBitmap(bitmap); 448} 449 450void SkPipeCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 451 const SkPaint* paint) { 452 sk_sp<SkImage> image = make_from_bitmap(bitmap); 453 if (image) { 454 this->onDrawImage(image.get(), x, y, paint); 455 } 456} 457 458void SkPipeCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 459 const SkPaint* paint, SrcRectConstraint constraint) { 460 sk_sp<SkImage> image = make_from_bitmap(bitmap); 461 if (image) { 462 this->onDrawImageRect(image.get(), src, dst, paint, constraint); 463 } 464} 465 466void SkPipeCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 467 const SkRect& dst, const SkPaint* paint) { 468 sk_sp<SkImage> image = make_from_bitmap(bitmap); 469 if (image) { 470 this->onDrawImageNine(image.get(), center, dst, paint); 471 } 472} 473 474void SkPipeCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, 475 const SkRect& dst, const SkPaint* paint) { 476 sk_sp<SkImage> image = make_from_bitmap(bitmap); 477 if (image) { 478 this->onDrawImageLattice(image.get(), lattice, dst, paint); 479 } 480} 481 482/////////////////////////////////////////////////////////////////////////////////////////////////// 483 484void SkPipeCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top, 485 const SkPaint* paint) { 486 unsigned extra = 0; 487 if (paint) { 488 extra |= kHasPaint_DrawImageMask; 489 } 490 SkPipeWriter writer(this); 491 writer.write32(pack_verb(SkPipeVerb::kDrawImage, extra)); 492 writer.writeImage(image); 493 writer.writeScalar(left); 494 writer.writeScalar(top); 495 if (paint) { 496 write_paint(writer, *paint, kImage_PaintUsage); 497 } 498} 499 500void SkPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 501 const SkPaint* paint, SrcRectConstraint constraint) { 502 SkASSERT(0 == ((unsigned)constraint & ~1)); 503 unsigned extra = (unsigned)constraint; 504 if (paint) { 505 extra |= kHasPaint_DrawImageRectMask; 506 } 507 if (src) { 508 extra |= kHasSrcRect_DrawImageRectMask; 509 } 510 511 SkPipeWriter writer(this); 512 writer.write32(pack_verb(SkPipeVerb::kDrawImageRect, extra)); 513 writer.writeImage(image); 514 if (src) { 515 writer.write(src, sizeof(*src)); 516 } 517 writer.write(&dst, sizeof(dst)); 518 if (paint) { 519 write_paint(writer, *paint, kImage_PaintUsage); 520 } 521} 522 523void SkPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 524 const SkPaint* paint) { 525 unsigned extra = 0; 526 if (paint) { 527 extra |= kHasPaint_DrawImageNineMask; 528 } 529 SkPipeWriter writer(this); 530 writer.write32(pack_verb(SkPipeVerb::kDrawImageNine, extra)); 531 writer.writeImage(image); 532 writer.write(¢er, sizeof(center)); 533 writer.write(&dst, sizeof(dst)); 534 if (paint) { 535 write_paint(writer, *paint, kImage_PaintUsage); 536 } 537} 538 539void SkPipeCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, 540 const SkRect& dst, const SkPaint* paint) { 541 unsigned extra = 0; 542 if (paint) { 543 extra |= kHasPaint_DrawImageLatticeMask; 544 } 545 if (lattice.fFlags) { 546 extra |= kHasFlags_DrawImageLatticeMask; 547 } 548 if (lattice.fXCount >= kCount_DrawImageLatticeMask) { 549 extra |= kCount_DrawImageLatticeMask << kXCount_DrawImageLatticeShift; 550 } else { 551 extra |= lattice.fXCount << kXCount_DrawImageLatticeShift; 552 } 553 if (lattice.fYCount >= kCount_DrawImageLatticeMask) { 554 extra |= kCount_DrawImageLatticeMask << kYCount_DrawImageLatticeShift; 555 } else { 556 extra |= lattice.fYCount << kYCount_DrawImageLatticeShift; 557 } 558 559 SkPipeWriter writer(this); 560 writer.write32(pack_verb(SkPipeVerb::kDrawImageLattice, extra)); 561 writer.writeImage(image); 562 if (lattice.fXCount >= kCount_DrawImageLatticeMask) { 563 writer.write32(lattice.fXCount); 564 } 565 if (lattice.fYCount >= kCount_DrawImageLatticeMask) { 566 writer.write32(lattice.fYCount); 567 } 568 // Often these divs will be small (8 or 16 bits). Consider sniffing that and writing a flag 569 // so we can store them smaller. 570 writer.write(lattice.fXDivs, lattice.fXCount * sizeof(int32_t)); 571 writer.write(lattice.fYDivs, lattice.fYCount * sizeof(int32_t)); 572 if (lattice.fFlags) { 573 int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1); 574 SkASSERT(count > 0); 575 write_pad(&writer, lattice.fFlags, count); 576 } 577 SkASSERT(lattice.fBounds); 578 writer.write(&lattice.fBounds, sizeof(*lattice.fBounds)); 579 writer.write(&dst, sizeof(dst)); 580 if (paint) { 581 write_paint(writer, *paint, kImage_PaintUsage); 582 } 583} 584 585/////////////////////////////////////////////////////////////////////////////////////////////////// 586 587void SkPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 588 const SkPaint& paint) { 589 SkASSERT(byteLength); 590 591 bool compact = fits_in(byteLength, 24); 592 593 SkPipeWriter writer(this); 594 writer.write32(pack_verb(SkPipeVerb::kDrawText, compact ? (unsigned)byteLength : 0)); 595 if (!compact) { 596 writer.write32(SkToU32(byteLength)); 597 } 598 write_pad(&writer, text, byteLength); 599 writer.writeScalar(x); 600 writer.writeScalar(y); 601 write_paint(writer, paint, kText_PaintUsage); 602} 603 604void SkPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 605 const SkPaint& paint) { 606 SkASSERT(byteLength); 607 608 bool compact = fits_in(byteLength, 24); 609 610 SkPipeWriter writer(this); 611 writer.write32(pack_verb(SkPipeVerb::kDrawPosText, compact ? (unsigned)byteLength : 0)); 612 if (!compact) { 613 writer.write32(SkToU32(byteLength)); 614 } 615 write_pad(&writer, text, byteLength); 616 writer.writePointArray(pos, paint.countText(text, byteLength)); 617 write_paint(writer, paint, kText_PaintUsage); 618} 619 620void SkPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 621 SkScalar constY, const SkPaint& paint) { 622 SkASSERT(byteLength); 623 624 bool compact = fits_in(byteLength, 24); 625 626 SkPipeWriter writer(this); 627 writer.write32(pack_verb(SkPipeVerb::kDrawPosTextH, compact ? (unsigned)byteLength : 0)); 628 if (!compact) { 629 writer.write32(SkToU32(byteLength)); 630 } 631 write_pad(&writer, text, byteLength); 632 writer.writeScalarArray(xpos, paint.countText(text, byteLength)); 633 writer.writeScalar(constY); 634 write_paint(writer, paint, kText_PaintUsage); 635} 636 637void SkPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 638 const SkMatrix* matrix, const SkPaint& paint) { 639 SkASSERT(byteLength > 0); 640 641 unsigned extra = 0; 642 if (byteLength <= kTextLength_DrawTextOnPathMask) { 643 extra |= byteLength; 644 } // else we will write the length after the packedverb 645 SkMatrix::TypeMask tm = matrix ? matrix->getType() : SkMatrix::kIdentity_Mask; 646 extra |= (unsigned)tm << kMatrixType_DrawTextOnPathShift; 647 648 SkPipeWriter writer(this); 649 writer.write32(pack_verb(SkPipeVerb::kDrawTextOnPath, extra)); 650 if (byteLength > kTextLength_DrawTextOnPathMask) { 651 writer.write32(byteLength); 652 } 653 write_pad(&writer, text, byteLength); 654 writer.writePath(path); 655 if (matrix) { 656 write_sparse_matrix(&writer, *matrix); 657 } 658 write_paint(writer, paint, kText_PaintUsage); 659} 660 661void SkPipeCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 662 const SkRect* cull, const SkPaint& paint) { 663 SkASSERT(byteLength); 664 665 bool compact = fits_in(byteLength, 23); 666 unsigned extra = compact ? (byteLength << 1) : 0; 667 if (cull) { 668 extra |= 1; 669 } 670 671 SkPipeWriter writer(this); 672 writer.write32(pack_verb(SkPipeVerb::kDrawTextRSXform, extra)); 673 if (!compact) { 674 writer.write32(SkToU32(byteLength)); 675 } 676 write_pad(&writer, text, byteLength); 677 678 int count = paint.countText(text, byteLength); 679 writer.write32(count); // maybe we can/should store this in extra as well? 680 writer.write(xform, count * sizeof(SkRSXform)); 681 if (cull) { 682 writer.writeRect(*cull); 683 } 684 write_paint(writer, paint, kText_PaintUsage); 685} 686 687void SkPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 688 const SkPaint &paint) { 689 SkPipeWriter writer(this); 690 writer.write32(pack_verb(SkPipeVerb::kDrawTextBlob, 0)); 691 blob->flatten(writer); 692 writer.writeScalar(x); 693 writer.writeScalar(y); 694 write_paint(writer, paint, kTextBlob_PaintUsage); 695} 696 697void SkPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 698 const SkPaint* paint) { 699 unsigned extra = fDeduper->findOrDefinePicture(const_cast<SkPicture*>(picture)); 700 if (matrix) { 701 extra |= kHasMatrix_DrawPictureExtra; 702 } 703 if (paint) { 704 extra |= kHasPaint_DrawPictureExtra; 705 } 706 SkPipeWriter writer(this); 707 writer.write32(pack_verb(SkPipeVerb::kDrawPicture, extra)); 708 if (matrix) { 709 writer.writeMatrix(*matrix); 710 } 711 if (paint) { 712 write_paint(writer, *paint, kSaveLayer_PaintUsage); 713 } 714} 715 716void SkPipeCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { 717 size_t size = region.writeToMemory(nullptr); 718 unsigned extra = 0; 719 if (fits_in(size, 24)) { 720 extra = SkToUInt(size); 721 } 722 723 SkPipeWriter writer(this); 724 writer.write32(pack_verb(SkPipeVerb::kDrawRegion, extra)); 725 if (0 == extra) { 726 writer.write32(size); 727 } 728 SkAutoSMalloc<2048> storage(size); 729 region.writeToMemory(storage.get()); 730 write_pad(&writer, storage.get(), size); 731 write_paint(writer, paint, kGeometry_PaintUsage); 732} 733 734void SkPipeCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 735 const SkPoint vertices[], const SkPoint texs[], 736 const SkColor colors[], SkBlendMode bmode, 737 const uint16_t indices[], int indexCount, 738 const SkPaint& paint) { 739 SkASSERT(vertexCount > 0); 740 741 unsigned extra = 0; 742 if (vertexCount <= kVCount_DrawVerticesMask) { 743 extra |= vertexCount; 744 } 745 extra |= (unsigned)vmode << kVMode_DrawVerticesShift; 746 extra |= (unsigned)bmode << kXMode_DrawVerticesShift; 747 748 if (texs) { 749 extra |= kHasTex_DrawVerticesMask; 750 } 751 if (colors) { 752 extra |= kHasColors_DrawVerticesMask; 753 } 754 if (indexCount > 0) { 755 extra |= kHasIndices_DrawVerticesMask; 756 } 757 758 SkPipeWriter writer(this); 759 writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra)); 760 if (vertexCount > kVCount_DrawVerticesMask) { 761 writer.write32(vertexCount); 762 } 763 writer.write(vertices, vertexCount * sizeof(SkPoint)); 764 if (texs) { 765 writer.write(texs, vertexCount * sizeof(SkPoint)); 766 } 767 if (colors) { 768 writer.write(colors, vertexCount * sizeof(SkColor)); 769 } 770 if (indexCount > 0) { 771 writer.write32(indexCount); 772 SkASSERT(SkIsAlign2(indexCount)); 773 writer.write(indices, indexCount * sizeof(uint16_t)); 774 } 775 write_paint(writer, paint, kVertices_PaintUsage); 776} 777 778void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 779 const SkPoint texCoords[4], SkBlendMode bmode, 780 const SkPaint& paint) { 781 SkPipeWriter writer(this); 782 unsigned extra = 0; 783 SkASSERT(0 == ((int)bmode & ~kModeEnum_DrawPatchExtraMask)); 784 extra = (unsigned)bmode; 785 if (colors) { 786 extra |= kHasColors_DrawPatchExtraMask; 787 } 788 if (texCoords) { 789 extra |= kHasTexture_DrawPatchExtraMask; 790 } 791 writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra)); 792 writer.write(cubics, sizeof(SkPoint) * 12); 793 if (colors) { 794 writer.write(colors, sizeof(SkColor) * 4); 795 } 796 if (texCoords) { 797 writer.write(texCoords, sizeof(SkPoint) * 4); 798 } 799 write_paint(writer, paint, kGeometry_PaintUsage); 800} 801 802void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) { 803 const size_t len = strlen(key) + 1; // must write the trailing 0 804 bool compact = fits_in(len, 23); 805 uint32_t extra = compact ? (unsigned)len : 0; 806 extra <<= 1; // make room for has_data_sentinel 807 if (data) { 808 extra |= 1; 809 } 810 811 fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra)); 812 fStream->write(&rect, sizeof(SkRect)); 813 if (!compact) { 814 fStream->write32(SkToU32(len)); 815 } 816 write_pad(fStream, key, len); 817 if (data) { 818 fStream->write32(SkToU32(data->size())); 819 write_pad(fStream, data->data(), data->size()); 820 } 821} 822 823/////////////////////////////////////////////////////////////////////////////////////////////////// 824 825class A8Serializer : public SkPixelSerializer { 826protected: 827 bool onUseEncodedData(const void* data, size_t len) { 828 return true; 829 } 830 831 SkData* onEncode(const SkPixmap& pmap) { 832 if (kAlpha_8_SkColorType == pmap.colorType()) { 833 SkDynamicMemoryWStream stream; 834 stream.write("skiaimgf", 8); 835 stream.write32(pmap.width()); 836 stream.write32(pmap.height()); 837 stream.write16(pmap.colorType()); 838 stream.write16(pmap.alphaType()); 839 stream.write32(0); // no colorspace for now 840 for (int y = 0; y < pmap.height(); ++y) { 841 stream.write(pmap.addr8(0, y), pmap.width()); 842 } 843 return stream.detachAsData().release(); 844 } 845 return nullptr; 846 } 847}; 848 849static sk_sp<SkData> default_image_serializer(SkImage* image) { 850 A8Serializer serial; 851 sk_sp<SkData> data(image->encode(&serial)); 852 if (!data) { 853 data.reset(image->encode()); 854 } 855 return data; 856} 857 858static bool show_deduper_traffic = false; 859 860int SkPipeDeduper::findOrDefineImage(SkImage* image) { 861 int index = fImages.find(image->uniqueID()); 862 SkASSERT(index >= 0); 863 if (index) { 864 if (show_deduper_traffic) { 865 SkDebugf(" reuseImage(%d)\n", index - 1); 866 } 867 return index; 868 } 869 870 sk_sp<SkData> data = fIMSerializer ? fIMSerializer->serialize(image) 871 : default_image_serializer(image); 872 if (data) { 873 index = fImages.add(image->uniqueID()); 874 SkASSERT(index > 0); 875 SkASSERT(fits_in(index, 24)); 876 fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index)); 877 878 uint32_t len = SkToU32(data->size()); 879 fStream->write32(SkAlign4(len)); 880 write_pad(fStream, data->data(), len); 881 882 if (show_deduper_traffic) { 883 int size = image->width() * image->height() << 2; 884 SkDebugf(" defineImage(%d) %d -> %d\n", index - 1, size, len); 885 } 886 return index; 887 } 888 SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->height()); 889 return 0; // failed to encode 890} 891 892int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) { 893 int index = fPictures.find(picture->uniqueID()); 894 SkASSERT(index >= 0); 895 if (index) { 896 if (show_deduper_traffic) { 897 SkDebugf(" reusePicture(%d)\n", index - 1); 898 } 899 return index; 900 } 901 902 size_t prevWritten = fStream->bytesWritten(); 903 unsigned extra = 0; // 0 means we're defining a new picture, non-zero means undef_index + 1 904 fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, extra)); 905 const SkRect cull = picture->cullRect(); 906 fStream->write(&cull, sizeof(cull)); 907 picture->playback(fPipeCanvas); 908 // call fPictures.add *after* we're written the picture, so that any nested pictures will have 909 // already been defined, and we get the "last" index value. 910 index = fPictures.add(picture->uniqueID()); 911 ASSERT_FITS_IN(index, kObjectDefinitionBits); 912 fStream->write32(pack_verb(SkPipeVerb::kEndPicture, index)); 913 914 SkDebugf(" definePicture(%d) %d\n", 915 index - 1, SkToU32(fStream->bytesWritten() - prevWritten)); 916 return index; 917} 918 919static sk_sp<SkData> encode(SkTypeface* tf) { 920 SkDynamicMemoryWStream stream; 921 tf->serialize(&stream); 922 return sk_sp<SkData>(stream.detachAsData()); 923} 924 925int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) { 926 if (!typeface) { 927 return 0; // default 928 } 929 930 int index = fTypefaces.find(typeface->uniqueID()); 931 SkASSERT(index >= 0); 932 if (index) { 933 if (show_deduper_traffic) { 934 SkDebugf(" reuseTypeface(%d)\n", index - 1); 935 } 936 return index; 937 } 938 939 sk_sp<SkData> data = fTFSerializer ? fTFSerializer->serialize(typeface) : encode(typeface); 940 if (data) { 941 index = fTypefaces.add(typeface->uniqueID()); 942 SkASSERT(index > 0); 943 SkASSERT(fits_in(index, 24)); 944 fStream->write32(pack_verb(SkPipeVerb::kDefineTypeface, index)); 945 946 uint32_t len = SkToU32(data->size()); 947 fStream->write32(SkAlign4(len)); 948 write_pad(fStream, data->data(), len); 949 950 if (show_deduper_traffic) { 951 SkDebugf(" defineTypeface(%d) %d\n", index - 1, len); 952 } 953 return index; 954 } 955 SkDebugf("+++ failed to encode typeface %d\n", typeface->uniqueID()); 956 return 0; // failed to encode 957} 958 959int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) { 960 if (!flattenable) { 961 return 0; 962 } 963 964 int index = fFactories.find(flattenable->getFactory()); 965 SkASSERT(index >= 0); 966 if (index) { 967 if (show_deduper_traffic) { 968 SkDebugf(" reuseFactory(%d)\n", index - 1); 969 } 970 return index; 971 } 972 973 index = fFactories.add(flattenable->getFactory()); 974 ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits); 975 const char* name = flattenable->getTypeName(); 976 size_t len = strlen(name); 977 ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits); 978 unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len; 979 size_t prevWritten = fStream->bytesWritten(); 980 fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra)); 981 write_pad(fStream, name, len + 1); 982 if (false) { 983 SkDebugf(" defineFactory(%d) %d %s\n", 984 index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name); 985 } 986 return index; 987} 988 989/////////////////////////////////////////////////////////////////////////////////////////////////// 990#include "SkPipe.h" 991 992class SkPipeSerializer::Impl { 993public: 994 SkPipeDeduper fDeduper; 995 std::unique_ptr<SkPipeCanvas> fCanvas; 996}; 997 998SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {} 999 1000SkPipeSerializer::~SkPipeSerializer() { 1001 if (fImpl->fCanvas) { 1002 this->endWrite(); 1003 } 1004} 1005 1006void SkPipeSerializer::setTypefaceSerializer(SkTypefaceSerializer* tfs) { 1007 fImpl->fDeduper.setTypefaceSerializer(tfs); 1008} 1009 1010void SkPipeSerializer::setImageSerializer(SkImageSerializer* ims) { 1011 fImpl->fDeduper.setImageSerializer(ims); 1012} 1013 1014void SkPipeSerializer::resetCache() { 1015 fImpl->fDeduper.resetCaches(); 1016} 1017 1018sk_sp<SkData> SkPipeSerializer::writeImage(SkImage* image) { 1019 SkDynamicMemoryWStream stream; 1020 this->writeImage(image, &stream); 1021 return stream.detachAsData(); 1022} 1023 1024sk_sp<SkData> SkPipeSerializer::writePicture(SkPicture* picture) { 1025 SkDynamicMemoryWStream stream; 1026 this->writePicture(picture, &stream); 1027 return stream.detachAsData(); 1028} 1029 1030void SkPipeSerializer::writePicture(SkPicture* picture, SkWStream* stream) { 1031 int index = fImpl->fDeduper.findPicture(picture); 1032 if (0 == index) { 1033 // Try to define the picture 1034 this->beginWrite(picture->cullRect(), stream); 1035 index = fImpl->fDeduper.findOrDefinePicture(picture); 1036 this->endWrite(); 1037 } 1038 stream->write32(pack_verb(SkPipeVerb::kWritePicture, index)); 1039} 1040 1041void SkPipeSerializer::writeImage(SkImage* image, SkWStream* stream) { 1042 int index = fImpl->fDeduper.findImage(image); 1043 if (0 == index) { 1044 // Try to define the image 1045 fImpl->fDeduper.setStream(stream); 1046 index = fImpl->fDeduper.findOrDefineImage(image); 1047 } 1048 stream->write32(pack_verb(SkPipeVerb::kWriteImage, index)); 1049} 1050 1051SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) { 1052 SkASSERT(nullptr == fImpl->fCanvas); 1053 fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream)); 1054 fImpl->fDeduper.setStream(stream); 1055 fImpl->fDeduper.setCanvas(fImpl->fCanvas.get()); 1056 return fImpl->fCanvas.get(); 1057} 1058 1059void SkPipeSerializer::endWrite() { 1060 fImpl->fCanvas->restoreToCount(1); 1061 fImpl->fCanvas.reset(nullptr); 1062 fImpl->fDeduper.setCanvas(nullptr); 1063} 1064