SkGPipeWrite.cpp revision ed9806f5c972513d4141c9d1b5a04ab78b3af4cb
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 32enum { 33 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector) 34}; 35 36static bool isCrossProcess(uint32_t flags) { 37 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag); 38} 39 40static 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 56static 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(size); 63 SkAutoDataUnref data(stream.copyToData()); 64 writer->writePad(data->data(), size); 65 } 66 return 4 + SkAlign4(size); 67} 68 69/////////////////////////////////////////////////////////////////////////////// 70 71class FlattenableHeap : public SkFlatController { 72public: 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 106private: 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 116void 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 124void* FlattenableHeap::allocThrow(size_t bytes) { 125 void* ptr = sk_malloc_throw(bytes); 126 *fPointers.append() = ptr; 127 return ptr; 128} 129 130const 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 155struct 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}; 161typedef 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 */ 169class BitmapShuttle : public SkBitmapHeap::ExternalStorage { 170public: 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 183private: 184 SkGPipeCanvas* fCanvas; 185}; 186 187/////////////////////////////////////////////////////////////////////////////// 188 189class SkGPipeCanvas : public SkCanvas { 190public: 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 int save(SaveFlags) SK_OVERRIDE; 233 virtual int saveLayer(const SkRect* bounds, const SkPaint*, 234 SaveFlags) SK_OVERRIDE; 235 virtual void restore() SK_OVERRIDE; 236 virtual bool isDrawingToLayer() const SK_OVERRIDE; 237 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE; 238 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE; 239 virtual bool rotate(SkScalar degrees) SK_OVERRIDE; 240 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE; 241 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE; 242 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE; 243 virtual bool clipRect(const SkRect&, SkRegion::Op op, bool doAntiAlias = false) SK_OVERRIDE; 244 virtual bool clipRRect(const SkRRect&, SkRegion::Op op, bool doAntiAlias = false) SK_OVERRIDE; 245 virtual bool clipPath(const SkPath& path, SkRegion::Op op, 246 bool doAntiAlias = false) SK_OVERRIDE; 247 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE; 248 virtual void clear(SkColor) SK_OVERRIDE; 249 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; 250 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[], 251 const SkPaint&) SK_OVERRIDE; 252 virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; 253 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE; 254 virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE; 255 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE; 256 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 257 const SkPaint*) SK_OVERRIDE; 258 virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, 259 const SkRect& dst, const SkPaint* paint, 260 DrawBitmapRectFlags flags) SK_OVERRIDE; 261 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 262 const SkPaint*) SK_OVERRIDE; 263 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 264 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE; 265 virtual void drawSprite(const SkBitmap&, int left, int top, 266 const SkPaint*) SK_OVERRIDE; 267 virtual void drawText(const void* text, size_t byteLength, SkScalar x, 268 SkScalar y, const SkPaint&) SK_OVERRIDE; 269 virtual void drawPosText(const void* text, size_t byteLength, 270 const SkPoint pos[], const SkPaint&) SK_OVERRIDE; 271 virtual void drawPosTextH(const void* text, size_t byteLength, 272 const SkScalar xpos[], SkScalar constY, 273 const SkPaint&) SK_OVERRIDE; 274 virtual void drawTextOnPath(const void* text, size_t byteLength, 275 const SkPath& path, const SkMatrix* matrix, 276 const SkPaint&) SK_OVERRIDE; 277 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE; 278 virtual void drawVertices(VertexMode, int vertexCount, 279 const SkPoint vertices[], const SkPoint texs[], 280 const SkColor colors[], SkXfermode*, 281 const uint16_t indices[], int indexCount, 282 const SkPaint&) SK_OVERRIDE; 283 virtual void drawData(const void*, size_t) SK_OVERRIDE; 284 virtual void beginCommentGroup(const char* description) SK_OVERRIDE; 285 virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; 286 virtual void endCommentGroup() SK_OVERRIDE; 287 288 /** 289 * Flatten an SkBitmap to send to the reader, where it will be referenced 290 * according to slot. 291 */ 292 bool shuttleBitmap(const SkBitmap&, int32_t slot); 293 294protected: 295 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE; 296 297private: 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 366void SkGPipeCanvas::flattenFactoryNames() { 367 const char* name; 368 while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) { 369 size_t len = strlen(name); 370 if (this->needOpBytes(len)) { 371 this->writeOp(kDef_Factory_DrawOp); 372 fWriter.writeString(name, len); 373 } 374 } 375} 376 377bool 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 uint32_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 395int 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 429SkGPipeCanvas::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 466SkGPipeCanvas::~SkGPipeCanvas() { 467 this->finish(true); 468 SkSafeUnref(fFactorySet); 469 SkSafeUnref(fBitmapHeap); 470} 471 472bool SkGPipeCanvas::needOpBytes(size_t needed) { 473 if (fDone) { 474 return false; 475 } 476 477 needed += 4; // size of DrawOp atom 478 if (fWriter.bytesWritten() + needed > fBlockSize) { 479 // Before we wipe out any data that has already been written, read it 480 // out. 481 this->doNotify(); 482 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed); 483 void* block = fController->requestBlock(blockSize, &fBlockSize); 484 if (NULL == block) { 485 // Do not notify the readers, which would call this function again. 486 this->finish(false); 487 return false; 488 } 489 SkASSERT(SkIsAlign4(fBlockSize)); 490 fWriter.reset(block, fBlockSize); 491 fBytesNotified = 0; 492 } 493 return true; 494} 495 496uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { 497 uint32_t id = 0; // 0 means default/null typeface 498 if (face) { 499 id = fTypefaceSet.find(face); 500 if (0 == id) { 501 id = fTypefaceSet.add(face); 502 size_t size = writeTypeface(NULL, face); 503 if (this->needOpBytes(size)) { 504 this->writeOp(kDef_Typeface_DrawOp); 505 writeTypeface(&fWriter, face); 506 } 507 } 508 } 509 return id; 510} 511 512/////////////////////////////////////////////////////////////////////////////// 513 514#define NOTIFY_SETUP(canvas) \ 515 AutoPipeNotify apn(canvas) 516 517int SkGPipeCanvas::save(SaveFlags flags) { 518 NOTIFY_SETUP(this); 519 if (this->needOpBytes()) { 520 this->writeOp(kSave_DrawOp, 0, flags); 521 } 522 return this->INHERITED::save(flags); 523} 524 525int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 526 SaveFlags saveFlags) { 527 NOTIFY_SETUP(this); 528 size_t size = 0; 529 unsigned opFlags = 0; 530 531 if (bounds) { 532 opFlags |= kSaveLayer_HasBounds_DrawOpFlag; 533 size += sizeof(SkRect); 534 } 535 if (paint) { 536 opFlags |= kSaveLayer_HasPaint_DrawOpFlag; 537 this->writePaint(*paint); 538 } 539 540 if (this->needOpBytes(size)) { 541 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags); 542 if (bounds) { 543 fWriter.writeRect(*bounds); 544 } 545 } 546 547 if (kNoSaveLayer == fFirstSaveLayerStackLevel){ 548 fFirstSaveLayerStackLevel = this->getSaveCount(); 549 } 550 // we just pass on the save, so we don't create a layer 551 return this->INHERITED::save(saveFlags); 552} 553 554void SkGPipeCanvas::restore() { 555 NOTIFY_SETUP(this); 556 if (this->needOpBytes()) { 557 this->writeOp(kRestore_DrawOp); 558 } 559 560 this->INHERITED::restore(); 561 562 if (this->getSaveCount() == fFirstSaveLayerStackLevel){ 563 fFirstSaveLayerStackLevel = kNoSaveLayer; 564 } 565} 566 567bool SkGPipeCanvas::isDrawingToLayer() const { 568 return kNoSaveLayer != fFirstSaveLayerStackLevel; 569} 570 571bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) { 572 if (dx || dy) { 573 NOTIFY_SETUP(this); 574 if (this->needOpBytes(2 * sizeof(SkScalar))) { 575 this->writeOp(kTranslate_DrawOp); 576 fWriter.writeScalar(dx); 577 fWriter.writeScalar(dy); 578 } 579 } 580 return this->INHERITED::translate(dx, dy); 581} 582 583bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) { 584 if (sx || sy) { 585 NOTIFY_SETUP(this); 586 if (this->needOpBytes(2 * sizeof(SkScalar))) { 587 this->writeOp(kScale_DrawOp); 588 fWriter.writeScalar(sx); 589 fWriter.writeScalar(sy); 590 } 591 } 592 return this->INHERITED::scale(sx, sy); 593} 594 595bool SkGPipeCanvas::rotate(SkScalar degrees) { 596 if (degrees) { 597 NOTIFY_SETUP(this); 598 if (this->needOpBytes(sizeof(SkScalar))) { 599 this->writeOp(kRotate_DrawOp); 600 fWriter.writeScalar(degrees); 601 } 602 } 603 return this->INHERITED::rotate(degrees); 604} 605 606bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) { 607 if (sx || sy) { 608 NOTIFY_SETUP(this); 609 if (this->needOpBytes(2 * sizeof(SkScalar))) { 610 this->writeOp(kSkew_DrawOp); 611 fWriter.writeScalar(sx); 612 fWriter.writeScalar(sy); 613 } 614 } 615 return this->INHERITED::skew(sx, sy); 616} 617 618bool SkGPipeCanvas::concat(const SkMatrix& matrix) { 619 if (!matrix.isIdentity()) { 620 NOTIFY_SETUP(this); 621 if (this->needOpBytes(matrix.writeToMemory(NULL))) { 622 this->writeOp(kConcat_DrawOp); 623 fWriter.writeMatrix(matrix); 624 } 625 } 626 return this->INHERITED::concat(matrix); 627} 628 629void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) { 630 NOTIFY_SETUP(this); 631 if (this->needOpBytes(matrix.writeToMemory(NULL))) { 632 this->writeOp(kSetMatrix_DrawOp); 633 fWriter.writeMatrix(matrix); 634 } 635 this->INHERITED::setMatrix(matrix); 636} 637 638bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp, 639 bool doAntiAlias) { 640 NOTIFY_SETUP(this); 641 if (this->needOpBytes(sizeof(SkRect))) { 642 unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag; 643 this->writeOp(kClipRect_DrawOp, flags, rgnOp); 644 fWriter.writeRect(rect); 645 } 646 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias); 647} 648 649bool SkGPipeCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op rgnOp, 650 bool doAntiAlias) { 651 NOTIFY_SETUP(this); 652 if (this->needOpBytes(kSizeOfFlatRRect)) { 653 unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag; 654 this->writeOp(kClipRRect_DrawOp, flags, rgnOp); 655 fWriter.writeRRect(rrect); 656 } 657 return this->INHERITED::clipRRect(rrect, rgnOp, doAntiAlias); 658} 659 660bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp, 661 bool doAntiAlias) { 662 NOTIFY_SETUP(this); 663 if (this->needOpBytes(path.writeToMemory(NULL))) { 664 unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag; 665 this->writeOp(kClipPath_DrawOp, flags, rgnOp); 666 fWriter.writePath(path); 667 } 668 // we just pass on the bounds of the path 669 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias); 670} 671 672bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) { 673 NOTIFY_SETUP(this); 674 if (this->needOpBytes(region.writeToMemory(NULL))) { 675 this->writeOp(kClipRegion_DrawOp, 0, rgnOp); 676 fWriter.writeRegion(region); 677 } 678 return this->INHERITED::clipRegion(region, rgnOp); 679} 680 681/////////////////////////////////////////////////////////////////////////////// 682 683void SkGPipeCanvas::clear(SkColor color) { 684 NOTIFY_SETUP(this); 685 unsigned flags = 0; 686 if (color) { 687 flags |= kClear_HasColor_DrawOpFlag; 688 } 689 if (this->needOpBytes(sizeof(SkColor))) { 690 this->writeOp(kDrawClear_DrawOp, flags, 0); 691 if (color) { 692 fWriter.write32(color); 693 } 694 } 695} 696 697void SkGPipeCanvas::drawPaint(const SkPaint& paint) { 698 NOTIFY_SETUP(this); 699 this->writePaint(paint); 700 if (this->needOpBytes()) { 701 this->writeOp(kDrawPaint_DrawOp); 702 } 703} 704 705void SkGPipeCanvas::drawPoints(PointMode mode, size_t count, 706 const SkPoint pts[], const SkPaint& paint) { 707 if (count) { 708 NOTIFY_SETUP(this); 709 this->writePaint(paint); 710 if (this->needOpBytes(4 + count * sizeof(SkPoint))) { 711 this->writeOp(kDrawPoints_DrawOp, mode, 0); 712 fWriter.write32(count); 713 fWriter.write(pts, count * sizeof(SkPoint)); 714 } 715 } 716} 717 718void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) { 719 NOTIFY_SETUP(this); 720 this->writePaint(paint); 721 if (this->needOpBytes(sizeof(SkRect))) { 722 this->writeOp(kDrawOval_DrawOp); 723 fWriter.writeRect(rect); 724 } 725} 726 727void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 728 NOTIFY_SETUP(this); 729 this->writePaint(paint); 730 if (this->needOpBytes(sizeof(SkRect))) { 731 this->writeOp(kDrawRect_DrawOp); 732 fWriter.writeRect(rect); 733 } 734} 735 736void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 737 NOTIFY_SETUP(this); 738 this->writePaint(paint); 739 if (this->needOpBytes(kSizeOfFlatRRect)) { 740 this->writeOp(kDrawRRect_DrawOp); 741 fWriter.writeRRect(rrect); 742 } 743} 744 745void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 746 const SkPaint& paint) { 747 NOTIFY_SETUP(this); 748 this->writePaint(paint); 749 if (this->needOpBytes(kSizeOfFlatRRect * 2)) { 750 this->writeOp(kDrawDRRect_DrawOp); 751 fWriter.writeRRect(outer); 752 fWriter.writeRRect(inner); 753 } 754} 755 756void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 757 NOTIFY_SETUP(this); 758 this->writePaint(paint); 759 if (this->needOpBytes(path.writeToMemory(NULL))) { 760 this->writeOp(kDrawPath_DrawOp); 761 fWriter.writePath(path); 762 } 763} 764 765bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op, 766 unsigned flags, 767 size_t opBytesNeeded, 768 const SkPaint* paint) { 769 if (paint != NULL) { 770 flags |= kDrawBitmap_HasPaint_DrawOpFlag; 771 this->writePaint(*paint); 772 } 773 if (this->needOpBytes(opBytesNeeded)) { 774 SkASSERT(fBitmapHeap != NULL); 775 int32_t bitmapIndex = fBitmapHeap->insert(bm); 776 if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) { 777 return false; 778 } 779 this->writeOp(op, flags, bitmapIndex); 780 return true; 781 } 782 return false; 783} 784 785void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top, 786 const SkPaint* paint) { 787 NOTIFY_SETUP(this); 788 size_t opBytesNeeded = sizeof(SkScalar) * 2; 789 790 if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) { 791 fWriter.writeScalar(left); 792 fWriter.writeScalar(top); 793 } 794} 795 796void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src, 797 const SkRect& dst, const SkPaint* paint, 798 DrawBitmapRectFlags dbmrFlags) { 799 NOTIFY_SETUP(this); 800 size_t opBytesNeeded = sizeof(SkRect); 801 bool hasSrc = src != NULL; 802 unsigned flags; 803 if (hasSrc) { 804 flags = kDrawBitmap_HasSrcRect_DrawOpFlag; 805 opBytesNeeded += sizeof(int32_t) * 4; 806 } else { 807 flags = 0; 808 } 809 if (dbmrFlags & kBleed_DrawBitmapRectFlag) { 810 flags |= kDrawBitmap_Bleed_DrawOpFlag; 811 } 812 813 if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) { 814 if (hasSrc) { 815 fWriter.writeRect(*src); 816 } 817 fWriter.writeRect(dst); 818 } 819} 820 821void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix, 822 const SkPaint* paint) { 823 NOTIFY_SETUP(this); 824 size_t opBytesNeeded = matrix.writeToMemory(NULL); 825 826 if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) { 827 fWriter.writeMatrix(matrix); 828 } 829} 830 831void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center, 832 const SkRect& dst, const SkPaint* paint) { 833 NOTIFY_SETUP(this); 834 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect); 835 836 if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) { 837 fWriter.write32(center.fLeft); 838 fWriter.write32(center.fTop); 839 fWriter.write32(center.fRight); 840 fWriter.write32(center.fBottom); 841 fWriter.writeRect(dst); 842 } 843} 844 845void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top, 846 const SkPaint* paint) { 847 NOTIFY_SETUP(this); 848 size_t opBytesNeeded = sizeof(int32_t) * 2; 849 850 if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) { 851 fWriter.write32(left); 852 fWriter.write32(top); 853 } 854} 855 856void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x, 857 SkScalar y, const SkPaint& paint) { 858 if (byteLength) { 859 NOTIFY_SETUP(this); 860 this->writePaint(paint); 861 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) { 862 this->writeOp(kDrawText_DrawOp); 863 fWriter.write32(byteLength); 864 fWriter.writePad(text, byteLength); 865 fWriter.writeScalar(x); 866 fWriter.writeScalar(y); 867 } 868 } 869} 870 871void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength, 872 const SkPoint pos[], const SkPaint& paint) { 873 if (byteLength) { 874 NOTIFY_SETUP(this); 875 this->writePaint(paint); 876 int count = paint.textToGlyphs(text, byteLength, NULL); 877 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) { 878 this->writeOp(kDrawPosText_DrawOp); 879 fWriter.write32(byteLength); 880 fWriter.writePad(text, byteLength); 881 fWriter.write32(count); 882 fWriter.write(pos, count * sizeof(SkPoint)); 883 } 884 } 885} 886 887void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength, 888 const SkScalar xpos[], SkScalar constY, 889 const SkPaint& paint) { 890 if (byteLength) { 891 NOTIFY_SETUP(this); 892 this->writePaint(paint); 893 int count = paint.textToGlyphs(text, byteLength, NULL); 894 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) { 895 this->writeOp(kDrawPosTextH_DrawOp); 896 fWriter.write32(byteLength); 897 fWriter.writePad(text, byteLength); 898 fWriter.write32(count); 899 fWriter.write(xpos, count * sizeof(SkScalar)); 900 fWriter.writeScalar(constY); 901 } 902 } 903} 904 905void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength, 906 const SkPath& path, const SkMatrix* matrix, 907 const SkPaint& paint) { 908 if (byteLength) { 909 NOTIFY_SETUP(this); 910 unsigned flags = 0; 911 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL); 912 if (matrix) { 913 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag; 914 size += matrix->writeToMemory(NULL); 915 } 916 this->writePaint(paint); 917 if (this->needOpBytes(size)) { 918 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0); 919 920 fWriter.write32(byteLength); 921 fWriter.writePad(text, byteLength); 922 923 fWriter.writePath(path); 924 if (matrix) { 925 fWriter.writeMatrix(*matrix); 926 } 927 } 928 } 929} 930 931void SkGPipeCanvas::drawPicture(SkPicture& picture) { 932 // we want to playback the picture into individual draw calls 933 this->INHERITED::drawPicture(picture); 934} 935 936void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount, 937 const SkPoint vertices[], const SkPoint texs[], 938 const SkColor colors[], SkXfermode* xfer, 939 const uint16_t indices[], int indexCount, 940 const SkPaint& paint) { 941 if (0 == vertexCount) { 942 return; 943 } 944 945 NOTIFY_SETUP(this); 946 size_t size = 4 + vertexCount * sizeof(SkPoint); 947 this->writePaint(paint); 948 unsigned flags = 0; 949 if (texs) { 950 flags |= kDrawVertices_HasTexs_DrawOpFlag; 951 size += vertexCount * sizeof(SkPoint); 952 } 953 if (colors) { 954 flags |= kDrawVertices_HasColors_DrawOpFlag; 955 size += vertexCount * sizeof(SkColor); 956 } 957 if (indices && indexCount > 0) { 958 flags |= kDrawVertices_HasIndices_DrawOpFlag; 959 size += 4 + SkAlign4(indexCount * sizeof(uint16_t)); 960 } 961 if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) { 962 flags |= kDrawVertices_HasXfermode_DrawOpFlag; 963 size += sizeof(int32_t); // mode enum 964 } 965 966 if (this->needOpBytes(size)) { 967 this->writeOp(kDrawVertices_DrawOp, flags, 0); 968 fWriter.write32(vmode); 969 fWriter.write32(vertexCount); 970 fWriter.write(vertices, vertexCount * sizeof(SkPoint)); 971 if (texs) { 972 fWriter.write(texs, vertexCount * sizeof(SkPoint)); 973 } 974 if (colors) { 975 fWriter.write(colors, vertexCount * sizeof(SkColor)); 976 } 977 if (flags & kDrawVertices_HasXfermode_DrawOpFlag) { 978 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; 979 (void)xfer->asMode(&mode); 980 fWriter.write32(mode); 981 } 982 if (indices && indexCount > 0) { 983 fWriter.write32(indexCount); 984 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); 985 } 986 } 987} 988 989void SkGPipeCanvas::drawData(const void* ptr, size_t size) { 990 if (size && ptr) { 991 NOTIFY_SETUP(this); 992 unsigned data = 0; 993 if (size < (1 << DRAWOPS_DATA_BITS)) { 994 data = (unsigned)size; 995 } 996 if (this->needOpBytes(4 + SkAlign4(size))) { 997 this->writeOp(kDrawData_DrawOp, 0, data); 998 if (0 == data) { 999 fWriter.write32(size); 1000 } 1001 fWriter.writePad(ptr, size); 1002 } 1003 } 1004} 1005 1006void SkGPipeCanvas::beginCommentGroup(const char* description) { 1007 // ignore for now 1008} 1009 1010void SkGPipeCanvas::addComment(const char* kywd, const char* value) { 1011 // ignore for now 1012} 1013 1014void SkGPipeCanvas::endCommentGroup() { 1015 // ignore for now 1016} 1017 1018void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) { 1019 doNotify(); 1020 if (detachCurrentBlock) { 1021 // force a new block to be requested for the next recorded command 1022 fBlockSize = 0; 1023 } 1024} 1025 1026size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) { 1027 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree); 1028} 1029 1030/////////////////////////////////////////////////////////////////////////////// 1031 1032template <typename T> uint32_t castToU32(T value) { 1033 union { 1034 T fSrc; 1035 uint32_t fDst; 1036 } data; 1037 data.fSrc = value; 1038 return data.fDst; 1039} 1040 1041void SkGPipeCanvas::writePaint(const SkPaint& paint) { 1042 if (fDone) { 1043 return; 1044 } 1045 SkPaint& base = fPaint; 1046 uint32_t storage[32]; 1047 uint32_t* ptr = storage; 1048 1049 if (base.getFlags() != paint.getFlags()) { 1050 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags()); 1051 base.setFlags(paint.getFlags()); 1052 } 1053 if (base.getColor() != paint.getColor()) { 1054 *ptr++ = PaintOp_packOp(kColor_PaintOp); 1055 *ptr++ = paint.getColor(); 1056 base.setColor(paint.getColor()); 1057 } 1058 if (base.getStyle() != paint.getStyle()) { 1059 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle()); 1060 base.setStyle(paint.getStyle()); 1061 } 1062 if (base.getStrokeJoin() != paint.getStrokeJoin()) { 1063 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin()); 1064 base.setStrokeJoin(paint.getStrokeJoin()); 1065 } 1066 if (base.getStrokeCap() != paint.getStrokeCap()) { 1067 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap()); 1068 base.setStrokeCap(paint.getStrokeCap()); 1069 } 1070 if (base.getStrokeWidth() != paint.getStrokeWidth()) { 1071 *ptr++ = PaintOp_packOp(kWidth_PaintOp); 1072 *ptr++ = castToU32(paint.getStrokeWidth()); 1073 base.setStrokeWidth(paint.getStrokeWidth()); 1074 } 1075 if (base.getStrokeMiter() != paint.getStrokeMiter()) { 1076 *ptr++ = PaintOp_packOp(kMiter_PaintOp); 1077 *ptr++ = castToU32(paint.getStrokeMiter()); 1078 base.setStrokeMiter(paint.getStrokeMiter()); 1079 } 1080 if (base.getTextEncoding() != paint.getTextEncoding()) { 1081 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding()); 1082 base.setTextEncoding(paint.getTextEncoding()); 1083 } 1084 if (base.getHinting() != paint.getHinting()) { 1085 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting()); 1086 base.setHinting(paint.getHinting()); 1087 } 1088 if (base.getTextAlign() != paint.getTextAlign()) { 1089 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign()); 1090 base.setTextAlign(paint.getTextAlign()); 1091 } 1092 if (base.getTextSize() != paint.getTextSize()) { 1093 *ptr++ = PaintOp_packOp(kTextSize_PaintOp); 1094 *ptr++ = castToU32(paint.getTextSize()); 1095 base.setTextSize(paint.getTextSize()); 1096 } 1097 if (base.getTextScaleX() != paint.getTextScaleX()) { 1098 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp); 1099 *ptr++ = castToU32(paint.getTextScaleX()); 1100 base.setTextScaleX(paint.getTextScaleX()); 1101 } 1102 if (base.getTextSkewX() != paint.getTextSkewX()) { 1103 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp); 1104 *ptr++ = castToU32(paint.getTextSkewX()); 1105 base.setTextSkewX(paint.getTextSkewX()); 1106 } 1107 1108 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { 1109 if (isCrossProcess(fFlags)) { 1110 uint32_t id = this->getTypefaceID(paint.getTypeface()); 1111 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); 1112 } else if (this->needOpBytes(sizeof(void*))) { 1113 // Add to the set for ref counting. 1114 fTypefaceSet.add(paint.getTypeface()); 1115 // It is safe to write the typeface to the stream before the rest 1116 // of the paint unless we ever send a kReset_PaintOp, which we 1117 // currently never do. 1118 this->writeOp(kSetTypeface_DrawOp); 1119 fWriter.writePtr(paint.getTypeface()); 1120 } 1121 base.setTypeface(paint.getTypeface()); 1122 } 1123 1124 // This is a new paint, so all old flats can be safely purged, if necessary. 1125 fFlattenableHeap.markAllFlatsSafeToDelete(); 1126 for (int i = 0; i < kCount_PaintFlats; i++) { 1127 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i); 1128 bool replaced = index < 0; 1129 if (replaced) { 1130 index = ~index; 1131 } 1132 // Store the index of any flat that needs to be kept. 0 means no flat. 1133 if (index > 0) { 1134 fFlattenableHeap.markFlatForKeeping(index); 1135 } 1136 SkASSERT(index >= 0 && index <= fFlatDictionary.count()); 1137 if (index != fCurrFlatIndex[i] || replaced) { 1138 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index); 1139 fCurrFlatIndex[i] = index; 1140 } 1141 } 1142 1143 size_t size = (char*)ptr - (char*)storage; 1144 if (size && this->needOpBytes(size)) { 1145 this->writeOp(kPaintOp_DrawOp, 0, size); 1146 fWriter.write(storage, size); 1147 for (size_t i = 0; i < size/4; i++) { 1148// SkDebugf("[%d] %08X\n", i, storage[i]); 1149 } 1150 } 1151 1152 // 1153 // Do these after we've written kPaintOp_DrawOp 1154 1155 if (base.getAnnotation() != paint.getAnnotation()) { 1156 if (NULL == paint.getAnnotation()) { 1157 if (this->needOpBytes()) { 1158 this->writeOp(kSetAnnotation_DrawOp, 0, 0); 1159 } 1160 } else { 1161 SkWriteBuffer buffer; 1162 paint.getAnnotation()->writeToBuffer(buffer); 1163 const size_t size = buffer.bytesWritten(); 1164 if (this->needOpBytes(size)) { 1165 this->writeOp(kSetAnnotation_DrawOp, 0, size); 1166 buffer.writeToMemory(fWriter.reserve(size)); 1167 } 1168 } 1169 base.setAnnotation(paint.getAnnotation()); 1170 } 1171} 1172 1173/////////////////////////////////////////////////////////////////////////////// 1174 1175#include "SkGPipe.h" 1176 1177SkGPipeController::~SkGPipeController() { 1178 SkSafeUnref(fCanvas); 1179} 1180 1181void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) { 1182 SkRefCnt_SafeAssign(fCanvas, canvas); 1183} 1184 1185/////////////////////////////////////////////////////////////////////////////// 1186 1187SkGPipeWriter::SkGPipeWriter() 1188: fWriter(0) { 1189 fCanvas = NULL; 1190} 1191 1192SkGPipeWriter::~SkGPipeWriter() { 1193 this->endRecording(); 1194} 1195 1196SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags, 1197 uint32_t width, uint32_t height) { 1198 if (NULL == fCanvas) { 1199 fWriter.reset(NULL, 0); 1200 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height)); 1201 } 1202 controller->setCanvas(fCanvas); 1203 return fCanvas; 1204} 1205 1206void SkGPipeWriter::endRecording() { 1207 if (fCanvas) { 1208 fCanvas->finish(true); 1209 fCanvas->unref(); 1210 fCanvas = NULL; 1211 } 1212} 1213 1214void SkGPipeWriter::flushRecording(bool detachCurrentBlock) { 1215 if (fCanvas) { 1216 fCanvas->flushRecording(detachCurrentBlock); 1217 } 1218} 1219 1220size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) { 1221 if (fCanvas) { 1222 return fCanvas->freeMemoryIfPossible(bytesToFree); 1223 } 1224 return 0; 1225} 1226 1227size_t SkGPipeWriter::storageAllocatedForRecording() const { 1228 return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording(); 1229} 1230 1231/////////////////////////////////////////////////////////////////////////////// 1232 1233BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { 1234 SkASSERT(canvas != NULL); 1235 fCanvas = canvas; 1236 fCanvas->ref(); 1237} 1238 1239BitmapShuttle::~BitmapShuttle() { 1240 this->removeCanvas(); 1241} 1242 1243bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { 1244 SkASSERT(fCanvas != NULL); 1245 return fCanvas->shuttleBitmap(bitmap, slot); 1246} 1247 1248void BitmapShuttle::removeCanvas() { 1249 if (NULL == fCanvas) { 1250 return; 1251 } 1252 fCanvas->unref(); 1253 fCanvas = NULL; 1254} 1255