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