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