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