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