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