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