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