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