SkCanvas.cpp revision 4cb543d6057b692e1099e9f115155f0bf323a0c8
1 2/* 3 * Copyright 2008 The Android Open Source Project 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 10#include "SkCanvas.h" 11#include "SkBitmapDevice.h" 12#include "SkBounder.h" 13#include "SkDeviceImageFilterProxy.h" 14#include "SkDraw.h" 15#include "SkDrawFilter.h" 16#include "SkDrawLooper.h" 17#include "SkMetaData.h" 18#include "SkPathOps.h" 19#include "SkPicture.h" 20#include "SkRasterClip.h" 21#include "SkRRect.h" 22#include "SkSmallAllocator.h" 23#include "SkSurface_Base.h" 24#include "SkTemplates.h" 25#include "SkTextFormatParams.h" 26#include "SkTLazy.h" 27#include "SkUtils.h" 28 29#if SK_SUPPORT_GPU 30#include "GrRenderTarget.h" 31#endif 32 33// experimental for faster tiled drawing... 34//#define SK_ENABLE_CLIP_QUICKREJECT 35 36//#define SK_TRACE_SAVERESTORE 37 38#ifdef SK_TRACE_SAVERESTORE 39 static int gLayerCounter; 40 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 41 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 42 43 static int gRecCounter; 44 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 45 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 46 47 static int gCanvasCounter; 48 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 49 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 50#else 51 #define inc_layer() 52 #define dec_layer() 53 #define inc_rec() 54 #define dec_rec() 55 #define inc_canvas() 56 #define dec_canvas() 57#endif 58 59#ifdef SK_DEBUG 60#include "SkPixelRef.h" 61 62/* 63 * Some pixelref subclasses can support being "locked" from another thread 64 * during the lock-scope of skia calling them. In these instances, this balance 65 * check will fail, but may not be indicative of a problem, so we allow a build 66 * flag to disable this check. 67 * 68 * Potentially another fix would be to have a (debug-only) virtual or flag on 69 * pixelref, which could tell us at runtime if this check is valid. That would 70 * eliminate the need for this heavy-handed build check. 71 */ 72#ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK 73class AutoCheckLockCountBalance { 74public: 75 AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ } 76}; 77#else 78class AutoCheckLockCountBalance { 79public: 80 AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) { 81 fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0; 82 } 83 ~AutoCheckLockCountBalance() { 84 const int count = fPixelRef ? fPixelRef->getLockCount() : 0; 85 SkASSERT(count == fLockCount); 86 } 87 88private: 89 const SkPixelRef* fPixelRef; 90 int fLockCount; 91}; 92#endif 93 94class AutoCheckNoSetContext { 95public: 96 AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) { 97 this->assertNoSetContext(fPaint); 98 } 99 ~AutoCheckNoSetContext() { 100 this->assertNoSetContext(fPaint); 101 } 102 103private: 104 const SkPaint& fPaint; 105 106 void assertNoSetContext(const SkPaint& paint) { 107 SkShader* s = paint.getShader(); 108 if (s) { 109 SkASSERT(!s->setContextHasBeenCalled()); 110 } 111 } 112}; 113 114#define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap) 115#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint) 116 117#else 118 #define CHECK_LOCKCOUNT_BALANCE(bitmap) 119 #define CHECK_SHADER_NOSETCONTEXT(paint) 120#endif 121 122typedef SkTLazy<SkPaint> SkLazyPaint; 123 124void SkCanvas::predrawNotify() { 125 if (fSurfaceBase) { 126 fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); 127 } 128} 129 130/////////////////////////////////////////////////////////////////////////////// 131 132/* This is the record we keep for each SkBaseDevice that the user installs. 133 The clip/matrix/proc are fields that reflect the top of the save/restore 134 stack. Whenever the canvas changes, it marks a dirty flag, and then before 135 these are used (assuming we're not on a layer) we rebuild these cache 136 values: they reflect the top of the save stack, but translated and clipped 137 by the device's XY offset and bitmap-bounds. 138*/ 139struct DeviceCM { 140 DeviceCM* fNext; 141 SkBaseDevice* fDevice; 142 SkRasterClip fClip; 143 const SkMatrix* fMatrix; 144 SkPaint* fPaint; // may be null (in the future) 145 146 DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas) 147 : fNext(NULL) { 148 if (NULL != device) { 149 device->ref(); 150 device->onAttachToCanvas(canvas); 151 } 152 fDevice = device; 153 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 154 } 155 156 ~DeviceCM() { 157 if (NULL != fDevice) { 158 fDevice->onDetachFromCanvas(); 159 fDevice->unref(); 160 } 161 SkDELETE(fPaint); 162 } 163 164 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 165 const SkClipStack& clipStack, SkRasterClip* updateClip) { 166 int x = fDevice->getOrigin().x(); 167 int y = fDevice->getOrigin().y(); 168 int width = fDevice->width(); 169 int height = fDevice->height(); 170 171 if ((x | y) == 0) { 172 fMatrix = &totalMatrix; 173 fClip = totalClip; 174 } else { 175 fMatrixStorage = totalMatrix; 176 fMatrixStorage.postTranslate(SkIntToScalar(-x), 177 SkIntToScalar(-y)); 178 fMatrix = &fMatrixStorage; 179 180 totalClip.translate(-x, -y, &fClip); 181 } 182 183 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 184 185 // intersect clip, but don't translate it (yet) 186 187 if (updateClip) { 188 updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 189 SkRegion::kDifference_Op); 190 } 191 192 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 193 194#ifdef SK_DEBUG 195 if (!fClip.isEmpty()) { 196 SkIRect deviceR; 197 deviceR.set(0, 0, width, height); 198 SkASSERT(deviceR.contains(fClip.getBounds())); 199 } 200#endif 201 } 202 203private: 204 SkMatrix fMatrixStorage; 205}; 206 207/* This is the record we keep for each save/restore level in the stack. 208 Since a level optionally copies the matrix and/or stack, we have pointers 209 for these fields. If the value is copied for this level, the copy is 210 stored in the ...Storage field, and the pointer points to that. If the 211 value is not copied for this level, we ignore ...Storage, and just point 212 at the corresponding value in the previous level in the stack. 213*/ 214class SkCanvas::MCRec { 215public: 216 int fFlags; 217 SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 218 SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec 219 SkDrawFilter* fFilter; // the current filter (or null) 220 221 DeviceCM* fLayer; 222 /* If there are any layers in the stack, this points to the top-most 223 one that is at or below this level in the stack (so we know what 224 bitmap/device to draw into from this level. This value is NOT 225 reference counted, since the real owner is either our fLayer field, 226 or a previous one in a lower level.) 227 */ 228 DeviceCM* fTopLayer; 229 230 MCRec(const MCRec* prev, int flags) : fFlags(flags) { 231 if (NULL != prev) { 232 if (flags & SkCanvas::kMatrix_SaveFlag) { 233 fMatrixStorage = *prev->fMatrix; 234 fMatrix = &fMatrixStorage; 235 } else { 236 fMatrix = prev->fMatrix; 237 } 238 239 if (flags & SkCanvas::kClip_SaveFlag) { 240 fRasterClipStorage = *prev->fRasterClip; 241 fRasterClip = &fRasterClipStorage; 242 } else { 243 fRasterClip = prev->fRasterClip; 244 } 245 246 fFilter = prev->fFilter; 247 SkSafeRef(fFilter); 248 249 fTopLayer = prev->fTopLayer; 250 } else { // no prev 251 fMatrixStorage.reset(); 252 253 fMatrix = &fMatrixStorage; 254 fRasterClip = &fRasterClipStorage; 255 fFilter = NULL; 256 fTopLayer = NULL; 257 } 258 fLayer = NULL; 259 260 // don't bother initializing fNext 261 inc_rec(); 262 } 263 ~MCRec() { 264 SkSafeUnref(fFilter); 265 SkDELETE(fLayer); 266 dec_rec(); 267 } 268 269private: 270 SkMatrix fMatrixStorage; 271 SkRasterClip fRasterClipStorage; 272}; 273 274class SkDrawIter : public SkDraw { 275public: 276 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 277 canvas = canvas->canvasForDrawIter(); 278 fCanvas = canvas; 279 canvas->updateDeviceCMCache(); 280 281 fClipStack = &canvas->fClipStack; 282 fBounder = canvas->getBounder(); 283 fCurrLayer = canvas->fMCRec->fTopLayer; 284 fSkipEmptyClips = skipEmptyClips; 285 } 286 287 bool next() { 288 // skip over recs with empty clips 289 if (fSkipEmptyClips) { 290 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 291 fCurrLayer = fCurrLayer->fNext; 292 } 293 } 294 295 const DeviceCM* rec = fCurrLayer; 296 if (rec && rec->fDevice) { 297 298 fMatrix = rec->fMatrix; 299 fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 300 fRC = &rec->fClip; 301 fDevice = rec->fDevice; 302 fBitmap = &fDevice->accessBitmap(true); 303 fPaint = rec->fPaint; 304 SkDEBUGCODE(this->validate();) 305 306 fCurrLayer = rec->fNext; 307 if (fBounder) { 308 fBounder->setClip(fClip); 309 } 310 // fCurrLayer may be NULL now 311 312 return true; 313 } 314 return false; 315 } 316 317 SkBaseDevice* getDevice() const { return fDevice; } 318 int getX() const { return fDevice->getOrigin().x(); } 319 int getY() const { return fDevice->getOrigin().y(); } 320 const SkMatrix& getMatrix() const { return *fMatrix; } 321 const SkRegion& getClip() const { return *fClip; } 322 const SkPaint* getPaint() const { return fPaint; } 323 324private: 325 SkCanvas* fCanvas; 326 const DeviceCM* fCurrLayer; 327 const SkPaint* fPaint; // May be null. 328 SkBool8 fSkipEmptyClips; 329 330 typedef SkDraw INHERITED; 331}; 332 333///////////////////////////////////////////////////////////////////////////// 334 335class AutoDrawLooper { 336public: 337 AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, 338 bool skipLayerForImageFilter = false, 339 const SkRect* bounds = NULL) : fOrigPaint(paint) { 340 fCanvas = canvas; 341 fFilter = canvas->getDrawFilter(); 342 fPaint = NULL; 343 fSaveCount = canvas->getSaveCount(); 344 fDoClearImageFilter = false; 345 fDone = false; 346 347 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 348 SkPaint tmp; 349 tmp.setImageFilter(fOrigPaint.getImageFilter()); 350 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, 351 true, SkCanvas::kFullLayer_SaveLayerStrategy); 352 // we'll clear the imageFilter for the actual draws in next(), so 353 // it will only be applied during the restore(). 354 fDoClearImageFilter = true; 355 } 356 357 if (SkDrawLooper* looper = paint.getLooper()) { 358 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>( 359 looper->contextSize()); 360 fLooperContext = looper->createContext(canvas, buffer); 361 fIsSimple = false; 362 } else { 363 fLooperContext = NULL; 364 // can we be marked as simple? 365 fIsSimple = !fFilter && !fDoClearImageFilter; 366 } 367 } 368 369 ~AutoDrawLooper() { 370 if (fDoClearImageFilter) { 371 fCanvas->internalRestore(); 372 } 373 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 374 } 375 376 const SkPaint& paint() const { 377 SkASSERT(fPaint); 378 return *fPaint; 379 } 380 381 bool next(SkDrawFilter::Type drawType) { 382 if (fDone) { 383 return false; 384 } else if (fIsSimple) { 385 fDone = true; 386 fPaint = &fOrigPaint; 387 return !fPaint->nothingToDraw(); 388 } else { 389 return this->doNext(drawType); 390 } 391 } 392 393private: 394 SkLazyPaint fLazyPaint; 395 SkCanvas* fCanvas; 396 const SkPaint& fOrigPaint; 397 SkDrawFilter* fFilter; 398 const SkPaint* fPaint; 399 int fSaveCount; 400 bool fDoClearImageFilter; 401 bool fDone; 402 bool fIsSimple; 403 SkDrawLooper::Context* fLooperContext; 404 SkSmallAllocator<1, 32> fLooperContextAllocator; 405 406 bool doNext(SkDrawFilter::Type drawType); 407}; 408 409bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 410 fPaint = NULL; 411 SkASSERT(!fIsSimple); 412 SkASSERT(fLooperContext || fFilter || fDoClearImageFilter); 413 414 SkPaint* paint = fLazyPaint.set(fOrigPaint); 415 416 if (fDoClearImageFilter) { 417 paint->setImageFilter(NULL); 418 } 419 420 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 421 fDone = true; 422 return false; 423 } 424 if (fFilter) { 425 if (!fFilter->filter(paint, drawType)) { 426 fDone = true; 427 return false; 428 } 429 if (NULL == fLooperContext) { 430 // no looper means we only draw once 431 fDone = true; 432 } 433 } 434 fPaint = paint; 435 436 // if we only came in here for the imagefilter, mark us as done 437 if (!fLooperContext && !fFilter) { 438 fDone = true; 439 } 440 441 // call this after any possible paint modifiers 442 if (fPaint->nothingToDraw()) { 443 fPaint = NULL; 444 return false; 445 } 446 return true; 447} 448 449/* Stack helper for managing a SkBounder. In the destructor, if we were 450 given a bounder, we call its commit() method, signifying that we are 451 done accumulating bounds for that draw. 452*/ 453class SkAutoBounderCommit { 454public: 455 SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 456 ~SkAutoBounderCommit() { 457 if (NULL != fBounder) { 458 fBounder->commit(); 459 } 460 } 461private: 462 SkBounder* fBounder; 463}; 464#define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit) 465 466#include "SkColorPriv.h" 467 468////////// macros to place around the internal draw calls ////////////////// 469 470#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ 471 this->predrawNotify(); \ 472 AutoDrawLooper looper(this, paint, true); \ 473 while (looper.next(type)) { \ 474 SkAutoBounderCommit ac(fBounder); \ 475 SkDrawIter iter(this); 476 477#define LOOPER_BEGIN(paint, type, bounds) \ 478 this->predrawNotify(); \ 479 AutoDrawLooper looper(this, paint, false, bounds); \ 480 while (looper.next(type)) { \ 481 SkAutoBounderCommit ac(fBounder); \ 482 SkDrawIter iter(this); 483 484#define LOOPER_END } 485 486//////////////////////////////////////////////////////////////////////////// 487 488SkBaseDevice* SkCanvas::init(SkBaseDevice* device) { 489 fBounder = NULL; 490 fCachedLocalClipBounds.setEmpty(); 491 fCachedLocalClipBoundsDirty = true; 492 fAllowSoftClip = true; 493 fAllowSimplifyClip = false; 494 fDeviceCMDirty = false; 495 fSaveLayerCount = 0; 496 fCullCount = 0; 497 fMetaData = NULL; 498 499 fMCRec = (MCRec*)fMCStack.push_back(); 500 new (fMCRec) MCRec(NULL, 0); 501 502 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL)); 503 fMCRec->fTopLayer = fMCRec->fLayer; 504 505 fSurfaceBase = NULL; 506 507 return this->setRootDevice(device); 508} 509 510SkCanvas::SkCanvas() 511 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 512{ 513 inc_canvas(); 514 515 this->init(NULL); 516} 517 518SkCanvas::SkCanvas(int width, int height) 519 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 520{ 521 inc_canvas(); 522 523 SkBitmap bitmap; 524 bitmap.setConfig(SkImageInfo::MakeUnknown(width, height)); 525 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); 526} 527 528SkCanvas::SkCanvas(SkBaseDevice* device) 529 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 530{ 531 inc_canvas(); 532 533 this->init(device); 534} 535 536SkCanvas::SkCanvas(const SkBitmap& bitmap) 537 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 538{ 539 inc_canvas(); 540 541 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); 542} 543 544SkCanvas::~SkCanvas() { 545 // free up the contents of our deque 546 this->restoreToCount(1); // restore everything but the last 547 SkASSERT(0 == fSaveLayerCount); 548 549 this->internalRestore(); // restore the last, since we're going away 550 551 SkSafeUnref(fBounder); 552 SkDELETE(fMetaData); 553 554 dec_canvas(); 555} 556 557SkBounder* SkCanvas::setBounder(SkBounder* bounder) { 558 SkRefCnt_SafeAssign(fBounder, bounder); 559 return bounder; 560} 561 562SkDrawFilter* SkCanvas::getDrawFilter() const { 563 return fMCRec->fFilter; 564} 565 566SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 567 SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 568 return filter; 569} 570 571SkMetaData& SkCanvas::getMetaData() { 572 // metadata users are rare, so we lazily allocate it. If that changes we 573 // can decide to just make it a field in the device (rather than a ptr) 574 if (NULL == fMetaData) { 575 fMetaData = new SkMetaData; 576 } 577 return *fMetaData; 578} 579 580/////////////////////////////////////////////////////////////////////////////// 581 582void SkCanvas::flush() { 583 SkBaseDevice* device = this->getDevice(); 584 if (device) { 585 device->flush(); 586 } 587} 588 589SkISize SkCanvas::getTopLayerSize() const { 590 SkBaseDevice* d = this->getTopDevice(); 591 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 592} 593 594SkIPoint SkCanvas::getTopLayerOrigin() const { 595 SkBaseDevice* d = this->getTopDevice(); 596 return d ? d->getOrigin() : SkIPoint::Make(0, 0); 597} 598 599SkISize SkCanvas::getBaseLayerSize() const { 600 SkBaseDevice* d = this->getDevice(); 601 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 602} 603 604SkBaseDevice* SkCanvas::getDevice() const { 605 // return root device 606 MCRec* rec = (MCRec*) fMCStack.front(); 607 SkASSERT(rec && rec->fLayer); 608 return rec->fLayer->fDevice; 609} 610 611SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 612 if (updateMatrixClip) { 613 const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 614 } 615 return fMCRec->fTopLayer->fDevice; 616} 617 618SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) { 619 // return root device 620 SkDeque::F2BIter iter(fMCStack); 621 MCRec* rec = (MCRec*)iter.next(); 622 SkASSERT(rec && rec->fLayer); 623 SkBaseDevice* rootDevice = rec->fLayer->fDevice; 624 625 if (rootDevice == device) { 626 return device; 627 } 628 629 if (device) { 630 device->onAttachToCanvas(this); 631 } 632 if (rootDevice) { 633 rootDevice->onDetachFromCanvas(); 634 } 635 636 SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 637 rootDevice = device; 638 639 fDeviceCMDirty = true; 640 641 /* Now we update our initial region to have the bounds of the new device, 642 and then intersect all of the clips in our stack with these bounds, 643 to ensure that we can't draw outside of the device's bounds (and trash 644 memory). 645 646 NOTE: this is only a partial-fix, since if the new device is larger than 647 the previous one, we don't know how to "enlarge" the clips in our stack, 648 so drawing may be artificially restricted. Without keeping a history of 649 all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 650 reconstruct the correct clips, so this approximation will have to do. 651 The caller really needs to restore() back to the base if they want to 652 accurately take advantage of the new device bounds. 653 */ 654 655 SkIRect bounds; 656 if (device) { 657 bounds.set(0, 0, device->width(), device->height()); 658 } else { 659 bounds.setEmpty(); 660 } 661 // now jam our 1st clip to be bounds, and intersect the rest with that 662 rec->fRasterClip->setRect(bounds); 663 while ((rec = (MCRec*)iter.next()) != NULL) { 664 (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); 665 } 666 667 return device; 668} 669 670bool SkCanvas::readPixels(SkBitmap* bitmap, 671 int x, int y, 672 Config8888 config8888) { 673 SkBaseDevice* device = this->getDevice(); 674 if (!device) { 675 return false; 676 } 677 return device->readPixels(bitmap, x, y, config8888); 678} 679 680bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 681 SkBaseDevice* device = this->getDevice(); 682 if (!device) { 683 return false; 684 } 685 686 SkIRect bounds; 687 bounds.set(0, 0, device->width(), device->height()); 688 if (!bounds.intersect(srcRect)) { 689 return false; 690 } 691 692 SkBitmap tmp; 693 tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), 694 bounds.height()); 695 if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) { 696 bitmap->swap(tmp); 697 return true; 698 } else { 699 return false; 700 } 701} 702 703#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG 704void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y, 705 Config8888 config8888) { 706 SkBaseDevice* device = this->getDevice(); 707 if (device) { 708 if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()), 709 SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) { 710 device->accessBitmap(true); 711 device->writePixels(bitmap, x, y, config8888); 712 } 713 } 714} 715#endif 716 717bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 718 if (bitmap.getTexture()) { 719 return false; 720 } 721 SkBitmap bm(bitmap); 722 bm.lockPixels(); 723 if (bm.getPixels()) { 724 return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y); 725 } 726 return false; 727} 728 729bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes, 730 int x, int y) { 731 switch (origInfo.colorType()) { 732 case kUnknown_SkColorType: 733 case kIndex_8_SkColorType: 734 return false; 735 default: 736 break; 737 } 738 if (NULL == pixels || rowBytes < origInfo.minRowBytes()) { 739 return false; 740 } 741 742 const SkISize size = this->getBaseLayerSize(); 743 SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height()); 744 if (!target.intersect(0, 0, size.width(), size.height())) { 745 return false; 746 } 747 748 SkBaseDevice* device = this->getDevice(); 749 if (!device) { 750 return false; 751 } 752 753 SkImageInfo info = origInfo; 754 // the intersect may have shrunk info's logical size 755 info.fWidth = target.width(); 756 info.fHeight = target.height(); 757 758 // if x or y are negative, then we have to adjust pixels 759 if (x > 0) { 760 x = 0; 761 } 762 if (y > 0) { 763 y = 0; 764 } 765 // here x,y are either 0 or negative 766 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel()); 767 768 // The device can assert that the requested area is always contained in its bounds 769 return device->writePixelsDirect(info, pixels, rowBytes, target.x(), target.y()); 770} 771 772SkCanvas* SkCanvas::canvasForDrawIter() { 773 return this; 774} 775 776////////////////////////////////////////////////////////////////////////////// 777 778void SkCanvas::updateDeviceCMCache() { 779 if (fDeviceCMDirty) { 780 const SkMatrix& totalMatrix = this->getTotalMatrix(); 781 const SkRasterClip& totalClip = *fMCRec->fRasterClip; 782 DeviceCM* layer = fMCRec->fTopLayer; 783 784 if (NULL == layer->fNext) { // only one layer 785 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 786 } else { 787 SkRasterClip clip(totalClip); 788 do { 789 layer->updateMC(totalMatrix, clip, fClipStack, &clip); 790 } while ((layer = layer->fNext) != NULL); 791 } 792 fDeviceCMDirty = false; 793 } 794} 795 796/////////////////////////////////////////////////////////////////////////////// 797 798int SkCanvas::internalSave(SaveFlags flags) { 799 int saveCount = this->getSaveCount(); // record this before the actual save 800 801 MCRec* newTop = (MCRec*)fMCStack.push_back(); 802 new (newTop) MCRec(fMCRec, flags); // balanced in restore() 803 804 fMCRec = newTop; 805 806 if (SkCanvas::kClip_SaveFlag & flags) { 807 fClipStack.save(); 808 } 809 810 return saveCount; 811} 812 813void SkCanvas::willSave(SaveFlags) { 814 // Do nothing. Subclasses may do something. 815} 816 817int SkCanvas::save(SaveFlags flags) { 818 this->willSave(flags); 819 // call shared impl 820 return this->internalSave(flags); 821} 822 823static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 824#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 825 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 826#else 827 return true; 828#endif 829} 830 831bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 832 SkIRect* intersection, const SkImageFilter* imageFilter) { 833 SkIRect clipBounds; 834 SkRegion::Op op = SkRegion::kIntersect_Op; 835 if (!this->getClipDeviceBounds(&clipBounds)) { 836 return false; 837 } 838 839 if (imageFilter) { 840 imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds); 841 // Filters may grow the bounds beyond the device bounds. 842 op = SkRegion::kReplace_Op; 843 } 844 SkIRect ir; 845 if (NULL != bounds) { 846 SkRect r; 847 848 this->getTotalMatrix().mapRect(&r, *bounds); 849 r.roundOut(&ir); 850 // early exit if the layer's bounds are clipped out 851 if (!ir.intersect(clipBounds)) { 852 if (bounds_affects_clip(flags)) { 853 fMCRec->fRasterClip->setEmpty(); 854 } 855 return false; 856 } 857 } else { // no user bounds, so just use the clip 858 ir = clipBounds; 859 } 860 861 if (bounds_affects_clip(flags)) { 862 fClipStack.clipDevRect(ir, op); 863 // early exit if the clip is now empty 864 if (!fMCRec->fRasterClip->op(ir, op)) { 865 return false; 866 } 867 } 868 869 if (intersection) { 870 *intersection = ir; 871 } 872 return true; 873} 874 875SkCanvas::SaveLayerStrategy SkCanvas::willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) { 876 877 // Do nothing. Subclasses may do something. 878 return kFullLayer_SaveLayerStrategy; 879} 880 881int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 882 SaveFlags flags) { 883 // Overriding classes may return false to signal that we don't need to create a layer. 884 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags); 885 return this->internalSaveLayer(bounds, paint, flags, false, strategy); 886} 887 888static SkBaseDevice* createCompatibleDevice(SkCanvas* canvas, 889 const SkImageInfo& info) { 890 SkBaseDevice* device = canvas->getDevice(); 891 return device ? device->createCompatibleDevice(info) : NULL; 892} 893 894int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags, 895 bool justForImageFilter, SaveLayerStrategy strategy) { 896#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 897 flags = (SaveFlags)(flags | kClipToLayer_SaveFlag); 898#endif 899 900 // do this before we create the layer. We don't call the public save() since 901 // that would invoke a possibly overridden virtual 902 int count = this->internalSave(flags); 903 904 fDeviceCMDirty = true; 905 906 SkIRect ir; 907 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) { 908 return count; 909 } 910 911 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 912 // the clipRectBounds() call above? 913 if (kNoLayer_SaveLayerStrategy == strategy) { 914 return count; 915 } 916 917 // Kill the imagefilter if our device doesn't allow it 918 SkLazyPaint lazyP; 919 if (paint && paint->getImageFilter()) { 920 if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 921 if (justForImageFilter) { 922 // early exit if the layer was just for the imageFilter 923 return count; 924 } 925 SkPaint* p = lazyP.set(*paint); 926 p->setImageFilter(NULL); 927 paint = p; 928 } 929 } 930 931 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); 932 SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(), 933 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 934 935 SkBaseDevice* device; 936 if (paint && paint->getImageFilter()) { 937 device = createCompatibleDevice(this, info); 938 } else { 939 device = this->createLayerDevice(info); 940 } 941 if (NULL == device) { 942 SkDebugf("Unable to create device for layer."); 943 return count; 944 } 945 946 device->setOrigin(ir.fLeft, ir.fTop); 947 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this)); 948 device->unref(); 949 950 layer->fNext = fMCRec->fTopLayer; 951 fMCRec->fLayer = layer; 952 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 953 954 fSaveLayerCount += 1; 955 return count; 956} 957 958int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 959 SaveFlags flags) { 960 if (0xFF == alpha) { 961 return this->saveLayer(bounds, NULL, flags); 962 } else { 963 SkPaint tmpPaint; 964 tmpPaint.setAlpha(alpha); 965 return this->saveLayer(bounds, &tmpPaint, flags); 966 } 967} 968 969void SkCanvas::willRestore() { 970 // Do nothing. Subclasses may do something. 971} 972 973void SkCanvas::restore() { 974 // check for underflow 975 if (fMCStack.count() > 1) { 976 this->willRestore(); 977 this->internalRestore(); 978 } 979} 980 981void SkCanvas::internalRestore() { 982 SkASSERT(fMCStack.count() != 0); 983 984 fDeviceCMDirty = true; 985 fCachedLocalClipBoundsDirty = true; 986 987 if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) { 988 fClipStack.restore(); 989 } 990 991 // reserve our layer (if any) 992 DeviceCM* layer = fMCRec->fLayer; // may be null 993 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 994 fMCRec->fLayer = NULL; 995 996 // now do the normal restore() 997 fMCRec->~MCRec(); // balanced in save() 998 fMCStack.pop_back(); 999 fMCRec = (MCRec*)fMCStack.back(); 1000 1001 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1002 since if we're being recorded, we don't want to record this (the 1003 recorder will have already recorded the restore). 1004 */ 1005 if (NULL != layer) { 1006 if (layer->fNext) { 1007 const SkIPoint& origin = layer->fDevice->getOrigin(); 1008 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1009 layer->fPaint); 1010 // reset this, since internalDrawDevice will have set it to true 1011 fDeviceCMDirty = true; 1012 1013 SkASSERT(fSaveLayerCount > 0); 1014 fSaveLayerCount -= 1; 1015 } 1016 SkDELETE(layer); 1017 } 1018} 1019 1020int SkCanvas::getSaveCount() const { 1021 return fMCStack.count(); 1022} 1023 1024void SkCanvas::restoreToCount(int count) { 1025 // sanity check 1026 if (count < 1) { 1027 count = 1; 1028 } 1029 1030 int n = this->getSaveCount() - count; 1031 for (int i = 0; i < n; ++i) { 1032 this->restore(); 1033 } 1034} 1035 1036bool SkCanvas::isDrawingToLayer() const { 1037 return fSaveLayerCount > 0; 1038} 1039 1040SkSurface* SkCanvas::newSurface(const SkImageInfo& info) { 1041 return this->onNewSurface(info); 1042} 1043 1044SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) { 1045 SkBaseDevice* dev = this->getDevice(); 1046 return dev ? dev->newSurface(info) : NULL; 1047} 1048 1049SkImageInfo SkCanvas::imageInfo() const { 1050 SkBaseDevice* dev = this->getDevice(); 1051 if (dev) { 1052 return dev->imageInfo(); 1053 } else { 1054 return SkImageInfo::MakeUnknown(0, 0); 1055 } 1056} 1057 1058const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1059 return this->onPeekPixels(info, rowBytes); 1060} 1061 1062const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) { 1063 SkBaseDevice* dev = this->getDevice(); 1064 return dev ? dev->peekPixels(info, rowBytes) : NULL; 1065} 1066 1067void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) { 1068 return this->onAccessTopLayerPixels(info, rowBytes); 1069} 1070 1071void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) { 1072 SkBaseDevice* dev = this->getTopDevice(); 1073 return dev ? dev->accessPixels(info, rowBytes) : NULL; 1074} 1075 1076SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) { 1077 fAddr = canvas->peekPixels(&fInfo, &fRowBytes); 1078 if (NULL == fAddr) { 1079 fInfo = canvas->imageInfo(); 1080 if (kUnknown_SkColorType == fInfo.colorType() || 1081 !fBitmap.allocPixels(fInfo)) 1082 { 1083 return; // failure, fAddr is NULL 1084 } 1085 fBitmap.lockPixels(); 1086 if (!canvas->readPixels(&fBitmap, 0, 0)) { 1087 return; // failure, fAddr is NULL 1088 } 1089 fAddr = fBitmap.getPixels(); 1090 fRowBytes = fBitmap.rowBytes(); 1091 } 1092 SkASSERT(fAddr); // success 1093} 1094 1095bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const { 1096 if (fAddr) { 1097 return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes, 1098 NULL, NULL); 1099 } else { 1100 bitmap->reset(); 1101 return false; 1102 } 1103} 1104 1105void SkCanvas::onPushCull(const SkRect& cullRect) { 1106 // do nothing. Subclasses may do something 1107} 1108 1109void SkCanvas::onPopCull() { 1110 // do nothing. Subclasses may do something 1111} 1112 1113///////////////////////////////////////////////////////////////////////////// 1114 1115void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 1116 const SkMatrix& matrix, const SkPaint* paint) { 1117 if (bitmap.drawsNothing()) { 1118 return; 1119 } 1120 1121 SkLazyPaint lazy; 1122 if (NULL == paint) { 1123 paint = lazy.init(); 1124 } 1125 1126 SkDEBUGCODE(bitmap.validate();) 1127 CHECK_LOCKCOUNT_BALANCE(bitmap); 1128 1129 SkRect storage; 1130 const SkRect* bounds = NULL; 1131 if (paint && paint->canComputeFastBounds()) { 1132 bitmap.getBounds(&storage); 1133 matrix.mapRect(&storage); 1134 bounds = &paint->computeFastBounds(storage, &storage); 1135 } 1136 1137 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1138 1139 while (iter.next()) { 1140 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 1141 } 1142 1143 LOOPER_END 1144} 1145 1146void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 1147 const SkPaint* paint) { 1148 SkPaint tmp; 1149 if (NULL == paint) { 1150 tmp.setDither(true); 1151 paint = &tmp; 1152 } 1153 1154 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1155 while (iter.next()) { 1156 SkBaseDevice* dstDev = iter.fDevice; 1157 paint = &looper.paint(); 1158 SkImageFilter* filter = paint->getImageFilter(); 1159 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1160 if (filter && !dstDev->canHandleImageFilter(filter)) { 1161 SkDeviceImageFilterProxy proxy(dstDev); 1162 SkBitmap dst; 1163 SkIPoint offset = SkIPoint::Make(0, 0); 1164 const SkBitmap& src = srcDev->accessBitmap(false); 1165 SkMatrix matrix = *iter.fMatrix; 1166 matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 1167 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height()); 1168 SkImageFilter::Context ctx(matrix, clipBounds); 1169 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { 1170 SkPaint tmpUnfiltered(*paint); 1171 tmpUnfiltered.setImageFilter(NULL); 1172 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1173 tmpUnfiltered); 1174 } 1175 } else { 1176 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1177 } 1178 } 1179 LOOPER_END 1180} 1181 1182void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 1183 const SkPaint* paint) { 1184 if (bitmap.drawsNothing()) { 1185 return; 1186 } 1187 SkDEBUGCODE(bitmap.validate();) 1188 CHECK_LOCKCOUNT_BALANCE(bitmap); 1189 1190 SkPaint tmp; 1191 if (NULL == paint) { 1192 paint = &tmp; 1193 } 1194 1195 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1196 1197 while (iter.next()) { 1198 paint = &looper.paint(); 1199 SkImageFilter* filter = paint->getImageFilter(); 1200 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1201 if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 1202 SkDeviceImageFilterProxy proxy(iter.fDevice); 1203 SkBitmap dst; 1204 SkIPoint offset = SkIPoint::Make(0, 0); 1205 SkMatrix matrix = *iter.fMatrix; 1206 matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 1207 SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height()); 1208 SkImageFilter::Context ctx(matrix, clipBounds); 1209 if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) { 1210 SkPaint tmpUnfiltered(*paint); 1211 tmpUnfiltered.setImageFilter(NULL); 1212 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1213 tmpUnfiltered); 1214 } 1215 } else { 1216 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 1217 } 1218 } 1219 LOOPER_END 1220} 1221 1222///////////////////////////////////////////////////////////////////////////// 1223void SkCanvas::didTranslate(SkScalar, SkScalar) { 1224 // Do nothing. Subclasses may do something. 1225} 1226 1227bool SkCanvas::translate(SkScalar dx, SkScalar dy) { 1228 fDeviceCMDirty = true; 1229 fCachedLocalClipBoundsDirty = true; 1230 bool res = fMCRec->fMatrix->preTranslate(dx, dy); 1231 1232 this->didTranslate(dx, dy); 1233 return res; 1234} 1235 1236void SkCanvas::didScale(SkScalar, SkScalar) { 1237 // Do nothing. Subclasses may do something. 1238} 1239 1240bool SkCanvas::scale(SkScalar sx, SkScalar sy) { 1241 fDeviceCMDirty = true; 1242 fCachedLocalClipBoundsDirty = true; 1243 bool res = fMCRec->fMatrix->preScale(sx, sy); 1244 1245 this->didScale(sx, sy); 1246 return res; 1247} 1248 1249void SkCanvas::didRotate(SkScalar) { 1250 // Do nothing. Subclasses may do something. 1251} 1252 1253bool SkCanvas::rotate(SkScalar degrees) { 1254 fDeviceCMDirty = true; 1255 fCachedLocalClipBoundsDirty = true; 1256 bool res = fMCRec->fMatrix->preRotate(degrees); 1257 1258 this->didRotate(degrees); 1259 return res; 1260} 1261 1262void SkCanvas::didSkew(SkScalar, SkScalar) { 1263 // Do nothing. Subclasses may do something. 1264} 1265 1266bool SkCanvas::skew(SkScalar sx, SkScalar sy) { 1267 fDeviceCMDirty = true; 1268 fCachedLocalClipBoundsDirty = true; 1269 bool res = fMCRec->fMatrix->preSkew(sx, sy); 1270 1271 this->didSkew(sx, sy); 1272 return res; 1273} 1274 1275void SkCanvas::didConcat(const SkMatrix&) { 1276 // Do nothing. Subclasses may do something. 1277} 1278 1279bool SkCanvas::concat(const SkMatrix& matrix) { 1280 fDeviceCMDirty = true; 1281 fCachedLocalClipBoundsDirty = true; 1282 bool res = fMCRec->fMatrix->preConcat(matrix); 1283 1284 this->didConcat(matrix); 1285 return res; 1286} 1287 1288void SkCanvas::didSetMatrix(const SkMatrix&) { 1289 // Do nothing. Subclasses may do something. 1290} 1291 1292void SkCanvas::setMatrix(const SkMatrix& matrix) { 1293 fDeviceCMDirty = true; 1294 fCachedLocalClipBoundsDirty = true; 1295 *fMCRec->fMatrix = matrix; 1296 this->didSetMatrix(matrix); 1297} 1298 1299void SkCanvas::resetMatrix() { 1300 SkMatrix matrix; 1301 1302 matrix.reset(); 1303 this->setMatrix(matrix); 1304} 1305 1306////////////////////////////////////////////////////////////////////////////// 1307 1308void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1309 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1310 this->onClipRect(rect, op, edgeStyle); 1311} 1312 1313void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1314#ifdef SK_ENABLE_CLIP_QUICKREJECT 1315 if (SkRegion::kIntersect_Op == op) { 1316 if (fMCRec->fRasterClip->isEmpty()) { 1317 return false; 1318 } 1319 1320 if (this->quickReject(rect)) { 1321 fDeviceCMDirty = true; 1322 fCachedLocalClipBoundsDirty = true; 1323 1324 fClipStack.clipEmpty(); 1325 return fMCRec->fRasterClip->setEmpty(); 1326 } 1327 } 1328#endif 1329 1330 AutoValidateClip avc(this); 1331 1332 fDeviceCMDirty = true; 1333 fCachedLocalClipBoundsDirty = true; 1334 if (!fAllowSoftClip) { 1335 edgeStyle = kHard_ClipEdgeStyle; 1336 } 1337 1338 if (fMCRec->fMatrix->rectStaysRect()) { 1339 // for these simpler matrices, we can stay a rect even after applying 1340 // the matrix. This means we don't have to a) make a path, and b) tell 1341 // the region code to scan-convert the path, only to discover that it 1342 // is really just a rect. 1343 SkRect r; 1344 1345 fMCRec->fMatrix->mapRect(&r, rect); 1346 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1347 fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1348 } else { 1349 // since we're rotated or some such thing, we convert the rect to a path 1350 // and clip against that, since it can handle any matrix. However, to 1351 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1352 // we explicitly call "our" version of clipPath. 1353 SkPath path; 1354 1355 path.addRect(rect); 1356 this->SkCanvas::onClipPath(path, op, edgeStyle); 1357 } 1358} 1359 1360static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip, 1361 const SkPath& devPath, SkRegion::Op op, bool doAA) { 1362 // base is used to limit the size (and therefore memory allocation) of the 1363 // region that results from scan converting devPath. 1364 SkRegion base; 1365 1366 if (SkRegion::kIntersect_Op == op) { 1367 // since we are intersect, we can do better (tighter) with currRgn's 1368 // bounds, than just using the device. However, if currRgn is complex, 1369 // our region blitter may hork, so we do that case in two steps. 1370 if (currClip->isRect()) { 1371 // FIXME: we should also be able to do this when currClip->isBW(), 1372 // but relaxing the test above triggers GM asserts in 1373 // SkRgnBuilder::blitH(). We need to investigate what's going on. 1374 currClip->setPath(devPath, currClip->bwRgn(), doAA); 1375 } else { 1376 base.setRect(currClip->getBounds()); 1377 SkRasterClip clip; 1378 clip.setPath(devPath, base, doAA); 1379 currClip->op(clip, op); 1380 } 1381 } else { 1382 const SkBaseDevice* device = canvas->getDevice(); 1383 if (!device) { 1384 currClip->setEmpty(); 1385 return; 1386 } 1387 1388 base.setRect(0, 0, device->width(), device->height()); 1389 1390 if (SkRegion::kReplace_Op == op) { 1391 currClip->setPath(devPath, base, doAA); 1392 } else { 1393 SkRasterClip clip; 1394 clip.setPath(devPath, base, doAA); 1395 currClip->op(clip, op); 1396 } 1397 } 1398} 1399 1400void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1401 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1402 if (rrect.isRect()) { 1403 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1404 } else { 1405 this->onClipRRect(rrect, op, edgeStyle); 1406 } 1407} 1408 1409void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1410 SkRRect transformedRRect; 1411 if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) { 1412 AutoValidateClip avc(this); 1413 1414 fDeviceCMDirty = true; 1415 fCachedLocalClipBoundsDirty = true; 1416 if (!fAllowSoftClip) { 1417 edgeStyle = kHard_ClipEdgeStyle; 1418 } 1419 1420 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1421 1422 SkPath devPath; 1423 devPath.addRRect(transformedRRect); 1424 1425 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1426 return; 1427 } 1428 1429 SkPath path; 1430 path.addRRect(rrect); 1431 // call the non-virtual version 1432 this->SkCanvas::onClipPath(path, op, edgeStyle); 1433} 1434 1435void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1436 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1437 SkRect r; 1438 if (!path.isInverseFillType() && path.isRect(&r)) { 1439 this->onClipRect(r, op, edgeStyle); 1440 } else { 1441 this->onClipPath(path, op, edgeStyle); 1442 } 1443} 1444 1445void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1446#ifdef SK_ENABLE_CLIP_QUICKREJECT 1447 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1448 if (fMCRec->fRasterClip->isEmpty()) { 1449 return false; 1450 } 1451 1452 if (this->quickReject(path.getBounds())) { 1453 fDeviceCMDirty = true; 1454 fCachedLocalClipBoundsDirty = true; 1455 1456 fClipStack.clipEmpty(); 1457 return fMCRec->fRasterClip->setEmpty(); 1458 } 1459 } 1460#endif 1461 1462 AutoValidateClip avc(this); 1463 1464 fDeviceCMDirty = true; 1465 fCachedLocalClipBoundsDirty = true; 1466 if (!fAllowSoftClip) { 1467 edgeStyle = kHard_ClipEdgeStyle; 1468 } 1469 1470 SkPath devPath; 1471 path.transform(*fMCRec->fMatrix, &devPath); 1472 1473 // Check if the transfomation, or the original path itself 1474 // made us empty. Note this can also happen if we contained NaN 1475 // values. computing the bounds detects this, and will set our 1476 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1477 if (devPath.getBounds().isEmpty()) { 1478 // resetting the path will remove any NaN or other wanky values 1479 // that might upset our scan converter. 1480 devPath.reset(); 1481 } 1482 1483 // if we called path.swap() we could avoid a deep copy of this path 1484 fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1485 1486 if (fAllowSimplifyClip) { 1487 devPath.reset(); 1488 devPath.setFillType(SkPath::kInverseEvenOdd_FillType); 1489 const SkClipStack* clipStack = getClipStack(); 1490 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); 1491 const SkClipStack::Element* element; 1492 while ((element = iter.next())) { 1493 SkClipStack::Element::Type type = element->getType(); 1494 if (type == SkClipStack::Element::kEmpty_Type) { 1495 continue; 1496 } 1497 SkPath operand; 1498 element->asPath(&operand); 1499 SkRegion::Op elementOp = element->getOp(); 1500 if (elementOp == SkRegion::kReplace_Op) { 1501 devPath = operand; 1502 } else { 1503 Op(devPath, operand, (SkPathOp) elementOp, &devPath); 1504 } 1505 // if the prev and curr clips disagree about aa -vs- not, favor the aa request. 1506 // perhaps we need an API change to avoid this sort of mixed-signals about 1507 // clipping. 1508 if (element->isAA()) { 1509 edgeStyle = kSoft_ClipEdgeStyle; 1510 } 1511 } 1512 op = SkRegion::kReplace_Op; 1513 } 1514 1515 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle); 1516} 1517 1518void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, 1519 bool inverseFilled) { 1520 // This is for updating the clip conservatively using only bounds 1521 // information. 1522 // Contract: 1523 // The current clip must contain the true clip. The true 1524 // clip is the clip that would have normally been computed 1525 // by calls to clipPath and clipRRect 1526 // Objective: 1527 // Keep the current clip as small as possible without 1528 // breaking the contract, using only clip bounding rectangles 1529 // (for performance). 1530 1531 // N.B.: This *never* calls back through a virtual on canvas, so subclasses 1532 // don't have to worry about getting caught in a loop. Thus anywhere 1533 // we call a virtual method, we explicitly prefix it with 1534 // SkCanvas:: to be sure to call the base-class. 1535 1536 if (inverseFilled) { 1537 switch (op) { 1538 case SkRegion::kIntersect_Op: 1539 case SkRegion::kDifference_Op: 1540 // These ops can only shrink the current clip. So leaving 1541 // the clip unchanged conservatively respects the contract. 1542 break; 1543 case SkRegion::kUnion_Op: 1544 case SkRegion::kReplace_Op: 1545 case SkRegion::kReverseDifference_Op: 1546 case SkRegion::kXOR_Op: { 1547 // These ops can grow the current clip up to the extents of 1548 // the input clip, which is inverse filled, so we just set 1549 // the current clip to the device bounds. 1550 SkRect deviceBounds; 1551 SkIRect deviceIBounds; 1552 this->getDevice()->getGlobalBounds(&deviceIBounds); 1553 deviceBounds = SkRect::Make(deviceIBounds); 1554 this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); 1555 // set the clip in device space 1556 this->SkCanvas::setMatrix(SkMatrix::I()); 1557 this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op, 1558 kHard_ClipEdgeStyle); 1559 this->SkCanvas::restore(); //pop the matrix, but keep the clip 1560 break; 1561 } 1562 default: 1563 SkASSERT(0); // unhandled op? 1564 } 1565 } else { 1566 // Not inverse filled 1567 switch (op) { 1568 case SkRegion::kIntersect_Op: 1569 case SkRegion::kUnion_Op: 1570 case SkRegion::kReplace_Op: 1571 this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle); 1572 break; 1573 case SkRegion::kDifference_Op: 1574 // Difference can only shrink the current clip. 1575 // Leaving clip unchanged conservatively fullfills the contract. 1576 break; 1577 case SkRegion::kReverseDifference_Op: 1578 // To reverse, we swap in the bounds with a replace op. 1579 // As with difference, leave it unchanged. 1580 this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle); 1581 break; 1582 case SkRegion::kXOR_Op: 1583 // Be conservative, based on (A XOR B) always included in (A union B), 1584 // which is always included in (bounds(A) union bounds(B)) 1585 this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle); 1586 break; 1587 default: 1588 SkASSERT(0); // unhandled op? 1589 } 1590 } 1591} 1592 1593void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1594 this->onClipRegion(rgn, op); 1595} 1596 1597void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1598 AutoValidateClip avc(this); 1599 1600 fDeviceCMDirty = true; 1601 fCachedLocalClipBoundsDirty = true; 1602 1603 // todo: signal fClipStack that we have a region, and therefore (I guess) 1604 // we have to ignore it, and use the region directly? 1605 fClipStack.clipDevRect(rgn.getBounds(), op); 1606 1607 fMCRec->fRasterClip->op(rgn, op); 1608} 1609 1610#ifdef SK_DEBUG 1611void SkCanvas::validateClip() const { 1612 // construct clipRgn from the clipstack 1613 const SkBaseDevice* device = this->getDevice(); 1614 if (!device) { 1615 SkASSERT(this->isClipEmpty()); 1616 return; 1617 } 1618 1619 SkIRect ir; 1620 ir.set(0, 0, device->width(), device->height()); 1621 SkRasterClip tmpClip(ir); 1622 1623 SkClipStack::B2TIter iter(fClipStack); 1624 const SkClipStack::Element* element; 1625 while ((element = iter.next()) != NULL) { 1626 switch (element->getType()) { 1627 case SkClipStack::Element::kRect_Type: 1628 element->getRect().round(&ir); 1629 tmpClip.op(ir, element->getOp()); 1630 break; 1631 case SkClipStack::Element::kEmpty_Type: 1632 tmpClip.setEmpty(); 1633 break; 1634 default: { 1635 SkPath path; 1636 element->asPath(&path); 1637 clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA()); 1638 break; 1639 } 1640 } 1641 } 1642} 1643#endif 1644 1645void SkCanvas::replayClips(ClipVisitor* visitor) const { 1646 SkClipStack::B2TIter iter(fClipStack); 1647 const SkClipStack::Element* element; 1648 1649 static const SkRect kEmpty = { 0, 0, 0, 0 }; 1650 while ((element = iter.next()) != NULL) { 1651 switch (element->getType()) { 1652 case SkClipStack::Element::kPath_Type: 1653 visitor->clipPath(element->getPath(), element->getOp(), element->isAA()); 1654 break; 1655 case SkClipStack::Element::kRRect_Type: 1656 visitor->clipRRect(element->getRRect(), element->getOp(), element->isAA()); 1657 break; 1658 case SkClipStack::Element::kRect_Type: 1659 visitor->clipRect(element->getRect(), element->getOp(), element->isAA()); 1660 break; 1661 case SkClipStack::Element::kEmpty_Type: 1662 visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false); 1663 break; 1664 } 1665 } 1666} 1667 1668/////////////////////////////////////////////////////////////////////////////// 1669 1670bool SkCanvas::isClipEmpty() const { 1671 return fMCRec->fRasterClip->isEmpty(); 1672} 1673 1674bool SkCanvas::isClipRect() const { 1675 return fMCRec->fRasterClip->isRect(); 1676} 1677 1678bool SkCanvas::quickReject(const SkRect& rect) const { 1679 1680 if (!rect.isFinite()) 1681 return true; 1682 1683 if (fMCRec->fRasterClip->isEmpty()) { 1684 return true; 1685 } 1686 1687 if (fMCRec->fMatrix->hasPerspective()) { 1688 SkRect dst; 1689 fMCRec->fMatrix->mapRect(&dst, rect); 1690 SkIRect idst; 1691 dst.roundOut(&idst); 1692 return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); 1693 } else { 1694 const SkRect& clipR = this->getLocalClipBounds(); 1695 1696 // for speed, do the most likely reject compares first 1697 // TODO: should we use | instead, or compare all 4 at once? 1698 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1699 return true; 1700 } 1701 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1702 return true; 1703 } 1704 return false; 1705 } 1706} 1707 1708bool SkCanvas::quickReject(const SkPath& path) const { 1709 return path.isEmpty() || this->quickReject(path.getBounds()); 1710} 1711 1712bool SkCanvas::getClipBounds(SkRect* bounds) const { 1713 SkIRect ibounds; 1714 if (!this->getClipDeviceBounds(&ibounds)) { 1715 return false; 1716 } 1717 1718 SkMatrix inverse; 1719 // if we can't invert the CTM, we can't return local clip bounds 1720 if (!fMCRec->fMatrix->invert(&inverse)) { 1721 if (bounds) { 1722 bounds->setEmpty(); 1723 } 1724 return false; 1725 } 1726 1727 if (NULL != bounds) { 1728 SkRect r; 1729 // adjust it outwards in case we are antialiasing 1730 const int inset = 1; 1731 1732 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1733 ibounds.fRight + inset, ibounds.fBottom + inset); 1734 inverse.mapRect(bounds, r); 1735 } 1736 return true; 1737} 1738 1739bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1740 const SkRasterClip& clip = *fMCRec->fRasterClip; 1741 if (clip.isEmpty()) { 1742 if (bounds) { 1743 bounds->setEmpty(); 1744 } 1745 return false; 1746 } 1747 1748 if (NULL != bounds) { 1749 *bounds = clip.getBounds(); 1750 } 1751 return true; 1752} 1753 1754const SkMatrix& SkCanvas::getTotalMatrix() const { 1755 return *fMCRec->fMatrix; 1756} 1757 1758#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE 1759SkCanvas::ClipType SkCanvas::getClipType() const { 1760 if (fMCRec->fRasterClip->isEmpty()) { 1761 return kEmpty_ClipType; 1762 } 1763 if (fMCRec->fRasterClip->isRect()) { 1764 return kRect_ClipType; 1765 } 1766 return kComplex_ClipType; 1767} 1768#endif 1769 1770#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP 1771const SkRegion& SkCanvas::getTotalClip() const { 1772 return fMCRec->fRasterClip->forceGetBW(); 1773} 1774#endif 1775 1776const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1777 return fMCRec->fRasterClip->forceGetBW(); 1778} 1779 1780void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const { 1781 path->reset(); 1782 1783 const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW(); 1784 if (rgn.isEmpty()) { 1785 return; 1786 } 1787 (void)rgn.getBoundaryPath(path); 1788} 1789 1790GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { 1791 SkBaseDevice* dev = this->getTopDevice(); 1792 return dev ? dev->accessRenderTarget() : NULL; 1793} 1794 1795SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) { 1796 SkBaseDevice* device = this->getTopDevice(); 1797 return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL; 1798} 1799 1800GrContext* SkCanvas::getGrContext() { 1801#if SK_SUPPORT_GPU 1802 SkBaseDevice* device = this->getTopDevice(); 1803 if (NULL != device) { 1804 GrRenderTarget* renderTarget = device->accessRenderTarget(); 1805 if (NULL != renderTarget) { 1806 return renderTarget->getContext(); 1807 } 1808 } 1809#endif 1810 1811 return NULL; 1812 1813} 1814 1815void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1816 const SkPaint& paint) { 1817 if (outer.isEmpty()) { 1818 return; 1819 } 1820 if (inner.isEmpty()) { 1821 this->drawRRect(outer, paint); 1822 return; 1823 } 1824 1825 // We don't have this method (yet), but technically this is what we should 1826 // be able to assert... 1827 // SkASSERT(outer.contains(inner)); 1828 // 1829 // For now at least check for containment of bounds 1830 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1831 1832 this->onDrawDRRect(outer, inner, paint); 1833} 1834 1835////////////////////////////////////////////////////////////////////////////// 1836// These are the virtual drawing methods 1837////////////////////////////////////////////////////////////////////////////// 1838 1839void SkCanvas::clear(SkColor color) { 1840 SkDrawIter iter(this); 1841 this->predrawNotify(); 1842 while (iter.next()) { 1843 iter.fDevice->clear(color); 1844 } 1845} 1846 1847void SkCanvas::drawPaint(const SkPaint& paint) { 1848 this->internalDrawPaint(paint); 1849} 1850 1851void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1852 CHECK_SHADER_NOSETCONTEXT(paint); 1853 1854 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 1855 1856 while (iter.next()) { 1857 iter.fDevice->drawPaint(iter, looper.paint()); 1858 } 1859 1860 LOOPER_END 1861} 1862 1863void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 1864 const SkPaint& paint) { 1865 if ((long)count <= 0) { 1866 return; 1867 } 1868 1869 CHECK_SHADER_NOSETCONTEXT(paint); 1870 1871 SkRect r, storage; 1872 const SkRect* bounds = NULL; 1873 if (paint.canComputeFastBounds()) { 1874 // special-case 2 points (common for drawing a single line) 1875 if (2 == count) { 1876 r.set(pts[0], pts[1]); 1877 } else { 1878 r.set(pts, SkToInt(count)); 1879 } 1880 bounds = &paint.computeFastStrokeBounds(r, &storage); 1881 if (this->quickReject(*bounds)) { 1882 return; 1883 } 1884 } 1885 1886 SkASSERT(pts != NULL); 1887 1888 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 1889 1890 while (iter.next()) { 1891 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1892 } 1893 1894 LOOPER_END 1895} 1896 1897void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1898 CHECK_SHADER_NOSETCONTEXT(paint); 1899 1900 SkRect storage; 1901 const SkRect* bounds = NULL; 1902 if (paint.canComputeFastBounds()) { 1903 bounds = &paint.computeFastBounds(r, &storage); 1904 if (this->quickReject(*bounds)) { 1905 return; 1906 } 1907 } 1908 1909 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 1910 1911 while (iter.next()) { 1912 iter.fDevice->drawRect(iter, r, looper.paint()); 1913 } 1914 1915 LOOPER_END 1916} 1917 1918void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1919 CHECK_SHADER_NOSETCONTEXT(paint); 1920 1921 SkRect storage; 1922 const SkRect* bounds = NULL; 1923 if (paint.canComputeFastBounds()) { 1924 bounds = &paint.computeFastBounds(oval, &storage); 1925 if (this->quickReject(*bounds)) { 1926 return; 1927 } 1928 } 1929 1930 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 1931 1932 while (iter.next()) { 1933 iter.fDevice->drawOval(iter, oval, looper.paint()); 1934 } 1935 1936 LOOPER_END 1937} 1938 1939void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1940 CHECK_SHADER_NOSETCONTEXT(paint); 1941 1942 SkRect storage; 1943 const SkRect* bounds = NULL; 1944 if (paint.canComputeFastBounds()) { 1945 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 1946 if (this->quickReject(*bounds)) { 1947 return; 1948 } 1949 } 1950 1951 if (rrect.isRect()) { 1952 // call the non-virtual version 1953 this->SkCanvas::drawRect(rrect.getBounds(), paint); 1954 return; 1955 } else if (rrect.isOval()) { 1956 // call the non-virtual version 1957 this->SkCanvas::drawOval(rrect.getBounds(), paint); 1958 return; 1959 } 1960 1961 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1962 1963 while (iter.next()) { 1964 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1965 } 1966 1967 LOOPER_END 1968} 1969 1970void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1971 const SkPaint& paint) { 1972 CHECK_SHADER_NOSETCONTEXT(paint); 1973 1974 SkRect storage; 1975 const SkRect* bounds = NULL; 1976 if (paint.canComputeFastBounds()) { 1977 bounds = &paint.computeFastBounds(outer.getBounds(), &storage); 1978 if (this->quickReject(*bounds)) { 1979 return; 1980 } 1981 } 1982 1983 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1984 1985 while (iter.next()) { 1986 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 1987 } 1988 1989 LOOPER_END 1990} 1991 1992void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1993 CHECK_SHADER_NOSETCONTEXT(paint); 1994 1995 if (!path.isFinite()) { 1996 return; 1997 } 1998 1999 SkRect storage; 2000 const SkRect* bounds = NULL; 2001 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 2002 const SkRect& pathBounds = path.getBounds(); 2003 bounds = &paint.computeFastBounds(pathBounds, &storage); 2004 if (this->quickReject(*bounds)) { 2005 return; 2006 } 2007 } 2008 2009 const SkRect& r = path.getBounds(); 2010 if (r.width() <= 0 && r.height() <= 0) { 2011 if (path.isInverseFillType()) { 2012 this->internalDrawPaint(paint); 2013 } 2014 return; 2015 } 2016 2017 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 2018 2019 while (iter.next()) { 2020 iter.fDevice->drawPath(iter, path, looper.paint()); 2021 } 2022 2023 LOOPER_END 2024} 2025 2026void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 2027 const SkPaint* paint) { 2028 SkDEBUGCODE(bitmap.validate();) 2029 2030 if (NULL == paint || paint->canComputeFastBounds()) { 2031 SkRect bounds = { 2032 x, y, 2033 x + SkIntToScalar(bitmap.width()), 2034 y + SkIntToScalar(bitmap.height()) 2035 }; 2036 if (paint) { 2037 (void)paint->computeFastBounds(bounds, &bounds); 2038 } 2039 if (this->quickReject(bounds)) { 2040 return; 2041 } 2042 } 2043 2044 SkMatrix matrix; 2045 matrix.setTranslate(x, y); 2046 this->internalDrawBitmap(bitmap, matrix, paint); 2047} 2048 2049// this one is non-virtual, so it can be called safely by other canvas apis 2050void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2051 const SkRect& dst, const SkPaint* paint, 2052 DrawBitmapRectFlags flags) { 2053 if (bitmap.drawsNothing() || dst.isEmpty()) { 2054 return; 2055 } 2056 2057 CHECK_LOCKCOUNT_BALANCE(bitmap); 2058 2059 SkRect storage; 2060 const SkRect* bounds = &dst; 2061 if (NULL == paint || paint->canComputeFastBounds()) { 2062 if (paint) { 2063 bounds = &paint->computeFastBounds(dst, &storage); 2064 } 2065 if (this->quickReject(*bounds)) { 2066 return; 2067 } 2068 } 2069 2070 SkLazyPaint lazy; 2071 if (NULL == paint) { 2072 paint = lazy.init(); 2073 } 2074 2075 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 2076 2077 while (iter.next()) { 2078 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 2079 } 2080 2081 LOOPER_END 2082} 2083 2084void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 2085 const SkRect& dst, const SkPaint* paint, 2086 DrawBitmapRectFlags flags) { 2087 SkDEBUGCODE(bitmap.validate();) 2088 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 2089} 2090 2091void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 2092 const SkPaint* paint) { 2093 SkDEBUGCODE(bitmap.validate();) 2094 this->internalDrawBitmap(bitmap, matrix, paint); 2095} 2096 2097void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 2098 const SkIRect& center, const SkRect& dst, 2099 const SkPaint* paint) { 2100 if (bitmap.drawsNothing()) { 2101 return; 2102 } 2103 if (NULL == paint || paint->canComputeFastBounds()) { 2104 SkRect storage; 2105 const SkRect* bounds = &dst; 2106 if (paint) { 2107 bounds = &paint->computeFastBounds(dst, &storage); 2108 } 2109 if (this->quickReject(*bounds)) { 2110 return; 2111 } 2112 } 2113 2114 const int32_t w = bitmap.width(); 2115 const int32_t h = bitmap.height(); 2116 2117 SkIRect c = center; 2118 // pin center to the bounds of the bitmap 2119 c.fLeft = SkMax32(0, center.fLeft); 2120 c.fTop = SkMax32(0, center.fTop); 2121 c.fRight = SkPin32(center.fRight, c.fLeft, w); 2122 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 2123 2124 const SkScalar srcX[4] = { 2125 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 2126 }; 2127 const SkScalar srcY[4] = { 2128 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 2129 }; 2130 SkScalar dstX[4] = { 2131 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 2132 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 2133 }; 2134 SkScalar dstY[4] = { 2135 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 2136 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 2137 }; 2138 2139 if (dstX[1] > dstX[2]) { 2140 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 2141 dstX[2] = dstX[1]; 2142 } 2143 2144 if (dstY[1] > dstY[2]) { 2145 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 2146 dstY[2] = dstY[1]; 2147 } 2148 2149 for (int y = 0; y < 3; y++) { 2150 SkRect s, d; 2151 2152 s.fTop = srcY[y]; 2153 s.fBottom = srcY[y+1]; 2154 d.fTop = dstY[y]; 2155 d.fBottom = dstY[y+1]; 2156 for (int x = 0; x < 3; x++) { 2157 s.fLeft = srcX[x]; 2158 s.fRight = srcX[x+1]; 2159 d.fLeft = dstX[x]; 2160 d.fRight = dstX[x+1]; 2161 this->internalDrawBitmapRect(bitmap, &s, d, paint, 2162 kNone_DrawBitmapRectFlag); 2163 } 2164 } 2165} 2166 2167void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 2168 const SkRect& dst, const SkPaint* paint) { 2169 SkDEBUGCODE(bitmap.validate();) 2170 2171 // Need a device entry-point, so gpu can use a mesh 2172 this->internalDrawBitmapNine(bitmap, center, dst, paint); 2173} 2174 2175class SkDeviceFilteredPaint { 2176public: 2177 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2178 SkBaseDevice::TextFlags flags; 2179 if (device->filterTextFlags(paint, &flags)) { 2180 SkPaint* newPaint = fLazy.set(paint); 2181 newPaint->setFlags(flags.fFlags); 2182 newPaint->setHinting(flags.fHinting); 2183 fPaint = newPaint; 2184 } else { 2185 fPaint = &paint; 2186 } 2187 } 2188 2189 const SkPaint& paint() const { return *fPaint; } 2190 2191private: 2192 const SkPaint* fPaint; 2193 SkLazyPaint fLazy; 2194}; 2195 2196void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2197 const SkRect& r, SkScalar textSize) { 2198 if (paint.getStyle() == SkPaint::kFill_Style) { 2199 draw.fDevice->drawRect(draw, r, paint); 2200 } else { 2201 SkPaint p(paint); 2202 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2203 draw.fDevice->drawRect(draw, r, p); 2204 } 2205} 2206 2207void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2208 const char text[], size_t byteLength, 2209 SkScalar x, SkScalar y) { 2210 SkASSERT(byteLength == 0 || text != NULL); 2211 2212 // nothing to draw 2213 if (text == NULL || byteLength == 0 || 2214 draw.fClip->isEmpty() || 2215 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2216 return; 2217 } 2218 2219 SkScalar width = 0; 2220 SkPoint start; 2221 2222 start.set(0, 0); // to avoid warning 2223 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2224 SkPaint::kStrikeThruText_Flag)) { 2225 width = paint.measureText(text, byteLength); 2226 2227 SkScalar offsetX = 0; 2228 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2229 offsetX = SkScalarHalf(width); 2230 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2231 offsetX = width; 2232 } 2233 start.set(x - offsetX, y); 2234 } 2235 2236 if (0 == width) { 2237 return; 2238 } 2239 2240 uint32_t flags = paint.getFlags(); 2241 2242 if (flags & (SkPaint::kUnderlineText_Flag | 2243 SkPaint::kStrikeThruText_Flag)) { 2244 SkScalar textSize = paint.getTextSize(); 2245 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2246 SkRect r; 2247 2248 r.fLeft = start.fX; 2249 r.fRight = start.fX + width; 2250 2251 if (flags & SkPaint::kUnderlineText_Flag) { 2252 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2253 start.fY); 2254 r.fTop = offset; 2255 r.fBottom = offset + height; 2256 DrawRect(draw, paint, r, textSize); 2257 } 2258 if (flags & SkPaint::kStrikeThruText_Flag) { 2259 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2260 start.fY); 2261 r.fTop = offset; 2262 r.fBottom = offset + height; 2263 DrawRect(draw, paint, r, textSize); 2264 } 2265 } 2266} 2267 2268void SkCanvas::drawText(const void* text, size_t byteLength, 2269 SkScalar x, SkScalar y, const SkPaint& paint) { 2270 CHECK_SHADER_NOSETCONTEXT(paint); 2271 2272 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2273 2274 while (iter.next()) { 2275 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2276 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2277 DrawTextDecorations(iter, dfp.paint(), 2278 static_cast<const char*>(text), byteLength, x, y); 2279 } 2280 2281 LOOPER_END 2282} 2283 2284void SkCanvas::drawPosText(const void* text, size_t byteLength, 2285 const SkPoint pos[], const SkPaint& paint) { 2286 CHECK_SHADER_NOSETCONTEXT(paint); 2287 2288 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2289 2290 while (iter.next()) { 2291 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2292 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 2293 dfp.paint()); 2294 } 2295 2296 LOOPER_END 2297} 2298 2299void SkCanvas::drawPosTextH(const void* text, size_t byteLength, 2300 const SkScalar xpos[], SkScalar constY, 2301 const SkPaint& paint) { 2302 CHECK_SHADER_NOSETCONTEXT(paint); 2303 2304 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2305 2306 while (iter.next()) { 2307 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2308 iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 2309 dfp.paint()); 2310 } 2311 2312 LOOPER_END 2313} 2314 2315void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 2316 const SkPath& path, const SkMatrix* matrix, 2317 const SkPaint& paint) { 2318 CHECK_SHADER_NOSETCONTEXT(paint); 2319 2320 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2321 2322 while (iter.next()) { 2323 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2324 matrix, looper.paint()); 2325 } 2326 2327 LOOPER_END 2328} 2329 2330void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 2331 const SkPoint verts[], const SkPoint texs[], 2332 const SkColor colors[], SkXfermode* xmode, 2333 const uint16_t indices[], int indexCount, 2334 const SkPaint& paint) { 2335 CHECK_SHADER_NOSETCONTEXT(paint); 2336 2337 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2338 2339 while (iter.next()) { 2340 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2341 colors, xmode, indices, indexCount, 2342 looper.paint()); 2343 } 2344 2345 LOOPER_END 2346} 2347 2348////////////////////////////////////////////////////////////////////////////// 2349// These methods are NOT virtual, and therefore must call back into virtual 2350// methods, rather than actually drawing themselves. 2351////////////////////////////////////////////////////////////////////////////// 2352 2353void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2354 SkXfermode::Mode mode) { 2355 SkPaint paint; 2356 2357 paint.setARGB(a, r, g, b); 2358 if (SkXfermode::kSrcOver_Mode != mode) { 2359 paint.setXfermodeMode(mode); 2360 } 2361 this->drawPaint(paint); 2362} 2363 2364void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2365 SkPaint paint; 2366 2367 paint.setColor(c); 2368 if (SkXfermode::kSrcOver_Mode != mode) { 2369 paint.setXfermodeMode(mode); 2370 } 2371 this->drawPaint(paint); 2372} 2373 2374void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2375 SkPoint pt; 2376 2377 pt.set(x, y); 2378 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2379} 2380 2381void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2382 SkPoint pt; 2383 SkPaint paint; 2384 2385 pt.set(x, y); 2386 paint.setColor(color); 2387 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2388} 2389 2390void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2391 const SkPaint& paint) { 2392 SkPoint pts[2]; 2393 2394 pts[0].set(x0, y0); 2395 pts[1].set(x1, y1); 2396 this->drawPoints(kLines_PointMode, 2, pts, paint); 2397} 2398 2399void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2400 SkScalar right, SkScalar bottom, 2401 const SkPaint& paint) { 2402 SkRect r; 2403 2404 r.set(left, top, right, bottom); 2405 this->drawRect(r, paint); 2406} 2407 2408void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2409 const SkPaint& paint) { 2410 if (radius < 0) { 2411 radius = 0; 2412 } 2413 2414 SkRect r; 2415 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2416 this->drawOval(r, paint); 2417} 2418 2419void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2420 const SkPaint& paint) { 2421 if (rx > 0 && ry > 0) { 2422 if (paint.canComputeFastBounds()) { 2423 SkRect storage; 2424 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2425 return; 2426 } 2427 } 2428 SkRRect rrect; 2429 rrect.setRectXY(r, rx, ry); 2430 this->drawRRect(rrect, paint); 2431 } else { 2432 this->drawRect(r, paint); 2433 } 2434} 2435 2436void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2437 SkScalar sweepAngle, bool useCenter, 2438 const SkPaint& paint) { 2439 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2440 this->drawOval(oval, paint); 2441 } else { 2442 SkPath path; 2443 if (useCenter) { 2444 path.moveTo(oval.centerX(), oval.centerY()); 2445 } 2446 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2447 if (useCenter) { 2448 path.close(); 2449 } 2450 this->drawPath(path, paint); 2451 } 2452} 2453 2454void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2455 const SkPath& path, SkScalar hOffset, 2456 SkScalar vOffset, const SkPaint& paint) { 2457 SkMatrix matrix; 2458 2459 matrix.setTranslate(hOffset, vOffset); 2460 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2461} 2462 2463/////////////////////////////////////////////////////////////////////////////// 2464 2465void SkCanvas::drawPicture(SkPicture& picture) { 2466 picture.draw(this); 2467} 2468 2469/////////////////////////////////////////////////////////////////////////////// 2470/////////////////////////////////////////////////////////////////////////////// 2471 2472SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2473 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 2474 2475 SkASSERT(canvas); 2476 2477 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2478 fDone = !fImpl->next(); 2479} 2480 2481SkCanvas::LayerIter::~LayerIter() { 2482 fImpl->~SkDrawIter(); 2483} 2484 2485void SkCanvas::LayerIter::next() { 2486 fDone = !fImpl->next(); 2487} 2488 2489SkBaseDevice* SkCanvas::LayerIter::device() const { 2490 return fImpl->getDevice(); 2491} 2492 2493const SkMatrix& SkCanvas::LayerIter::matrix() const { 2494 return fImpl->getMatrix(); 2495} 2496 2497const SkPaint& SkCanvas::LayerIter::paint() const { 2498 const SkPaint* paint = fImpl->getPaint(); 2499 if (NULL == paint) { 2500 paint = &fDefaultPaint; 2501 } 2502 return *paint; 2503} 2504 2505const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2506int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2507int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2508 2509/////////////////////////////////////////////////////////////////////////////// 2510 2511SkCanvas::ClipVisitor::~ClipVisitor() { } 2512 2513/////////////////////////////////////////////////////////////////////////////// 2514 2515static bool supported_for_raster_canvas(const SkImageInfo& info) { 2516 switch (info.alphaType()) { 2517 case kPremul_SkAlphaType: 2518 case kOpaque_SkAlphaType: 2519 break; 2520 default: 2521 return false; 2522 } 2523 2524 switch (info.colorType()) { 2525 case kAlpha_8_SkColorType: 2526 case kRGB_565_SkColorType: 2527 case kPMColor_SkColorType: 2528 break; 2529 default: 2530 return false; 2531 } 2532 2533 return true; 2534} 2535 2536SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) { 2537 if (!supported_for_raster_canvas(info)) { 2538 return NULL; 2539 } 2540 2541 SkBitmap bitmap; 2542 if (!bitmap.allocPixels(info)) { 2543 return NULL; 2544 } 2545 2546 // should this functionality be moved into allocPixels()? 2547 if (!bitmap.info().isOpaque()) { 2548 bitmap.eraseColor(0); 2549 } 2550 return SkNEW_ARGS(SkCanvas, (bitmap)); 2551} 2552