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