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