1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "SkAnnotation.h" 10 #include "SkBitmapDevice.h" 11 #include "SkBitmapHeap.h" 12 #include "SkCanvas.h" 13 #include "SkColorFilter.h" 14 #include "SkData.h" 15 #include "SkDrawLooper.h" 16 #include "SkGPipe.h" 17 #include "SkGPipePriv.h" 18 #include "SkImageFilter.h" 19 #include "SkMaskFilter.h" 20 #include "SkWriteBuffer.h" 21 #include "SkPaint.h" 22 #include "SkPathEffect.h" 23 #include "SkPictureFlat.h" 24 #include "SkRasterizer.h" 25 #include "SkRRect.h" 26 #include "SkShader.h" 27 #include "SkStream.h" 28 #include "SkTSearch.h" 29 #include "SkTypeface.h" 30 #include "SkWriter32.h" 31 32 enum { 33 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector) 34 }; 35 36 static bool isCrossProcess(uint32_t flags) { 37 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag); 38 } 39 40 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { 41 SkASSERT(paintFlat < kCount_PaintFlats); 42 switch (paintFlat) { 43 case kColorFilter_PaintFlat: return paint.getColorFilter(); 44 case kDrawLooper_PaintFlat: return paint.getLooper(); 45 case kMaskFilter_PaintFlat: return paint.getMaskFilter(); 46 case kPathEffect_PaintFlat: return paint.getPathEffect(); 47 case kRasterizer_PaintFlat: return paint.getRasterizer(); 48 case kShader_PaintFlat: return paint.getShader(); 49 case kImageFilter_PaintFlat: return paint.getImageFilter(); 50 case kXfermode_PaintFlat: return paint.getXfermode(); 51 } 52 SkDEBUGFAIL("never gets here"); 53 return NULL; 54 } 55 56 static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) { 57 SkASSERT(typeface); 58 SkDynamicMemoryWStream stream; 59 typeface->serialize(&stream); 60 size_t size = stream.getOffset(); 61 if (writer) { 62 writer->write32(SkToU32(size)); 63 SkAutoDataUnref data(stream.copyToData()); 64 writer->writePad(data->data(), size); 65 } 66 return 4 + SkAlign4(size); 67 } 68 69 /////////////////////////////////////////////////////////////////////////////// 70 71 class FlattenableHeap : public SkFlatController { 72 public: 73 FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossProcess) 74 : INHERITED(isCrossProcess ? SkWriteBuffer::kCrossProcess_Flag : 0) 75 , fNumFlatsToKeep(numFlatsToKeep) { 76 SkASSERT((isCrossProcess && fset != NULL) || (!isCrossProcess && NULL == fset)); 77 if (isCrossProcess) { 78 this->setNamedFactorySet(fset); 79 } 80 } 81 82 ~FlattenableHeap() { 83 fPointers.freeAll(); 84 } 85 86 virtual void* allocThrow(size_t bytes) SK_OVERRIDE; 87 88 virtual void unalloc(void* ptr) SK_OVERRIDE; 89 90 void setBitmapStorage(SkBitmapHeap* heap) { 91 this->setBitmapHeap(heap); 92 } 93 94 const SkFlatData* flatToReplace() const; 95 96 // Mark an SkFlatData as one that should not be returned by flatToReplace. 97 // Takes the result of SkFlatData::index() as its parameter. 98 void markFlatForKeeping(int index) { 99 *fFlatsThatMustBeKept.append() = index; 100 } 101 102 void markAllFlatsSafeToDelete() { 103 fFlatsThatMustBeKept.reset(); 104 } 105 106 private: 107 // Keep track of the indices (i.e. the result of SkFlatData::index()) of 108 // flats that must be kept, since they are on the current paint. 109 SkTDArray<int> fFlatsThatMustBeKept; 110 SkTDArray<void*> fPointers; 111 const int fNumFlatsToKeep; 112 113 typedef SkFlatController INHERITED; 114 }; 115 116 void FlattenableHeap::unalloc(void* ptr) { 117 int indexToRemove = fPointers.rfind(ptr); 118 if (indexToRemove >= 0) { 119 sk_free(ptr); 120 fPointers.remove(indexToRemove); 121 } 122 } 123 124 void* FlattenableHeap::allocThrow(size_t bytes) { 125 void* ptr = sk_malloc_throw(bytes); 126 *fPointers.append() = ptr; 127 return ptr; 128 } 129 130 const SkFlatData* FlattenableHeap::flatToReplace() const { 131 // First, determine whether we should replace one. 132 if (fPointers.count() > fNumFlatsToKeep) { 133 // Look through the flattenable heap. 134 // TODO: Return the LRU flat. 135 for (int i = 0; i < fPointers.count(); i++) { 136 SkFlatData* potential = (SkFlatData*)fPointers[i]; 137 // Make sure that it is not one that must be kept. 138 bool mustKeep = false; 139 for (int j = 0; j < fFlatsThatMustBeKept.count(); j++) { 140 if (potential->index() == fFlatsThatMustBeKept[j]) { 141 mustKeep = true; 142 break; 143 } 144 } 145 if (!mustKeep) { 146 return potential; 147 } 148 } 149 } 150 return NULL; 151 } 152 153 /////////////////////////////////////////////////////////////////////////////// 154 155 struct SkFlattenableTraits { 156 static void Flatten(SkWriteBuffer& buffer, const SkFlattenable& flattenable) { 157 buffer.writeFlattenable(&flattenable); 158 } 159 // No need to define unflatten if we never call it. 160 }; 161 typedef SkFlatDictionary<SkFlattenable, SkFlattenableTraits> FlatDictionary; 162 163 /////////////////////////////////////////////////////////////////////////////// 164 165 /** 166 * If SkBitmaps are to be flattened to send to the reader, this class is 167 * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so. 168 */ 169 class BitmapShuttle : public SkBitmapHeap::ExternalStorage { 170 public: 171 BitmapShuttle(SkGPipeCanvas*); 172 173 ~BitmapShuttle(); 174 175 virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE; 176 177 /** 178 * Remove the SkGPipeCanvas used for insertion. After this, calls to 179 * insert will crash. 180 */ 181 void removeCanvas(); 182 183 private: 184 SkGPipeCanvas* fCanvas; 185 }; 186 187 /////////////////////////////////////////////////////////////////////////////// 188 189 class SkGPipeCanvas : public SkCanvas { 190 public: 191 SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags, 192 uint32_t width, uint32_t height); 193 virtual ~SkGPipeCanvas(); 194 195 /** 196 * Called when nothing else is to be written to the stream. Any repeated 197 * calls are ignored. 198 * 199 * @param notifyReaders Whether to send a message to the reader(s) that 200 * the writer is through sending commands. Should generally be true, 201 * unless there is an error which prevents further messages from 202 * being sent. 203 */ 204 void finish(bool notifyReaders) { 205 if (fDone) { 206 return; 207 } 208 if (notifyReaders && this->needOpBytes()) { 209 this->writeOp(kDone_DrawOp); 210 this->doNotify(); 211 } 212 if (shouldFlattenBitmaps(fFlags)) { 213 // The following circular references exist: 214 // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalStorage -> fCanvas 215 // fBitmapHeap -> fExternalStorage -> fCanvas 216 // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas 217 218 // Break them all by destroying the final link to this SkGPipeCanvas. 219 fBitmapShuttle->removeCanvas(); 220 } 221 fDone = true; 222 } 223 224 void flushRecording(bool detachCurrentBlock); 225 size_t freeMemoryIfPossible(size_t bytesToFree); 226 227 size_t storageAllocatedForRecording() { 228 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated(); 229 } 230 231 // overrides from SkCanvas 232 virtual bool isDrawingToLayer() const SK_OVERRIDE; 233 virtual void clear(SkColor) SK_OVERRIDE; 234 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; 235 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[], 236 const SkPaint&) SK_OVERRIDE; 237 virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; 238 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE; 239 virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE; 240 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE; 241 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 242 const SkPaint*) SK_OVERRIDE; 243 virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, 244 const SkRect& dst, const SkPaint* paint, 245 DrawBitmapRectFlags flags) SK_OVERRIDE; 246 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 247 const SkPaint*) SK_OVERRIDE; 248 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 249 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE; 250 virtual void drawSprite(const SkBitmap&, int left, int top, 251 const SkPaint*) SK_OVERRIDE; 252 virtual void drawVertices(VertexMode, int vertexCount, 253 const SkPoint vertices[], const SkPoint texs[], 254 const SkColor colors[], SkXfermode*, 255 const uint16_t indices[], int indexCount, 256 const SkPaint&) SK_OVERRIDE; 257 virtual void drawData(const void*, size_t) SK_OVERRIDE; 258 virtual void beginCommentGroup(const char* description) SK_OVERRIDE; 259 virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; 260 virtual void endCommentGroup() SK_OVERRIDE; 261 262 /** 263 * Flatten an SkBitmap to send to the reader, where it will be referenced 264 * according to slot. 265 */ 266 bool shuttleBitmap(const SkBitmap&, int32_t slot); 267 268 protected: 269 virtual void willSave(SaveFlags) SK_OVERRIDE; 270 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE; 271 virtual void willRestore() SK_OVERRIDE; 272 273 virtual void didConcat(const SkMatrix&) SK_OVERRIDE; 274 virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE; 275 276 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE; 277 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 278 const SkPaint&) SK_OVERRIDE; 279 virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 280 const SkPaint&) SK_OVERRIDE; 281 virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 282 SkScalar constY, const SkPaint&) SK_OVERRIDE; 283 virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 284 const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE; 285 286 virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 287 virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 288 virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 289 virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE; 290 291 virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE; 292 293 private: 294 void recordTranslate(const SkMatrix&); 295 void recordScale(const SkMatrix&); 296 void recordConcat(const SkMatrix&); 297 298 enum { 299 kNoSaveLayer = -1, 300 }; 301 SkNamedFactorySet* fFactorySet; 302 int fFirstSaveLayerStackLevel; 303 SkBitmapHeap* fBitmapHeap; 304 SkGPipeController* fController; 305 SkWriter32& fWriter; 306 size_t fBlockSize; // amount allocated for writer 307 size_t fBytesNotified; 308 bool fDone; 309 const uint32_t fFlags; 310 311 SkRefCntSet fTypefaceSet; 312 313 uint32_t getTypefaceID(SkTypeface*); 314 315 inline void writeOp(DrawOps op, unsigned flags, unsigned data) { 316 fWriter.write32(DrawOp_packOpFlagData(op, flags, data)); 317 } 318 319 inline void writeOp(DrawOps op) { 320 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0)); 321 } 322 323 bool needOpBytes(size_t size = 0); 324 325 inline void doNotify() { 326 if (!fDone) { 327 size_t bytes = fWriter.bytesWritten() - fBytesNotified; 328 if (bytes > 0) { 329 fController->notifyWritten(bytes); 330 fBytesNotified += bytes; 331 } 332 } 333 } 334 335 // Should be called after any calls to an SkFlatDictionary::findAndReplace 336 // if a new SkFlatData was added when in cross process mode 337 void flattenFactoryNames(); 338 339 FlattenableHeap fFlattenableHeap; 340 FlatDictionary fFlatDictionary; 341 SkAutoTUnref<BitmapShuttle> fBitmapShuttle; 342 int fCurrFlatIndex[kCount_PaintFlats]; 343 344 int flattenToIndex(SkFlattenable* obj, PaintFlats); 345 346 // Common code used by drawBitmap*. Behaves differently depending on the 347 // type of SkBitmapHeap being used, which is determined by the flags used. 348 bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, 349 size_t opBytesNeeded, const SkPaint* paint); 350 351 SkPaint fPaint; 352 void writePaint(const SkPaint&); 353 354 class AutoPipeNotify { 355 public: 356 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {} 357 ~AutoPipeNotify() { fCanvas->doNotify(); } 358 private: 359 SkGPipeCanvas* fCanvas; 360 }; 361 friend class AutoPipeNotify; 362 363 typedef SkCanvas INHERITED; 364 }; 365 366 void SkGPipeCanvas::flattenFactoryNames() { 367 const char* name; 368 while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) { 369 size_t len = strlen(name); 370 if (this->needOpBytes(SkWriter32::WriteStringSize(name, len))) { 371 this->writeOp(kDef_Factory_DrawOp); 372 fWriter.writeString(name, len); 373 } 374 } 375 } 376 377 bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) { 378 SkASSERT(shouldFlattenBitmaps(fFlags)); 379 SkWriteBuffer buffer; 380 buffer.setNamedFactoryRecorder(fFactorySet); 381 buffer.writeBitmap(bm); 382 this->flattenFactoryNames(); 383 size_t size = buffer.bytesWritten(); 384 if (this->needOpBytes(size)) { 385 this->writeOp(kDef_Bitmap_DrawOp, 0, slot); 386 void* dst = static_cast<void*>(fWriter.reserve(size)); 387 buffer.writeToMemory(dst); 388 return true; 389 } 390 return false; 391 } 392 393 // return 0 for NULL (or unflattenable obj), or index-base-1 394 // return ~(index-base-1) if an old flattenable was replaced 395 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) { 396 SkASSERT(!fDone && fBitmapHeap != NULL); 397 if (NULL == obj) { 398 return 0; 399 } 400 401 fBitmapHeap->deferAddingOwners(); 402 bool added, replaced; 403 const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHeap.flatToReplace(), 404 &added, &replaced); 405 fBitmapHeap->endAddingOwnersDeferral(added); 406 int index = flat->index(); 407 if (added) { 408 if (isCrossProcess(fFlags)) { 409 this->flattenFactoryNames(); 410 } 411 size_t flatSize = flat->flatSize(); 412 if (this->needOpBytes(flatSize)) { 413 this->writeOp(kDef_Flattenable_DrawOp, paintflat, index); 414 fWriter.write(flat->data(), flatSize); 415 } 416 } 417 if (replaced) { 418 index = ~index; 419 } 420 return index; 421 } 422 423 /////////////////////////////////////////////////////////////////////////////// 424 425 #define MIN_BLOCK_SIZE (16 * 1024) 426 #define BITMAPS_TO_KEEP 5 427 #define FLATTENABLES_TO_KEEP 10 428 429 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, 430 SkWriter32* writer, uint32_t flags, 431 uint32_t width, uint32_t height) 432 : SkCanvas(width, height) 433 , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) 434 , fWriter(*writer) 435 , fFlags(flags) 436 , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags)) 437 , fFlatDictionary(&fFlattenableHeap) 438 { 439 fController = controller; 440 fDone = false; 441 fBlockSize = 0; // need first block from controller 442 fBytesNotified = 0; 443 fFirstSaveLayerStackLevel = kNoSaveLayer; 444 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); 445 446 // Tell the reader the appropriate flags to use. 447 if (this->needOpBytes()) { 448 this->writeOp(kReportFlags_DrawOp, fFlags, 0); 449 } 450 451 if (shouldFlattenBitmaps(flags)) { 452 fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this))); 453 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO_KEEP)); 454 } else { 455 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, 456 (BITMAPS_TO_KEEP, controller->numberOfReaders())); 457 if (this->needOpBytes(sizeof(void*))) { 458 this->writeOp(kShareBitmapHeap_DrawOp); 459 fWriter.writePtr(static_cast<void*>(fBitmapHeap)); 460 } 461 } 462 fFlattenableHeap.setBitmapStorage(fBitmapHeap); 463 this->doNotify(); 464 } 465 466 SkGPipeCanvas::~SkGPipeCanvas() { 467 this->finish(true); 468 SkSafeUnref(fFactorySet); 469 SkSafeUnref(fBitmapHeap); 470 } 471 472 bool SkGPipeCanvas::needOpBytes(size_t needed) { 473 if (fDone) { 474 return false; 475 } 476 477 needed += 4; // size of DrawOp atom 478 needed = SkTMax<size_t>(MIN_BLOCK_SIZE, needed); 479 needed = SkAlign4(needed); 480 if (fWriter.bytesWritten() + needed > fBlockSize) { 481 // Before we wipe out any data that has already been written, read it 482 // out. 483 this->doNotify(); 484 void* block = fController->requestBlock(needed, &fBlockSize); 485 if (NULL == block) { 486 // Do not notify the readers, which would call this function again. 487 this->finish(false); 488 return false; 489 } 490 SkASSERT(SkIsAlign4(fBlockSize)); 491 fWriter.reset(block, fBlockSize); 492 fBytesNotified = 0; 493 } 494 return true; 495 } 496 497 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { 498 uint32_t id = 0; // 0 means default/null typeface 499 if (face) { 500 id = fTypefaceSet.find(face); 501 if (0 == id) { 502 id = fTypefaceSet.add(face); 503 size_t size = writeTypeface(NULL, face); 504 if (this->needOpBytes(size)) { 505 this->writeOp(kDef_Typeface_DrawOp); 506 writeTypeface(&fWriter, face); 507 } 508 } 509 } 510 return id; 511 } 512 513 /////////////////////////////////////////////////////////////////////////////// 514 515 #define NOTIFY_SETUP(canvas) \ 516 AutoPipeNotify apn(canvas) 517 518 void SkGPipeCanvas::willSave(SaveFlags flags) { 519 NOTIFY_SETUP(this); 520 if (this->needOpBytes()) { 521 this->writeOp(kSave_DrawOp, 0, flags); 522 } 523 524 this->INHERITED::willSave(flags); 525 } 526 527 SkCanvas::SaveLayerStrategy SkGPipeCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint, 528 SaveFlags saveFlags) { 529 NOTIFY_SETUP(this); 530 size_t size = 0; 531 unsigned opFlags = 0; 532 533 if (bounds) { 534 opFlags |= kSaveLayer_HasBounds_DrawOpFlag; 535 size += sizeof(SkRect); 536 } 537 if (paint) { 538 opFlags |= kSaveLayer_HasPaint_DrawOpFlag; 539 this->writePaint(*paint); 540 } 541 542 if (this->needOpBytes(size)) { 543 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags); 544 if (bounds) { 545 fWriter.writeRect(*bounds); 546 } 547 } 548 549 if (kNoSaveLayer == fFirstSaveLayerStackLevel){ 550 fFirstSaveLayerStackLevel = this->getSaveCount(); 551 } 552 553 this->INHERITED::willSaveLayer(bounds, paint, saveFlags); 554 // we don't create a layer 555 return kNoLayer_SaveLayerStrategy; 556 } 557 558 void SkGPipeCanvas::willRestore() { 559 NOTIFY_SETUP(this); 560 if (this->needOpBytes()) { 561 this->writeOp(kRestore_DrawOp); 562 } 563 564 if (this->getSaveCount() - 1 == fFirstSaveLayerStackLevel){ 565 fFirstSaveLayerStackLevel = kNoSaveLayer; 566 } 567 568 this->INHERITED::willRestore(); 569 } 570 571 bool SkGPipeCanvas::isDrawingToLayer() const { 572 return kNoSaveLayer != fFirstSaveLayerStackLevel; 573 } 574 575 void SkGPipeCanvas::recordTranslate(const SkMatrix& m) { 576 if (this->needOpBytes(2 * sizeof(SkScalar))) { 577 this->writeOp(kTranslate_DrawOp); 578 fWriter.writeScalar(m.getTranslateX()); 579 fWriter.writeScalar(m.getTranslateY()); 580 } 581 } 582 583 void SkGPipeCanvas::recordScale(const SkMatrix& m) { 584 if (this->needOpBytes(2 * sizeof(SkScalar))) { 585 this->writeOp(kScale_DrawOp); 586 fWriter.writeScalar(m.getScaleX()); 587 fWriter.writeScalar(m.getScaleY()); 588 } 589 } 590 591 void SkGPipeCanvas::recordConcat(const SkMatrix& m) { 592 if (this->needOpBytes(m.writeToMemory(NULL))) { 593 this->writeOp(kConcat_DrawOp); 594 fWriter.writeMatrix(m); 595 } 596 } 597 598 void SkGPipeCanvas::didConcat(const SkMatrix& matrix) { 599 if (!matrix.isIdentity()) { 600 NOTIFY_SETUP(this); 601 switch (matrix.getType()) { 602 case SkMatrix::kTranslate_Mask: 603 this->recordTranslate(matrix); 604 break; 605 case SkMatrix::kScale_Mask: 606 this->recordScale(matrix); 607 break; 608 default: 609 this->recordConcat(matrix); 610 break; 611 } 612 } 613 614 this->INHERITED::didConcat(matrix); 615 } 616 617 void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) { 618 NOTIFY_SETUP(this); 619 if (this->needOpBytes(matrix.writeToMemory(NULL))) { 620 this->writeOp(kSetMatrix_DrawOp); 621 fWriter.writeMatrix(matrix); 622 } 623 this->INHERITED::didSetMatrix(matrix); 624 } 625 626 void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp, 627 ClipEdgeStyle edgeStyle) { 628 NOTIFY_SETUP(this); 629 if (this->needOpBytes(sizeof(SkRect))) { 630 unsigned flags = 0; 631 if (kSoft_ClipEdgeStyle == edgeStyle) { 632 flags = kClip_HasAntiAlias_DrawOpFlag; 633 } 634 this->writeOp(kClipRect_DrawOp, flags, rgnOp); 635 fWriter.writeRect(rect); 636 } 637 this->INHERITED::onClipRect(rect, rgnOp, edgeStyle); 638 } 639 640 void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp, 641 ClipEdgeStyle edgeStyle) { 642 NOTIFY_SETUP(this); 643 if (this->needOpBytes(kSizeOfFlatRRect)) { 644 unsigned flags = 0; 645 if (kSoft_ClipEdgeStyle == edgeStyle) { 646 flags = kClip_HasAntiAlias_DrawOpFlag; 647 } 648 this->writeOp(kClipRRect_DrawOp, flags, rgnOp); 649 fWriter.writeRRect(rrect); 650 } 651 this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle); 652 } 653 654 void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp, 655 ClipEdgeStyle edgeStyle) { 656 NOTIFY_SETUP(this); 657 if (this->needOpBytes(path.writeToMemory(NULL))) { 658 unsigned flags = 0; 659 if (kSoft_ClipEdgeStyle == edgeStyle) { 660 flags = kClip_HasAntiAlias_DrawOpFlag; 661 } 662 this->writeOp(kClipPath_DrawOp, flags, rgnOp); 663 fWriter.writePath(path); 664 } 665 // we just pass on the bounds of the path 666 this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle); 667 } 668 669 void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) { 670 NOTIFY_SETUP(this); 671 if (this->needOpBytes(region.writeToMemory(NULL))) { 672 this->writeOp(kClipRegion_DrawOp, 0, rgnOp); 673 fWriter.writeRegion(region); 674 } 675 this->INHERITED::onClipRegion(region, rgnOp); 676 } 677 678 /////////////////////////////////////////////////////////////////////////////// 679 680 void SkGPipeCanvas::clear(SkColor color) { 681 NOTIFY_SETUP(this); 682 unsigned flags = 0; 683 if (color) { 684 flags |= kClear_HasColor_DrawOpFlag; 685 } 686 if (this->needOpBytes(sizeof(SkColor))) { 687 this->writeOp(kDrawClear_DrawOp, flags, 0); 688 if (color) { 689 fWriter.write32(color); 690 } 691 } 692 } 693 694 void SkGPipeCanvas::drawPaint(const SkPaint& paint) { 695 NOTIFY_SETUP(this); 696 this->writePaint(paint); 697 if (this->needOpBytes()) { 698 this->writeOp(kDrawPaint_DrawOp); 699 } 700 } 701 702 void SkGPipeCanvas::drawPoints(PointMode mode, size_t count, 703 const SkPoint pts[], const SkPaint& paint) { 704 if (count) { 705 NOTIFY_SETUP(this); 706 this->writePaint(paint); 707 if (this->needOpBytes(4 + count * sizeof(SkPoint))) { 708 this->writeOp(kDrawPoints_DrawOp, mode, 0); 709 fWriter.write32(SkToU32(count)); 710 fWriter.write(pts, count * sizeof(SkPoint)); 711 } 712 } 713 } 714 715 void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) { 716 NOTIFY_SETUP(this); 717 this->writePaint(paint); 718 if (this->needOpBytes(sizeof(SkRect))) { 719 this->writeOp(kDrawOval_DrawOp); 720 fWriter.writeRect(rect); 721 } 722 } 723 724 void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 725 NOTIFY_SETUP(this); 726 this->writePaint(paint); 727 if (this->needOpBytes(sizeof(SkRect))) { 728 this->writeOp(kDrawRect_DrawOp); 729 fWriter.writeRect(rect); 730 } 731 } 732 733 void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 734 NOTIFY_SETUP(this); 735 this->writePaint(paint); 736 if (this->needOpBytes(kSizeOfFlatRRect)) { 737 this->writeOp(kDrawRRect_DrawOp); 738 fWriter.writeRRect(rrect); 739 } 740 } 741 742 void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 743 const SkPaint& paint) { 744 NOTIFY_SETUP(this); 745 this->writePaint(paint); 746 if (this->needOpBytes(kSizeOfFlatRRect * 2)) { 747 this->writeOp(kDrawDRRect_DrawOp); 748 fWriter.writeRRect(outer); 749 fWriter.writeRRect(inner); 750 } 751 } 752 753 void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 754 NOTIFY_SETUP(this); 755 this->writePaint(paint); 756 if (this->needOpBytes(path.writeToMemory(NULL))) { 757 this->writeOp(kDrawPath_DrawOp); 758 fWriter.writePath(path); 759 } 760 } 761 762 bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op, 763 unsigned flags, 764 size_t opBytesNeeded, 765 const SkPaint* paint) { 766 if (fDone) { 767 return false; 768 } 769 770 if (paint != NULL) { 771 flags |= kDrawBitmap_HasPaint_DrawOpFlag; 772 this->writePaint(*paint); 773 } 774 // This needs to run first so its calls to needOpBytes() and its writes 775 // don't interlace with the needOpBytes() and write below. 776 SkASSERT(fBitmapHeap != NULL); 777 int32_t bitmapIndex = fBitmapHeap->insert(bm); 778 if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) { 779 return false; 780 } 781 782 if (this->needOpBytes(opBytesNeeded)) { 783 this->writeOp(op, flags, bitmapIndex); 784 return true; 785 } 786 return false; 787 } 788 789 void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top, 790 const SkPaint* paint) { 791 NOTIFY_SETUP(this); 792 size_t opBytesNeeded = sizeof(SkScalar) * 2; 793 794 if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) { 795 fWriter.writeScalar(left); 796 fWriter.writeScalar(top); 797 } 798 } 799 800 void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src, 801 const SkRect& dst, const SkPaint* paint, 802 DrawBitmapRectFlags dbmrFlags) { 803 NOTIFY_SETUP(this); 804 size_t opBytesNeeded = sizeof(SkRect); 805 bool hasSrc = src != NULL; 806 unsigned flags; 807 if (hasSrc) { 808 flags = kDrawBitmap_HasSrcRect_DrawOpFlag; 809 opBytesNeeded += sizeof(int32_t) * 4; 810 } else { 811 flags = 0; 812 } 813 if (dbmrFlags & kBleed_DrawBitmapRectFlag) { 814 flags |= kDrawBitmap_Bleed_DrawOpFlag; 815 } 816 817 if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) { 818 if (hasSrc) { 819 fWriter.writeRect(*src); 820 } 821 fWriter.writeRect(dst); 822 } 823 } 824 825 void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix, 826 const SkPaint* paint) { 827 NOTIFY_SETUP(this); 828 size_t opBytesNeeded = matrix.writeToMemory(NULL); 829 830 if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) { 831 fWriter.writeMatrix(matrix); 832 } 833 } 834 835 void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center, 836 const SkRect& dst, const SkPaint* paint) { 837 NOTIFY_SETUP(this); 838 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect); 839 840 if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) { 841 fWriter.write32(center.fLeft); 842 fWriter.write32(center.fTop); 843 fWriter.write32(center.fRight); 844 fWriter.write32(center.fBottom); 845 fWriter.writeRect(dst); 846 } 847 } 848 849 void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top, 850 const SkPaint* paint) { 851 NOTIFY_SETUP(this); 852 size_t opBytesNeeded = sizeof(int32_t) * 2; 853 854 if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) { 855 fWriter.write32(left); 856 fWriter.write32(top); 857 } 858 } 859 860 void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 861 const SkPaint& paint) { 862 if (byteLength) { 863 NOTIFY_SETUP(this); 864 this->writePaint(paint); 865 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) { 866 this->writeOp(kDrawText_DrawOp); 867 fWriter.write32(SkToU32(byteLength)); 868 fWriter.writePad(text, byteLength); 869 fWriter.writeScalar(x); 870 fWriter.writeScalar(y); 871 } 872 } 873 } 874 875 void SkGPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 876 const SkPaint& paint) { 877 if (byteLength) { 878 NOTIFY_SETUP(this); 879 this->writePaint(paint); 880 int count = paint.textToGlyphs(text, byteLength, NULL); 881 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) { 882 this->writeOp(kDrawPosText_DrawOp); 883 fWriter.write32(SkToU32(byteLength)); 884 fWriter.writePad(text, byteLength); 885 fWriter.write32(count); 886 fWriter.write(pos, count * sizeof(SkPoint)); 887 } 888 } 889 } 890 891 void SkGPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 892 SkScalar constY, const SkPaint& paint) { 893 if (byteLength) { 894 NOTIFY_SETUP(this); 895 this->writePaint(paint); 896 int count = paint.textToGlyphs(text, byteLength, NULL); 897 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) { 898 this->writeOp(kDrawPosTextH_DrawOp); 899 fWriter.write32(SkToU32(byteLength)); 900 fWriter.writePad(text, byteLength); 901 fWriter.write32(count); 902 fWriter.write(xpos, count * sizeof(SkScalar)); 903 fWriter.writeScalar(constY); 904 } 905 } 906 } 907 908 void SkGPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 909 const SkMatrix* matrix, const SkPaint& paint) { 910 if (byteLength) { 911 NOTIFY_SETUP(this); 912 unsigned flags = 0; 913 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL); 914 if (matrix) { 915 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag; 916 size += matrix->writeToMemory(NULL); 917 } 918 this->writePaint(paint); 919 if (this->needOpBytes(size)) { 920 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0); 921 922 fWriter.write32(SkToU32(byteLength)); 923 fWriter.writePad(text, byteLength); 924 925 fWriter.writePath(path); 926 if (matrix) { 927 fWriter.writeMatrix(*matrix); 928 } 929 } 930 } 931 } 932 933 void SkGPipeCanvas::onDrawPicture(const SkPicture* picture) { 934 // we want to playback the picture into individual draw calls 935 this->INHERITED::onDrawPicture(picture); 936 } 937 938 void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount, 939 const SkPoint vertices[], const SkPoint texs[], 940 const SkColor colors[], SkXfermode* xfer, 941 const uint16_t indices[], int indexCount, 942 const SkPaint& paint) { 943 if (0 == vertexCount) { 944 return; 945 } 946 947 NOTIFY_SETUP(this); 948 this->writePaint(paint); 949 950 unsigned flags = 0; // packs with the op, so needs no extra space 951 952 size_t size = 0; 953 size += 4; // vmode 954 size += 4; // vertex count 955 size += vertexCount * sizeof(SkPoint); // vertices 956 957 if (texs) { 958 flags |= kDrawVertices_HasTexs_DrawOpFlag; 959 size += vertexCount * sizeof(SkPoint); 960 } 961 if (colors) { 962 flags |= kDrawVertices_HasColors_DrawOpFlag; 963 size += vertexCount * sizeof(SkColor); 964 } 965 if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) { 966 flags |= kDrawVertices_HasXfermode_DrawOpFlag; 967 size += sizeof(int32_t); // SkXfermode::Mode 968 } 969 if (indices && indexCount > 0) { 970 flags |= kDrawVertices_HasIndices_DrawOpFlag; 971 size += 4; // index count 972 size += SkAlign4(indexCount * sizeof(uint16_t)); // indices 973 } 974 975 if (this->needOpBytes(size)) { 976 this->writeOp(kDrawVertices_DrawOp, flags, 0); 977 fWriter.write32(vmode); 978 fWriter.write32(vertexCount); 979 fWriter.write(vertices, vertexCount * sizeof(SkPoint)); 980 if (flags & kDrawVertices_HasTexs_DrawOpFlag) { 981 fWriter.write(texs, vertexCount * sizeof(SkPoint)); 982 } 983 if (flags & kDrawVertices_HasColors_DrawOpFlag) { 984 fWriter.write(colors, vertexCount * sizeof(SkColor)); 985 } 986 if (flags & kDrawVertices_HasXfermode_DrawOpFlag) { 987 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; 988 SkAssertResult(xfer->asMode(&mode)); 989 fWriter.write32(mode); 990 } 991 if (flags & kDrawVertices_HasIndices_DrawOpFlag) { 992 fWriter.write32(indexCount); 993 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); 994 } 995 } 996 } 997 998 void SkGPipeCanvas::drawData(const void* ptr, size_t size) { 999 if (size && ptr) { 1000 NOTIFY_SETUP(this); 1001 unsigned data = 0; 1002 if (size < (1 << DRAWOPS_DATA_BITS)) { 1003 data = (unsigned)size; 1004 } 1005 if (this->needOpBytes(4 + SkAlign4(size))) { 1006 this->writeOp(kDrawData_DrawOp, 0, data); 1007 if (0 == data) { 1008 fWriter.write32(SkToU32(size)); 1009 } 1010 fWriter.writePad(ptr, size); 1011 } 1012 } 1013 } 1014 1015 void SkGPipeCanvas::beginCommentGroup(const char* description) { 1016 // ignore for now 1017 } 1018 1019 void SkGPipeCanvas::addComment(const char* kywd, const char* value) { 1020 // ignore for now 1021 } 1022 1023 void SkGPipeCanvas::endCommentGroup() { 1024 // ignore for now 1025 } 1026 1027 void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) { 1028 this->doNotify(); 1029 if (detachCurrentBlock) { 1030 // force a new block to be requested for the next recorded command 1031 fBlockSize = 0; 1032 } 1033 } 1034 1035 size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) { 1036 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree); 1037 } 1038 1039 /////////////////////////////////////////////////////////////////////////////// 1040 1041 template <typename T> uint32_t castToU32(T value) { 1042 union { 1043 T fSrc; 1044 uint32_t fDst; 1045 } data; 1046 data.fSrc = value; 1047 return data.fDst; 1048 } 1049 1050 void SkGPipeCanvas::writePaint(const SkPaint& paint) { 1051 if (fDone) { 1052 return; 1053 } 1054 SkPaint& base = fPaint; 1055 uint32_t storage[32]; 1056 uint32_t* ptr = storage; 1057 1058 if (base.getFlags() != paint.getFlags()) { 1059 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags()); 1060 base.setFlags(paint.getFlags()); 1061 } 1062 if (base.getColor() != paint.getColor()) { 1063 *ptr++ = PaintOp_packOp(kColor_PaintOp); 1064 *ptr++ = paint.getColor(); 1065 base.setColor(paint.getColor()); 1066 } 1067 if (base.getFilterLevel() != paint.getFilterLevel()) { 1068 *ptr++ = PaintOp_packOpData(kFilterLevel_PaintOp, paint.getFilterLevel()); 1069 base.setFilterLevel(paint.getFilterLevel()); 1070 } 1071 if (base.getStyle() != paint.getStyle()) { 1072 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle()); 1073 base.setStyle(paint.getStyle()); 1074 } 1075 if (base.getStrokeJoin() != paint.getStrokeJoin()) { 1076 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin()); 1077 base.setStrokeJoin(paint.getStrokeJoin()); 1078 } 1079 if (base.getStrokeCap() != paint.getStrokeCap()) { 1080 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap()); 1081 base.setStrokeCap(paint.getStrokeCap()); 1082 } 1083 if (base.getStrokeWidth() != paint.getStrokeWidth()) { 1084 *ptr++ = PaintOp_packOp(kWidth_PaintOp); 1085 *ptr++ = castToU32(paint.getStrokeWidth()); 1086 base.setStrokeWidth(paint.getStrokeWidth()); 1087 } 1088 if (base.getStrokeMiter() != paint.getStrokeMiter()) { 1089 *ptr++ = PaintOp_packOp(kMiter_PaintOp); 1090 *ptr++ = castToU32(paint.getStrokeMiter()); 1091 base.setStrokeMiter(paint.getStrokeMiter()); 1092 } 1093 if (base.getTextEncoding() != paint.getTextEncoding()) { 1094 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding()); 1095 base.setTextEncoding(paint.getTextEncoding()); 1096 } 1097 if (base.getHinting() != paint.getHinting()) { 1098 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting()); 1099 base.setHinting(paint.getHinting()); 1100 } 1101 if (base.getTextAlign() != paint.getTextAlign()) { 1102 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign()); 1103 base.setTextAlign(paint.getTextAlign()); 1104 } 1105 if (base.getTextSize() != paint.getTextSize()) { 1106 *ptr++ = PaintOp_packOp(kTextSize_PaintOp); 1107 *ptr++ = castToU32(paint.getTextSize()); 1108 base.setTextSize(paint.getTextSize()); 1109 } 1110 if (base.getTextScaleX() != paint.getTextScaleX()) { 1111 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp); 1112 *ptr++ = castToU32(paint.getTextScaleX()); 1113 base.setTextScaleX(paint.getTextScaleX()); 1114 } 1115 if (base.getTextSkewX() != paint.getTextSkewX()) { 1116 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp); 1117 *ptr++ = castToU32(paint.getTextSkewX()); 1118 base.setTextSkewX(paint.getTextSkewX()); 1119 } 1120 1121 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { 1122 if (isCrossProcess(fFlags)) { 1123 uint32_t id = this->getTypefaceID(paint.getTypeface()); 1124 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); 1125 } else if (this->needOpBytes(sizeof(void*))) { 1126 // Add to the set for ref counting. 1127 fTypefaceSet.add(paint.getTypeface()); 1128 // It is safe to write the typeface to the stream before the rest 1129 // of the paint unless we ever send a kReset_PaintOp, which we 1130 // currently never do. 1131 this->writeOp(kSetTypeface_DrawOp); 1132 fWriter.writePtr(paint.getTypeface()); 1133 } 1134 base.setTypeface(paint.getTypeface()); 1135 } 1136 1137 // This is a new paint, so all old flats can be safely purged, if necessary. 1138 fFlattenableHeap.markAllFlatsSafeToDelete(); 1139 for (int i = 0; i < kCount_PaintFlats; i++) { 1140 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i); 1141 bool replaced = index < 0; 1142 if (replaced) { 1143 index = ~index; 1144 } 1145 // Store the index of any flat that needs to be kept. 0 means no flat. 1146 if (index > 0) { 1147 fFlattenableHeap.markFlatForKeeping(index); 1148 } 1149 SkASSERT(index >= 0 && index <= fFlatDictionary.count()); 1150 if (index != fCurrFlatIndex[i] || replaced) { 1151 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index); 1152 fCurrFlatIndex[i] = index; 1153 } 1154 } 1155 1156 size_t size = (char*)ptr - (char*)storage; 1157 if (size && this->needOpBytes(size)) { 1158 this->writeOp(kPaintOp_DrawOp, 0, SkToU32(size)); 1159 fWriter.write(storage, size); 1160 for (size_t i = 0; i < size/4; i++) { 1161 // SkDebugf("[%d] %08X\n", i, storage[i]); 1162 } 1163 } 1164 1165 // 1166 // Do these after we've written kPaintOp_DrawOp 1167 1168 if (base.getAnnotation() != paint.getAnnotation()) { 1169 if (NULL == paint.getAnnotation()) { 1170 if (this->needOpBytes()) { 1171 this->writeOp(kSetAnnotation_DrawOp, 0, 0); 1172 } 1173 } else { 1174 SkWriteBuffer buffer; 1175 paint.getAnnotation()->writeToBuffer(buffer); 1176 const size_t size = buffer.bytesWritten(); 1177 if (this->needOpBytes(size)) { 1178 this->writeOp(kSetAnnotation_DrawOp, 0, SkToU32(size)); 1179 buffer.writeToMemory(fWriter.reserve(size)); 1180 } 1181 } 1182 base.setAnnotation(paint.getAnnotation()); 1183 } 1184 } 1185 1186 /////////////////////////////////////////////////////////////////////////////// 1187 1188 #include "SkGPipe.h" 1189 1190 SkGPipeController::~SkGPipeController() { 1191 SkSafeUnref(fCanvas); 1192 } 1193 1194 void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) { 1195 SkRefCnt_SafeAssign(fCanvas, canvas); 1196 } 1197 1198 /////////////////////////////////////////////////////////////////////////////// 1199 1200 SkGPipeWriter::SkGPipeWriter() 1201 : fWriter(0) { 1202 fCanvas = NULL; 1203 } 1204 1205 SkGPipeWriter::~SkGPipeWriter() { 1206 this->endRecording(); 1207 } 1208 1209 SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags, 1210 uint32_t width, uint32_t height) { 1211 if (NULL == fCanvas) { 1212 fWriter.reset(NULL, 0); 1213 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height)); 1214 } 1215 controller->setCanvas(fCanvas); 1216 return fCanvas; 1217 } 1218 1219 void SkGPipeWriter::endRecording() { 1220 if (fCanvas) { 1221 fCanvas->finish(true); 1222 fCanvas->unref(); 1223 fCanvas = NULL; 1224 } 1225 } 1226 1227 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) { 1228 if (fCanvas) { 1229 fCanvas->flushRecording(detachCurrentBlock); 1230 } 1231 } 1232 1233 size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) { 1234 if (fCanvas) { 1235 return fCanvas->freeMemoryIfPossible(bytesToFree); 1236 } 1237 return 0; 1238 } 1239 1240 size_t SkGPipeWriter::storageAllocatedForRecording() const { 1241 return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording(); 1242 } 1243 1244 /////////////////////////////////////////////////////////////////////////////// 1245 1246 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { 1247 SkASSERT(canvas != NULL); 1248 fCanvas = canvas; 1249 fCanvas->ref(); 1250 } 1251 1252 BitmapShuttle::~BitmapShuttle() { 1253 this->removeCanvas(); 1254 } 1255 1256 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { 1257 SkASSERT(fCanvas != NULL); 1258 return fCanvas->shuttleBitmap(bitmap, slot); 1259 } 1260 1261 void BitmapShuttle::removeCanvas() { 1262 if (NULL == fCanvas) { 1263 return; 1264 } 1265 fCanvas->unref(); 1266 fCanvas = NULL; 1267 } 1268