SkDeferredCanvas.cpp revision eeaf47f638dbab2cbe3306e099d93dc6244b25a5
1 2/* 3 * Copyright 2012 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 "SkDeferredCanvas.h" 10 11#include "SkChunkAlloc.h" 12#include "SkColorFilter.h" 13#include "SkDevice.h" 14#include "SkDrawFilter.h" 15#include "SkGPipe.h" 16#include "SkPaint.h" 17#include "SkShader.h" 18 19enum { 20 // Deferred canvas will auto-flush when recording reaches this limit 21 kDefaultMaxRecordingStorageBytes = 64*1024*1024, 22}; 23 24enum PlaybackMode { 25 kNormal_PlaybackMode, 26 kSilent_PlaybackMode, 27}; 28 29namespace { 30bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint) { 31 if (bitmap && bitmap->getTexture() && !bitmap->isImmutable()) { 32 return true; 33 } 34 if (paint) { 35 SkShader* shader = paint->getShader(); 36 // Here we detect the case where the shader is an SkBitmapProcShader 37 // with a gpu texture attached. Checking this without RTTI 38 // requires making the assumption that only gradient shaders 39 // and SkBitmapProcShader implement asABitmap(). The following 40 // code may need to be revised if that assumption is ever broken. 41 if (shader && !shader->asAGradient(NULL)) { 42 SkBitmap bm; 43 if (shader->asABitmap(&bm, NULL, NULL) && 44 NULL != bm.getTexture()) { 45 return true; 46 } 47 } 48 } 49 return false; 50} 51} 52 53class AutoImmediateDrawIfNeeded { 54public: 55 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap, 56 const SkPaint* paint) { 57 this->init(canvas, bitmap, paint); 58 } 59 60 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) { 61 this->init(canvas, NULL, paint); 62 } 63 64 ~AutoImmediateDrawIfNeeded() { 65 if (fCanvas) { 66 fCanvas->setDeferredDrawing(true); 67 } 68 } 69private: 70 void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint) 71 { 72 if (canvas.isDeferredDrawing() && shouldDrawImmediately(bitmap, paint)) { 73 canvas.setDeferredDrawing(false); 74 fCanvas = &canvas; 75 } else { 76 fCanvas = NULL; 77 } 78 } 79 80 SkDeferredCanvas* fCanvas; 81}; 82 83namespace { 84 85bool isPaintOpaque(const SkPaint* paint, 86 const SkBitmap* bmpReplacesShader = NULL) { 87 // TODO: SkXfermode should have a virtual isOpaque method, which would 88 // make it possible to test modes that do not have a Coeff representation. 89 90 if (!paint) { 91 return bmpReplacesShader ? bmpReplacesShader->isOpaque() : true; 92 } 93 94 SkXfermode::Coeff srcCoeff, dstCoeff; 95 if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){ 96 switch (dstCoeff) { 97 case SkXfermode::kZero_Coeff: 98 return true; 99 case SkXfermode::kISA_Coeff: 100 if (paint->getAlpha() != 255) { 101 break; 102 } 103 if (bmpReplacesShader) { 104 if (!bmpReplacesShader->isOpaque()) { 105 break; 106 } 107 } else if (paint->getShader() && !paint->getShader()->isOpaque()) { 108 break; 109 } 110 if (paint->getColorFilter() && 111 ((paint->getColorFilter()->getFlags() & 112 SkColorFilter::kAlphaUnchanged_Flag) == 0)) { 113 break; 114 } 115 return true; 116 case SkXfermode::kSA_Coeff: 117 if (paint->getAlpha() != 0) { 118 break; 119 } 120 if (paint->getColorFilter() && 121 ((paint->getColorFilter()->getFlags() & 122 SkColorFilter::kAlphaUnchanged_Flag) == 0)) { 123 break; 124 } 125 return true; 126 case SkXfermode::kSC_Coeff: 127 if (paint->getColor() != 0) { // all components must be 0 128 break; 129 } 130 if (bmpReplacesShader || paint->getShader()) { 131 break; 132 } 133 if (paint->getColorFilter() && ( 134 (paint->getColorFilter()->getFlags() & 135 SkColorFilter::kAlphaUnchanged_Flag) == 0)) { 136 break; 137 } 138 return true; 139 default: 140 break; 141 } 142 } 143 return false; 144} 145 146} // unnamed namespace 147 148//----------------------------------------------------------------------------- 149// DeferredPipeController 150//----------------------------------------------------------------------------- 151 152class DeferredPipeController : public SkGPipeController { 153public: 154 DeferredPipeController(); 155 void setPlaybackCanvas(SkCanvas*); 156 virtual ~DeferredPipeController(); 157 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE; 158 virtual void notifyWritten(size_t bytes) SK_OVERRIDE; 159 void playback(bool silent); 160 bool hasRecorded() const { return fAllocator.blockCount() != 0; } 161 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); } 162private: 163 enum { 164 kMinBlockSize = 4096 165 }; 166 struct PipeBlock { 167 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; } 168 void* fBlock; 169 size_t fSize; 170 }; 171 void* fBlock; 172 size_t fBytesWritten; 173 SkChunkAlloc fAllocator; 174 SkTDArray<PipeBlock> fBlockList; 175 SkGPipeReader fReader; 176}; 177 178DeferredPipeController::DeferredPipeController() : 179 fAllocator(kMinBlockSize) { 180 fBlock = NULL; 181 fBytesWritten = 0; 182} 183 184DeferredPipeController::~DeferredPipeController() { 185 fAllocator.reset(); 186} 187 188void DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) { 189 fReader.setCanvas(canvas); 190} 191 192void* DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) { 193 if (fBlock) { 194 // Save the previous block for later 195 PipeBlock previousBloc(fBlock, fBytesWritten); 196 fBlockList.push(previousBloc); 197 } 198 int32_t blockSize = SkMax32(minRequest, kMinBlockSize); 199 fBlock = fAllocator.allocThrow(blockSize); 200 fBytesWritten = 0; 201 *actual = blockSize; 202 return fBlock; 203} 204 205void DeferredPipeController::notifyWritten(size_t bytes) { 206 fBytesWritten += bytes; 207} 208 209void DeferredPipeController::playback(bool silent) { 210 uint32_t flags = silent ? SkGPipeReader::kSilent_PlaybackFlag : 0; 211 for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) { 212 fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize, 213 flags); 214 } 215 fBlockList.reset(); 216 217 if (fBlock) { 218 fReader.playback(fBlock, fBytesWritten, flags); 219 fBlock = NULL; 220 } 221 222 // Release all allocated blocks 223 fAllocator.reset(); 224} 225 226//----------------------------------------------------------------------------- 227// DeferredDevice 228//----------------------------------------------------------------------------- 229class DeferredDevice : public SkDevice { 230public: 231 DeferredDevice(SkDevice* immediateDevice, 232 SkDeferredCanvas::NotificationClient* notificationClient = NULL); 233 ~DeferredDevice(); 234 235 void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient); 236 SkCanvas* recordingCanvas(); 237 SkCanvas* immediateCanvas() const {return fImmediateCanvas;} 238 SkDevice* immediateDevice() const {return fImmediateDevice;} 239 bool isFreshFrame(); 240 size_t storageAllocatedForRecording() const; 241 size_t freeMemoryIfPossible(size_t bytesToFree); 242 void flushPendingCommands(PlaybackMode); 243 void skipPendingCommands(); 244 void setMaxRecordingStorage(size_t); 245 void recordedDrawCommand(); 246 247 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE; 248 virtual int width() const SK_OVERRIDE; 249 virtual int height() const SK_OVERRIDE; 250 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE; 251 252 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, 253 int width, int height, 254 bool isOpaque, 255 Usage usage) SK_OVERRIDE; 256 257 virtual void writePixels(const SkBitmap& bitmap, int x, int y, 258 SkCanvas::Config8888 config8888) SK_OVERRIDE; 259 260protected: 261 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE; 262 virtual bool onReadPixels(const SkBitmap& bitmap, 263 int x, int y, 264 SkCanvas::Config8888 config8888) SK_OVERRIDE; 265 266 // The following methods are no-ops on a deferred device 267 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) 268 SK_OVERRIDE 269 {return false;} 270 virtual void setMatrixClip(const SkMatrix&, const SkRegion&, 271 const SkClipStack&) SK_OVERRIDE 272 {} 273 274 // None of the following drawing methods should ever get called on the 275 // deferred device 276 virtual void clear(SkColor color) 277 {SkASSERT(0);} 278 virtual void drawPaint(const SkDraw&, const SkPaint& paint) 279 {SkASSERT(0);} 280 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, 281 size_t count, const SkPoint[], 282 const SkPaint& paint) 283 {SkASSERT(0);} 284 virtual void drawRect(const SkDraw&, const SkRect& r, 285 const SkPaint& paint) 286 {SkASSERT(0);} 287 virtual void drawPath(const SkDraw&, const SkPath& path, 288 const SkPaint& paint, 289 const SkMatrix* prePathMatrix = NULL, 290 bool pathIsMutable = false) 291 {SkASSERT(0);} 292 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, 293 const SkIRect* srcRectOrNull, 294 const SkMatrix& matrix, const SkPaint& paint) 295 {SkASSERT(0);} 296 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 297 int x, int y, const SkPaint& paint) 298 {SkASSERT(0);} 299 virtual void drawText(const SkDraw&, const void* text, size_t len, 300 SkScalar x, SkScalar y, const SkPaint& paint) 301 {SkASSERT(0);} 302 virtual void drawPosText(const SkDraw&, const void* text, size_t len, 303 const SkScalar pos[], SkScalar constY, 304 int scalarsPerPos, const SkPaint& paint) 305 {SkASSERT(0);} 306 virtual void drawTextOnPath(const SkDraw&, const void* text, 307 size_t len, const SkPath& path, 308 const SkMatrix* matrix, 309 const SkPaint& paint) 310 {SkASSERT(0);} 311 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, 312 size_t len, const SkPoint pos[], 313 const SkPaint& paint, 314 const SkPath& path, 315 const SkMatrix* matrix) 316 {SkASSERT(0);} 317 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, 318 int vertexCount, const SkPoint verts[], 319 const SkPoint texs[], const SkColor colors[], 320 SkXfermode* xmode, const uint16_t indices[], 321 int indexCount, const SkPaint& paint) 322 {SkASSERT(0);} 323 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, 324 const SkPaint&) 325 {SkASSERT(0);} 326private: 327 virtual void flush(); 328 329 void beginRecording(); 330 331 DeferredPipeController fPipeController; 332 SkGPipeWriter fPipeWriter; 333 SkDevice* fImmediateDevice; 334 SkCanvas* fImmediateCanvas; 335 SkCanvas* fRecordingCanvas; 336 SkDeferredCanvas::NotificationClient* fNotificationClient; 337 bool fFreshFrame; 338 size_t fMaxRecordingStorageBytes; 339 size_t fPreviousStorageAllocated; 340}; 341 342DeferredDevice::DeferredDevice( 343 SkDevice* immediateDevice, SkDeferredCanvas::NotificationClient* notificationClient) : 344 SkDevice(SkBitmap::kNo_Config, immediateDevice->width(), 345 immediateDevice->height(), immediateDevice->isOpaque()) 346 , fRecordingCanvas(NULL) 347 , fFreshFrame(true) 348 , fPreviousStorageAllocated(0){ 349 350 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes; 351 fNotificationClient = notificationClient; 352 fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas 353 fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice)); 354 fPipeController.setPlaybackCanvas(fImmediateCanvas); 355 this->beginRecording(); 356} 357 358DeferredDevice::~DeferredDevice() { 359 this->flushPendingCommands(kSilent_PlaybackMode); 360 SkSafeUnref(fImmediateCanvas); 361} 362 363void DeferredDevice::setMaxRecordingStorage(size_t maxStorage) { 364 fMaxRecordingStorageBytes = maxStorage; 365 this->recordingCanvas(); // Accessing the recording canvas applies the new limit. 366} 367 368void DeferredDevice::beginRecording() { 369 SkASSERT(NULL == fRecordingCanvas); 370 fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0, 371 fImmediateDevice->width(), fImmediateDevice->height()); 372} 373 374void DeferredDevice::setNotificationClient( 375 SkDeferredCanvas::NotificationClient* notificationClient) { 376 fNotificationClient = notificationClient; 377} 378 379void DeferredDevice::skipPendingCommands() { 380 if (!fRecordingCanvas->isDrawingToLayer() && fPipeController.hasRecorded()) { 381 fFreshFrame = true; 382 flushPendingCommands(kSilent_PlaybackMode); 383 } 384} 385 386bool DeferredDevice::isFreshFrame() { 387 bool ret = fFreshFrame; 388 fFreshFrame = false; 389 return ret; 390} 391 392void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) { 393 if (!fPipeController.hasRecorded()) { 394 return; 395 } 396 if (playbackMode == kNormal_PlaybackMode && fNotificationClient) { 397 fNotificationClient->prepareForDraw(); 398 } 399 fPipeWriter.flushRecording(true); 400 fPipeController.playback(playbackMode); 401 if (playbackMode == kNormal_PlaybackMode && fNotificationClient) { 402 fNotificationClient->flushedDrawCommands(); 403 } 404 fPreviousStorageAllocated = storageAllocatedForRecording(); 405} 406 407void DeferredDevice::flush() { 408 this->flushPendingCommands(kNormal_PlaybackMode); 409 fImmediateCanvas->flush(); 410} 411 412size_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) { 413 size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree); 414 fPreviousStorageAllocated = storageAllocatedForRecording(); 415 return val; 416} 417 418size_t DeferredDevice::storageAllocatedForRecording() const { 419 return (fPipeController.storageAllocatedForRecording() 420 + fPipeWriter.storageAllocatedForRecording()); 421} 422 423void DeferredDevice::recordedDrawCommand() { 424 size_t storageAllocated = this->storageAllocatedForRecording(); 425 426 if (storageAllocated > fMaxRecordingStorageBytes) { 427 // First, attempt to reduce cache without flushing 428 size_t tryFree = storageAllocated - fMaxRecordingStorageBytes; 429 if (this->freeMemoryIfPossible(tryFree) < tryFree) { 430 // Flush is necessary to free more space. 431 this->flushPendingCommands(kNormal_PlaybackMode); 432 // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes 433 // which could cause a high flushing frequency. 434 this->freeMemoryIfPossible(~0U); 435 } 436 storageAllocated = this->storageAllocatedForRecording(); 437 } 438 439 if (fNotificationClient && 440 storageAllocated != fPreviousStorageAllocated) { 441 fPreviousStorageAllocated = storageAllocated; 442 fNotificationClient->storageAllocatedForRecordingChanged(storageAllocated); 443 } 444} 445 446SkCanvas* DeferredDevice::recordingCanvas() { 447 return fRecordingCanvas; 448} 449 450uint32_t DeferredDevice::getDeviceCapabilities() { 451 return fImmediateDevice->getDeviceCapabilities(); 452} 453 454int DeferredDevice::width() const { 455 return fImmediateDevice->width(); 456} 457 458int DeferredDevice::height() const { 459 return fImmediateDevice->height(); 460} 461 462SkGpuRenderTarget* DeferredDevice::accessRenderTarget() { 463 this->flushPendingCommands(kNormal_PlaybackMode); 464 return fImmediateDevice->accessRenderTarget(); 465} 466 467void DeferredDevice::writePixels(const SkBitmap& bitmap, 468 int x, int y, SkCanvas::Config8888 config8888) { 469 470 if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() && 471 (y + bitmap.height()) >= height()) { 472 this->skipPendingCommands(); 473 } 474 475 if (SkBitmap::kARGB_8888_Config == bitmap.config() && 476 SkCanvas::kNative_Premul_Config8888 != config8888 && 477 kPMColorAlias != config8888) { 478 //Special case config: no deferral 479 this->flushPendingCommands(kNormal_PlaybackMode); 480 fImmediateDevice->writePixels(bitmap, x, y, config8888); 481 return; 482 } 483 484 SkPaint paint; 485 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 486 if (shouldDrawImmediately(&bitmap, NULL)) { 487 this->flushPendingCommands(kNormal_PlaybackMode); 488 fImmediateCanvas->drawSprite(bitmap, x, y, &paint); 489 } else { 490 this->recordingCanvas()->drawSprite(bitmap, x, y, &paint); 491 this->recordedDrawCommand(); 492 493 } 494} 495 496const SkBitmap& DeferredDevice::onAccessBitmap(SkBitmap*) { 497 this->flushPendingCommands(kNormal_PlaybackMode); 498 return fImmediateDevice->accessBitmap(false); 499} 500 501SkDevice* DeferredDevice::onCreateCompatibleDevice( 502 SkBitmap::Config config, int width, int height, bool isOpaque, 503 Usage usage) { 504 505 // Save layer usage not supported, and not required by SkDeferredCanvas. 506 SkASSERT(usage != kSaveLayer_Usage); 507 // Create a compatible non-deferred device. 508 SkAutoTUnref<SkDevice> compatibleDevice 509 (fImmediateDevice->createCompatibleDevice(config, width, height, 510 isOpaque)); 511 return SkNEW_ARGS(DeferredDevice, (compatibleDevice, fNotificationClient)); 512} 513 514bool DeferredDevice::onReadPixels( 515 const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) { 516 this->flushPendingCommands(kNormal_PlaybackMode); 517 return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap), 518 x, y, config8888); 519} 520 521 522SkDeferredCanvas::SkDeferredCanvas() { 523 this->init(); 524} 525 526SkDeferredCanvas::SkDeferredCanvas(SkDevice* device) { 527 this->init(); 528 this->setDevice(device); 529} 530 531void SkDeferredCanvas::init() { 532 fDeferredDrawing = true; // On by default 533} 534 535void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) { 536 this->validate(); 537 this->getDeferredDevice()->setMaxRecordingStorage(maxStorage); 538} 539 540size_t SkDeferredCanvas::storageAllocatedForRecording() const { 541 return this->getDeferredDevice()->storageAllocatedForRecording(); 542} 543 544size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) { 545 return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree); 546} 547 548void SkDeferredCanvas::recordedDrawCommand() { 549 if (fDeferredDrawing) { 550 this->getDeferredDevice()->recordedDrawCommand(); 551 } 552} 553 554void SkDeferredCanvas::validate() const { 555 SkASSERT(this->getDevice()); 556} 557 558SkCanvas* SkDeferredCanvas::drawingCanvas() const { 559 this->validate(); 560 return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() : 561 this->getDeferredDevice()->immediateCanvas(); 562} 563 564SkCanvas* SkDeferredCanvas::immediateCanvas() const { 565 this->validate(); 566 return this->getDeferredDevice()->immediateCanvas(); 567} 568 569DeferredDevice* SkDeferredCanvas::getDeferredDevice() const { 570 return static_cast<DeferredDevice*>(this->getDevice()); 571} 572 573void SkDeferredCanvas::setDeferredDrawing(bool val) { 574 this->validate(); // Must set device before calling this method 575 if (val != fDeferredDrawing) { 576 if (fDeferredDrawing) { 577 // Going live. 578 this->getDeferredDevice()->flushPendingCommands(kNormal_PlaybackMode); 579 } 580 fDeferredDrawing = val; 581 } 582} 583 584bool SkDeferredCanvas::isDeferredDrawing() const { 585 return fDeferredDrawing; 586} 587 588bool SkDeferredCanvas::isFreshFrame() const { 589 return this->getDeferredDevice()->isFreshFrame(); 590} 591 592void SkDeferredCanvas::silentFlush() { 593 if (fDeferredDrawing) { 594 this->getDeferredDevice()->flushPendingCommands(kSilent_PlaybackMode); 595 } 596} 597 598SkDeferredCanvas::~SkDeferredCanvas() { 599} 600 601SkDevice* SkDeferredCanvas::setDevice(SkDevice* device) { 602 this->INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (device)))->unref(); 603 return device; 604} 605 606SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient( 607 NotificationClient* notificationClient) { 608 609 DeferredDevice* deferredDevice = this->getDeferredDevice(); 610 SkASSERT(deferredDevice); 611 if (deferredDevice) { 612 deferredDevice->setNotificationClient(notificationClient); 613 } 614 return notificationClient; 615} 616 617bool SkDeferredCanvas::isFullFrame(const SkRect* rect, 618 const SkPaint* paint) const { 619 SkCanvas* canvas = this->drawingCanvas(); 620 SkISize canvasSize = this->getDeviceSize(); 621 if (rect) { 622 if (!canvas->getTotalMatrix().rectStaysRect()) { 623 return false; // conservative 624 } 625 626 SkRect transformedRect; 627 canvas->getTotalMatrix().mapRect(&transformedRect, *rect); 628 629 if (paint) { 630 SkPaint::Style paintStyle = paint->getStyle(); 631 if (!(paintStyle == SkPaint::kFill_Style || 632 paintStyle == SkPaint::kStrokeAndFill_Style)) { 633 return false; 634 } 635 if (paint->getMaskFilter() || paint->getLooper() 636 || paint->getPathEffect() || paint->getImageFilter()) { 637 return false; // conservative 638 } 639 } 640 641 // The following test holds with AA enabled, and is conservative 642 // by a 0.5 pixel margin with AA disabled 643 if (transformedRect.fLeft > SkIntToScalar(0) || 644 transformedRect.fTop > SkIntToScalar(0) || 645 transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) || 646 transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) { 647 return false; 648 } 649 } 650 651 switch (canvas->getClipType()) { 652 case SkCanvas::kRect_ClipType : 653 { 654 SkIRect bounds; 655 canvas->getClipDeviceBounds(&bounds); 656 if (bounds.fLeft > 0 || bounds.fTop > 0 || 657 bounds.fRight < canvasSize.fWidth || 658 bounds.fBottom < canvasSize.fHeight) 659 return false; 660 } 661 break; 662 case SkCanvas::kComplex_ClipType : 663 return false; // conservative 664 case SkCanvas::kEmpty_ClipType: 665 default: 666 break; 667 }; 668 669 return true; 670} 671 672int SkDeferredCanvas::save(SaveFlags flags) { 673 this->drawingCanvas()->save(flags); 674 int val = this->INHERITED::save(flags); 675 this->recordedDrawCommand(); 676 677 return val; 678} 679 680int SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 681 SaveFlags flags) { 682 this->drawingCanvas()->saveLayer(bounds, paint, flags); 683 int count = this->INHERITED::save(flags); 684 this->clipRectBounds(bounds, flags, NULL); 685 this->recordedDrawCommand(); 686 687 return count; 688} 689 690void SkDeferredCanvas::restore() { 691 this->drawingCanvas()->restore(); 692 this->INHERITED::restore(); 693 this->recordedDrawCommand(); 694} 695 696bool SkDeferredCanvas::isDrawingToLayer() const { 697 return this->drawingCanvas()->isDrawingToLayer(); 698} 699 700bool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) { 701 this->drawingCanvas()->translate(dx, dy); 702 bool val = this->INHERITED::translate(dx, dy); 703 this->recordedDrawCommand(); 704 return val; 705} 706 707bool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) { 708 this->drawingCanvas()->scale(sx, sy); 709 bool val = this->INHERITED::scale(sx, sy); 710 this->recordedDrawCommand(); 711 return val; 712} 713 714bool SkDeferredCanvas::rotate(SkScalar degrees) { 715 this->drawingCanvas()->rotate(degrees); 716 bool val = this->INHERITED::rotate(degrees); 717 this->recordedDrawCommand(); 718 return val; 719} 720 721bool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) { 722 this->drawingCanvas()->skew(sx, sy); 723 bool val = this->INHERITED::skew(sx, sy); 724 this->recordedDrawCommand(); 725 return val; 726} 727 728bool SkDeferredCanvas::concat(const SkMatrix& matrix) { 729 this->drawingCanvas()->concat(matrix); 730 bool val = this->INHERITED::concat(matrix); 731 this->recordedDrawCommand(); 732 return val; 733} 734 735void SkDeferredCanvas::setMatrix(const SkMatrix& matrix) { 736 this->drawingCanvas()->setMatrix(matrix); 737 this->INHERITED::setMatrix(matrix); 738 this->recordedDrawCommand(); 739} 740 741bool SkDeferredCanvas::clipRect(const SkRect& rect, 742 SkRegion::Op op, 743 bool doAntiAlias) { 744 this->drawingCanvas()->clipRect(rect, op, doAntiAlias); 745 bool val = this->INHERITED::clipRect(rect, op, doAntiAlias); 746 this->recordedDrawCommand(); 747 return val; 748} 749 750bool SkDeferredCanvas::clipPath(const SkPath& path, 751 SkRegion::Op op, 752 bool doAntiAlias) { 753 this->drawingCanvas()->clipPath(path, op, doAntiAlias); 754 bool val = this->INHERITED::clipPath(path, op, doAntiAlias); 755 this->recordedDrawCommand(); 756 return val; 757} 758 759bool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn, 760 SkRegion::Op op) { 761 this->drawingCanvas()->clipRegion(deviceRgn, op); 762 bool val = this->INHERITED::clipRegion(deviceRgn, op); 763 this->recordedDrawCommand(); 764 return val; 765} 766 767void SkDeferredCanvas::clear(SkColor color) { 768 // purge pending commands 769 if (fDeferredDrawing) { 770 this->getDeferredDevice()->skipPendingCommands(); 771 } 772 773 this->drawingCanvas()->clear(color); 774 this->recordedDrawCommand(); 775} 776 777void SkDeferredCanvas::drawPaint(const SkPaint& paint) { 778 if (fDeferredDrawing && this->isFullFrame(NULL, &paint) && 779 isPaintOpaque(&paint)) { 780 this->getDeferredDevice()->skipPendingCommands(); 781 } 782 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 783 this->drawingCanvas()->drawPaint(paint); 784 this->recordedDrawCommand(); 785} 786 787void SkDeferredCanvas::drawPoints(PointMode mode, size_t count, 788 const SkPoint pts[], const SkPaint& paint) { 789 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 790 this->drawingCanvas()->drawPoints(mode, count, pts, paint); 791 this->recordedDrawCommand(); 792} 793 794void SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 795 if (fDeferredDrawing && this->isFullFrame(&rect, &paint) && 796 isPaintOpaque(&paint)) { 797 this->getDeferredDevice()->skipPendingCommands(); 798 } 799 800 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 801 this->drawingCanvas()->drawRect(rect, paint); 802 this->recordedDrawCommand(); 803} 804 805void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 806 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 807 this->drawingCanvas()->drawPath(path, paint); 808 this->recordedDrawCommand(); 809} 810 811void SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left, 812 SkScalar top, const SkPaint* paint) { 813 SkRect bitmapRect = SkRect::MakeXYWH(left, top, 814 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 815 if (fDeferredDrawing && 816 this->isFullFrame(&bitmapRect, paint) && 817 isPaintOpaque(paint, &bitmap)) { 818 this->getDeferredDevice()->skipPendingCommands(); 819 } 820 821 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 822 this->drawingCanvas()->drawBitmap(bitmap, left, top, paint); 823 this->recordedDrawCommand(); 824} 825 826void SkDeferredCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, 827 const SkRect* src, 828 const SkRect& dst, 829 const SkPaint* paint) { 830 if (fDeferredDrawing && 831 this->isFullFrame(&dst, paint) && 832 isPaintOpaque(paint, &bitmap)) { 833 this->getDeferredDevice()->skipPendingCommands(); 834 } 835 836 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 837 this->drawingCanvas()->drawBitmapRectToRect(bitmap, src, dst, paint); 838 this->recordedDrawCommand(); 839} 840 841 842void SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap, 843 const SkMatrix& m, 844 const SkPaint* paint) { 845 // TODO: reset recording canvas if paint+bitmap is opaque and clip rect 846 // covers canvas entirely and transformed bitmap covers canvas entirely 847 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 848 this->drawingCanvas()->drawBitmapMatrix(bitmap, m, paint); 849 this->recordedDrawCommand(); 850} 851 852void SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap, 853 const SkIRect& center, const SkRect& dst, 854 const SkPaint* paint) { 855 // TODO: reset recording canvas if paint+bitmap is opaque and clip rect 856 // covers canvas entirely and dst covers canvas entirely 857 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 858 this->drawingCanvas()->drawBitmapNine(bitmap, center, dst, paint); 859 this->recordedDrawCommand(); 860} 861 862void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, 863 const SkPaint* paint) { 864 SkRect bitmapRect = SkRect::MakeXYWH( 865 SkIntToScalar(left), 866 SkIntToScalar(top), 867 SkIntToScalar(bitmap.width()), 868 SkIntToScalar(bitmap.height())); 869 if (fDeferredDrawing && 870 this->isFullFrame(&bitmapRect, paint) && 871 isPaintOpaque(paint, &bitmap)) { 872 this->getDeferredDevice()->skipPendingCommands(); 873 } 874 875 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 876 this->drawingCanvas()->drawSprite(bitmap, left, top, paint); 877 this->recordedDrawCommand(); 878} 879 880void SkDeferredCanvas::drawText(const void* text, size_t byteLength, 881 SkScalar x, SkScalar y, const SkPaint& paint) { 882 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 883 this->drawingCanvas()->drawText(text, byteLength, x, y, paint); 884 this->recordedDrawCommand(); 885} 886 887void SkDeferredCanvas::drawPosText(const void* text, size_t byteLength, 888 const SkPoint pos[], const SkPaint& paint) { 889 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 890 this->drawingCanvas()->drawPosText(text, byteLength, pos, paint); 891 this->recordedDrawCommand(); 892} 893 894void SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength, 895 const SkScalar xpos[], SkScalar constY, 896 const SkPaint& paint) { 897 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 898 this->drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint); 899 this->recordedDrawCommand(); 900} 901 902void SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength, 903 const SkPath& path, 904 const SkMatrix* matrix, 905 const SkPaint& paint) { 906 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 907 this->drawingCanvas()->drawTextOnPath(text, byteLength, path, matrix, paint); 908 this->recordedDrawCommand(); 909} 910 911void SkDeferredCanvas::drawPicture(SkPicture& picture) { 912 this->drawingCanvas()->drawPicture(picture); 913 this->recordedDrawCommand(); 914} 915 916void SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount, 917 const SkPoint vertices[], 918 const SkPoint texs[], 919 const SkColor colors[], SkXfermode* xmode, 920 const uint16_t indices[], int indexCount, 921 const SkPaint& paint) { 922 AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 923 this->drawingCanvas()->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 924 indices, indexCount, paint); 925 this->recordedDrawCommand(); 926} 927 928SkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) { 929 this->drawingCanvas()->setBounder(bounder); 930 this->INHERITED::setBounder(bounder); 931 this->recordedDrawCommand(); 932 return bounder; 933} 934 935SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) { 936 this->drawingCanvas()->setDrawFilter(filter); 937 this->INHERITED::setDrawFilter(filter); 938 this->recordedDrawCommand(); 939 return filter; 940} 941 942SkCanvas* SkDeferredCanvas::canvasForDrawIter() { 943 return this->drawingCanvas(); 944} 945