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