SkCanvas.cpp revision f622a6c8fd176acf9944de8df00d7f0bb56b67d3
1/* 2 * Copyright 2008 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCanvas.h" 9#include "SkCanvasPriv.h" 10#include "SkBitmapDevice.h" 11#include "SkDeviceImageFilterProxy.h" 12#include "SkDraw.h" 13#include "SkDrawFilter.h" 14#include "SkDrawLooper.h" 15#include "SkImage.h" 16#include "SkMetaData.h" 17#include "SkPathOps.h" 18#include "SkPatchUtils.h" 19#include "SkPicture.h" 20#include "SkRasterClip.h" 21#include "SkRRect.h" 22#include "SkSmallAllocator.h" 23#include "SkSurface_Base.h" 24#include "SkTemplates.h" 25#include "SkTextBlob.h" 26#include "SkTextFormatParams.h" 27#include "SkTLazy.h" 28#include "SkUtils.h" 29 30#if SK_SUPPORT_GPU 31#include "GrRenderTarget.h" 32#endif 33 34// experimental for faster tiled drawing... 35//#define SK_ENABLE_CLIP_QUICKREJECT 36 37//#define SK_TRACE_SAVERESTORE 38 39#ifdef SK_TRACE_SAVERESTORE 40 static int gLayerCounter; 41 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 42 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 43 44 static int gRecCounter; 45 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 46 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 47 48 static int gCanvasCounter; 49 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 50 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 51#else 52 #define inc_layer() 53 #define dec_layer() 54 #define inc_rec() 55 #define dec_rec() 56 #define inc_canvas() 57 #define dec_canvas() 58#endif 59 60typedef SkTLazy<SkPaint> SkLazyPaint; 61 62void SkCanvas::predrawNotify() { 63 if (fSurfaceBase) { 64 fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); 65 } 66} 67 68/////////////////////////////////////////////////////////////////////////////// 69 70static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) { 71 const uint32_t propFlags = props.flags(); 72 if (propFlags & SkSurfaceProps::kDisallowDither_Flag) { 73 flags &= ~SkPaint::kDither_Flag; 74 } 75 if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) { 76 flags &= ~SkPaint::kAntiAlias_Flag; 77 } 78 return flags; 79} 80 81/////////////////////////////////////////////////////////////////////////////// 82 83/* This is the record we keep for each SkBaseDevice that the user installs. 84 The clip/matrix/proc are fields that reflect the top of the save/restore 85 stack. Whenever the canvas changes, it marks a dirty flag, and then before 86 these are used (assuming we're not on a layer) we rebuild these cache 87 values: they reflect the top of the save stack, but translated and clipped 88 by the device's XY offset and bitmap-bounds. 89*/ 90struct DeviceCM { 91 DeviceCM* fNext; 92 SkBaseDevice* fDevice; 93 SkRasterClip fClip; 94 const SkMatrix* fMatrix; 95 SkPaint* fPaint; // may be null (in the future) 96 97 DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas, 98 bool conservativeRasterClip) 99 : fNext(NULL) 100 , fClip(conservativeRasterClip) 101 { 102 if (NULL != device) { 103 device->ref(); 104 device->onAttachToCanvas(canvas); 105 } 106 fDevice = device; 107 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 108 } 109 110 ~DeviceCM() { 111 if (fDevice) { 112 fDevice->onDetachFromCanvas(); 113 fDevice->unref(); 114 } 115 SkDELETE(fPaint); 116 } 117 118 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 119 const SkClipStack& clipStack, SkRasterClip* updateClip) { 120 int x = fDevice->getOrigin().x(); 121 int y = fDevice->getOrigin().y(); 122 int width = fDevice->width(); 123 int height = fDevice->height(); 124 125 if ((x | y) == 0) { 126 fMatrix = &totalMatrix; 127 fClip = totalClip; 128 } else { 129 fMatrixStorage = totalMatrix; 130 fMatrixStorage.postTranslate(SkIntToScalar(-x), 131 SkIntToScalar(-y)); 132 fMatrix = &fMatrixStorage; 133 134 totalClip.translate(-x, -y, &fClip); 135 } 136 137 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 138 139 // intersect clip, but don't translate it (yet) 140 141 if (updateClip) { 142 updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 143 SkRegion::kDifference_Op); 144 } 145 146 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 147 148#ifdef SK_DEBUG 149 if (!fClip.isEmpty()) { 150 SkIRect deviceR; 151 deviceR.set(0, 0, width, height); 152 SkASSERT(deviceR.contains(fClip.getBounds())); 153 } 154#endif 155 } 156 157private: 158 SkMatrix fMatrixStorage; 159}; 160 161/* This is the record we keep for each save/restore level in the stack. 162 Since a level optionally copies the matrix and/or stack, we have pointers 163 for these fields. If the value is copied for this level, the copy is 164 stored in the ...Storage field, and the pointer points to that. If the 165 value is not copied for this level, we ignore ...Storage, and just point 166 at the corresponding value in the previous level in the stack. 167*/ 168class SkCanvas::MCRec { 169public: 170 SkRasterClip fRasterClip; 171 SkMatrix fMatrix; 172 SkDrawFilter* fFilter; // the current filter (or null) 173 DeviceCM* fLayer; 174 /* If there are any layers in the stack, this points to the top-most 175 one that is at or below this level in the stack (so we know what 176 bitmap/device to draw into from this level. This value is NOT 177 reference counted, since the real owner is either our fLayer field, 178 or a previous one in a lower level.) 179 */ 180 DeviceCM* fTopLayer; 181 182 MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { 183 fMatrix.reset(); 184 fFilter = NULL; 185 fLayer = NULL; 186 fTopLayer = NULL; 187 188 // don't bother initializing fNext 189 inc_rec(); 190 } 191 MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) { 192 fMatrix = prev.fMatrix; 193 fFilter = SkSafeRef(prev.fFilter); 194 fLayer = NULL; 195 fTopLayer = prev.fTopLayer; 196 197 // don't bother initializing fNext 198 inc_rec(); 199 } 200 ~MCRec() { 201 SkSafeUnref(fFilter); 202 SkDELETE(fLayer); 203 dec_rec(); 204 } 205}; 206 207class SkDrawIter : public SkDraw { 208public: 209 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 210 canvas = canvas->canvasForDrawIter(); 211 fCanvas = canvas; 212 canvas->updateDeviceCMCache(); 213 214 fClipStack = &canvas->fClipStack; 215 fCurrLayer = canvas->fMCRec->fTopLayer; 216 fSkipEmptyClips = skipEmptyClips; 217 } 218 219 bool next() { 220 // skip over recs with empty clips 221 if (fSkipEmptyClips) { 222 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 223 fCurrLayer = fCurrLayer->fNext; 224 } 225 } 226 227 const DeviceCM* rec = fCurrLayer; 228 if (rec && rec->fDevice) { 229 230 fMatrix = rec->fMatrix; 231 fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 232 fRC = &rec->fClip; 233 fDevice = rec->fDevice; 234 fBitmap = &fDevice->accessBitmap(true); 235 fPaint = rec->fPaint; 236 SkDEBUGCODE(this->validate();) 237 238 fCurrLayer = rec->fNext; 239 // fCurrLayer may be NULL now 240 241 return true; 242 } 243 return false; 244 } 245 246 SkBaseDevice* getDevice() const { return fDevice; } 247 int getX() const { return fDevice->getOrigin().x(); } 248 int getY() const { return fDevice->getOrigin().y(); } 249 const SkMatrix& getMatrix() const { return *fMatrix; } 250 const SkRegion& getClip() const { return *fClip; } 251 const SkPaint* getPaint() const { return fPaint; } 252 253private: 254 SkCanvas* fCanvas; 255 const DeviceCM* fCurrLayer; 256 const SkPaint* fPaint; // May be null. 257 SkBool8 fSkipEmptyClips; 258 259 typedef SkDraw INHERITED; 260}; 261 262///////////////////////////////////////////////////////////////////////////// 263 264class AutoDrawLooper { 265public: 266 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, 267 bool skipLayerForImageFilter = false, 268 const SkRect* bounds = NULL) : fOrigPaint(paint) { 269 fCanvas = canvas; 270 fFilter = canvas->getDrawFilter(); 271 fPaint = &fOrigPaint; 272 fSaveCount = canvas->getSaveCount(); 273 fDoClearImageFilter = false; 274 fDone = false; 275 276 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 277 SkPaint tmp; 278 tmp.setImageFilter(fOrigPaint.getImageFilter()); 279 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, 280 true, SkCanvas::kFullLayer_SaveLayerStrategy); 281 // we'll clear the imageFilter for the actual draws in next(), so 282 // it will only be applied during the restore(). 283 fDoClearImageFilter = true; 284 } 285 286 if (SkDrawLooper* looper = paint.getLooper()) { 287 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>( 288 looper->contextSize()); 289 fLooperContext = looper->createContext(canvas, buffer); 290 fIsSimple = false; 291 } else { 292 fLooperContext = NULL; 293 // can we be marked as simple? 294 fIsSimple = !fFilter && !fDoClearImageFilter; 295 } 296 297 uint32_t oldFlags = paint.getFlags(); 298 fNewPaintFlags = filter_paint_flags(props, oldFlags); 299 if (fIsSimple && (fNewPaintFlags != oldFlags)) { 300 SkPaint* paint = fLazyPaint.set(fOrigPaint); 301 paint->setFlags(fNewPaintFlags); 302 fPaint = paint; 303 // if we're not simple, doNext() will take care of calling setFlags() 304 } 305 } 306 307 ~AutoDrawLooper() { 308 if (fDoClearImageFilter) { 309 fCanvas->internalRestore(); 310 } 311 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 312 } 313 314 const SkPaint& paint() const { 315 SkASSERT(fPaint); 316 return *fPaint; 317 } 318 319 bool next(SkDrawFilter::Type drawType) { 320 if (fDone) { 321 return false; 322 } else if (fIsSimple) { 323 fDone = true; 324 return !fPaint->nothingToDraw(); 325 } else { 326 return this->doNext(drawType); 327 } 328 } 329 330private: 331 SkLazyPaint fLazyPaint; 332 SkCanvas* fCanvas; 333 const SkPaint& fOrigPaint; 334 SkDrawFilter* fFilter; 335 const SkPaint* fPaint; 336 int fSaveCount; 337 uint32_t fNewPaintFlags; 338 bool fDoClearImageFilter; 339 bool fDone; 340 bool fIsSimple; 341 SkDrawLooper::Context* fLooperContext; 342 SkSmallAllocator<1, 32> fLooperContextAllocator; 343 344 bool doNext(SkDrawFilter::Type drawType); 345}; 346 347bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 348 fPaint = NULL; 349 SkASSERT(!fIsSimple); 350 SkASSERT(fLooperContext || fFilter || fDoClearImageFilter); 351 352 SkPaint* paint = fLazyPaint.set(fOrigPaint); 353 paint->setFlags(fNewPaintFlags); 354 355 if (fDoClearImageFilter) { 356 paint->setImageFilter(NULL); 357 } 358 359 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 360 fDone = true; 361 return false; 362 } 363 if (fFilter) { 364 if (!fFilter->filter(paint, drawType)) { 365 fDone = true; 366 return false; 367 } 368 if (NULL == fLooperContext) { 369 // no looper means we only draw once 370 fDone = true; 371 } 372 } 373 fPaint = paint; 374 375 // if we only came in here for the imagefilter, mark us as done 376 if (!fLooperContext && !fFilter) { 377 fDone = true; 378 } 379 380 // call this after any possible paint modifiers 381 if (fPaint->nothingToDraw()) { 382 fPaint = NULL; 383 return false; 384 } 385 return true; 386} 387 388////////// macros to place around the internal draw calls ////////////////// 389 390#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ 391 this->predrawNotify(); \ 392 AutoDrawLooper looper(this, fProps, paint, true); \ 393 while (looper.next(type)) { \ 394 SkDrawIter iter(this); 395 396#define LOOPER_BEGIN(paint, type, bounds) \ 397 this->predrawNotify(); \ 398 AutoDrawLooper looper(this, fProps, paint, false, bounds); \ 399 while (looper.next(type)) { \ 400 SkDrawIter iter(this); 401 402#define LOOPER_END } 403 404//////////////////////////////////////////////////////////////////////////// 405 406void SkCanvas::setupDevice(SkBaseDevice* device) { 407 device->setPixelGeometry(fProps.pixelGeometry()); 408} 409 410SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { 411 fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag); 412 fCachedLocalClipBounds.setEmpty(); 413 fCachedLocalClipBoundsDirty = true; 414 fAllowSoftClip = true; 415 fAllowSimplifyClip = false; 416 fDeviceCMDirty = true; 417 fSaveLayerCount = 0; 418 fCullCount = 0; 419 fMetaData = NULL; 420 421 fMCRec = (MCRec*)fMCStack.push_back(); 422 new (fMCRec) MCRec(fConservativeRasterClip); 423 424 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip)); 425 fMCRec->fTopLayer = fMCRec->fLayer; 426 427 fSurfaceBase = NULL; 428 429 if (device) { 430 this->setupDevice(device); 431 if (device->forceConservativeRasterClip()) { 432 fConservativeRasterClip = true; 433 } 434 device->onAttachToCanvas(this); 435 fMCRec->fLayer->fDevice = SkRef(device); 436 fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->height())); 437 } 438 return device; 439} 440 441SkCanvas::SkCanvas() 442 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 443 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 444{ 445 inc_canvas(); 446 447 this->init(NULL, kDefault_InitFlags); 448} 449 450static SkBitmap make_nopixels(int width, int height) { 451 SkBitmap bitmap; 452 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); 453 return bitmap; 454} 455 456class SkNoPixelsBitmapDevice : public SkBitmapDevice { 457public: 458 SkNoPixelsBitmapDevice(int width, int height) : INHERITED(make_nopixels(width, height)) {} 459 460private: 461 462 typedef SkBitmapDevice INHERITED; 463}; 464 465SkCanvas::SkCanvas(int width, int height) 466 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 467 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 468{ 469 inc_canvas(); 470 471 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_InitFlags)->unref(); 472} 473 474SkCanvas::SkCanvas(int width, int height, InitFlags flags) 475 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 476 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 477{ 478 inc_canvas(); 479 480 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unref(); 481} 482 483SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags) 484 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 485 , fProps(SkSurfacePropsCopyOrDefault(props)) 486{ 487 inc_canvas(); 488 489 this->init(device, flags); 490} 491 492SkCanvas::SkCanvas(SkBaseDevice* device) 493 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 494 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 495{ 496 inc_canvas(); 497 498 this->init(device, kDefault_InitFlags); 499} 500 501SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) 502 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 503 , fProps(props) 504{ 505 inc_canvas(); 506 507 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); 508 this->init(device, kDefault_InitFlags); 509} 510 511SkCanvas::SkCanvas(const SkBitmap& bitmap) 512 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 513 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 514{ 515 inc_canvas(); 516 517 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); 518 this->init(device, kDefault_InitFlags); 519} 520 521SkCanvas::~SkCanvas() { 522 // free up the contents of our deque 523 this->restoreToCount(1); // restore everything but the last 524 SkASSERT(0 == fSaveLayerCount); 525 526 this->internalRestore(); // restore the last, since we're going away 527 528 SkDELETE(fMetaData); 529 530 dec_canvas(); 531} 532 533SkDrawFilter* SkCanvas::getDrawFilter() const { 534 return fMCRec->fFilter; 535} 536 537SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 538 SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 539 return filter; 540} 541 542SkMetaData& SkCanvas::getMetaData() { 543 // metadata users are rare, so we lazily allocate it. If that changes we 544 // can decide to just make it a field in the device (rather than a ptr) 545 if (NULL == fMetaData) { 546 fMetaData = new SkMetaData; 547 } 548 return *fMetaData; 549} 550 551/////////////////////////////////////////////////////////////////////////////// 552 553void SkCanvas::flush() { 554 SkBaseDevice* device = this->getDevice(); 555 if (device) { 556 device->flush(); 557 } 558} 559 560SkISize SkCanvas::getTopLayerSize() const { 561 SkBaseDevice* d = this->getTopDevice(); 562 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 563} 564 565SkIPoint SkCanvas::getTopLayerOrigin() const { 566 SkBaseDevice* d = this->getTopDevice(); 567 return d ? d->getOrigin() : SkIPoint::Make(0, 0); 568} 569 570SkISize SkCanvas::getBaseLayerSize() const { 571 SkBaseDevice* d = this->getDevice(); 572 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 573} 574 575SkBaseDevice* SkCanvas::getDevice() const { 576 // return root device 577 MCRec* rec = (MCRec*) fMCStack.front(); 578 SkASSERT(rec && rec->fLayer); 579 return rec->fLayer->fDevice; 580} 581 582SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 583 if (updateMatrixClip) { 584 const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 585 } 586 return fMCRec->fTopLayer->fDevice; 587} 588 589SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) { 590 // return root device 591 SkDeque::F2BIter iter(fMCStack); 592 MCRec* rec = (MCRec*)iter.next(); 593 SkASSERT(rec && rec->fLayer); 594 SkBaseDevice* rootDevice = rec->fLayer->fDevice; 595 596 if (rootDevice == device) { 597 return device; 598 } 599 600 if (device) { 601 device->onAttachToCanvas(this); 602 } 603 if (rootDevice) { 604 rootDevice->onDetachFromCanvas(); 605 } 606 607 SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 608 rootDevice = device; 609 this->setupDevice(device); 610 611 fDeviceCMDirty = true; 612 613 /* Now we update our initial region to have the bounds of the new device, 614 and then intersect all of the clips in our stack with these bounds, 615 to ensure that we can't draw outside of the device's bounds (and trash 616 memory). 617 618 NOTE: this is only a partial-fix, since if the new device is larger than 619 the previous one, we don't know how to "enlarge" the clips in our stack, 620 so drawing may be artificially restricted. Without keeping a history of 621 all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 622 reconstruct the correct clips, so this approximation will have to do. 623 The caller really needs to restore() back to the base if they want to 624 accurately take advantage of the new device bounds. 625 */ 626 627 SkIRect bounds; 628 if (device) { 629 bounds.set(0, 0, device->width(), device->height()); 630 } else { 631 bounds.setEmpty(); 632 } 633 // now jam our 1st clip to be bounds, and intersect the rest with that 634 rec->fRasterClip.setRect(bounds); 635 while ((rec = (MCRec*)iter.next()) != NULL) { 636 (void)rec->fRasterClip.op(bounds, SkRegion::kIntersect_Op); 637 } 638 639 return device; 640} 641 642bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) { 643 if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) { 644 return false; 645 } 646 647 bool weAllocated = false; 648 if (NULL == bitmap->pixelRef()) { 649 if (!bitmap->tryAllocPixels()) { 650 return false; 651 } 652 weAllocated = true; 653 } 654 655 SkBitmap bm(*bitmap); 656 bm.lockPixels(); 657 if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) { 658 return true; 659 } 660 661 if (weAllocated) { 662 bitmap->setPixelRef(NULL); 663 } 664 return false; 665} 666 667bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 668 SkIRect r = srcRect; 669 const SkISize size = this->getBaseLayerSize(); 670 if (!r.intersect(0, 0, size.width(), size.height())) { 671 bitmap->reset(); 672 return false; 673 } 674 675 if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) { 676 // bitmap will already be reset. 677 return false; 678 } 679 if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) { 680 bitmap->reset(); 681 return false; 682 } 683 return true; 684} 685 686bool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) { 687 switch (origInfo.colorType()) { 688 case kUnknown_SkColorType: 689 case kIndex_8_SkColorType: 690 return false; 691 default: 692 break; 693 } 694 if (NULL == dstP || rowBytes < origInfo.minRowBytes()) { 695 return false; 696 } 697 if (0 == origInfo.width() || 0 == origInfo.height()) { 698 return false; 699 } 700 701 SkBaseDevice* device = this->getDevice(); 702 if (!device) { 703 return false; 704 } 705 706 const SkISize size = this->getBaseLayerSize(); 707 SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height()); 708 if (!srcR.intersect(0, 0, size.width(), size.height())) { 709 return false; 710 } 711 712 // the intersect may have shrunk info's logical size 713 const SkImageInfo info = origInfo.makeWH(srcR.width(), srcR.height()); 714 715 // if x or y are negative, then we have to adjust pixels 716 if (x > 0) { 717 x = 0; 718 } 719 if (y > 0) { 720 y = 0; 721 } 722 // here x,y are either 0 or negative 723 dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel()); 724 725 // The device can assert that the requested area is always contained in its bounds 726 return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y()); 727} 728 729bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 730 if (bitmap.getTexture()) { 731 return false; 732 } 733 SkBitmap bm(bitmap); 734 bm.lockPixels(); 735 if (bm.getPixels()) { 736 return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y); 737 } 738 return false; 739} 740 741bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes, 742 int x, int y) { 743 switch (origInfo.colorType()) { 744 case kUnknown_SkColorType: 745 case kIndex_8_SkColorType: 746 return false; 747 default: 748 break; 749 } 750 if (NULL == pixels || rowBytes < origInfo.minRowBytes()) { 751 return false; 752 } 753 754 const SkISize size = this->getBaseLayerSize(); 755 SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height()); 756 if (!target.intersect(0, 0, size.width(), size.height())) { 757 return false; 758 } 759 760 SkBaseDevice* device = this->getDevice(); 761 if (!device) { 762 return false; 763 } 764 765 // the intersect may have shrunk info's logical size 766 const SkImageInfo info = origInfo.makeWH(target.width(), target.height()); 767 768 // if x or y are negative, then we have to adjust pixels 769 if (x > 0) { 770 x = 0; 771 } 772 if (y > 0) { 773 y = 0; 774 } 775 // here x,y are either 0 or negative 776 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel()); 777 778 // Tell our owning surface to bump its generation ID 779 this->predrawNotify(); 780 781 // The device can assert that the requested area is always contained in its bounds 782 return device->writePixels(info, pixels, rowBytes, target.x(), target.y()); 783} 784 785SkCanvas* SkCanvas::canvasForDrawIter() { 786 return this; 787} 788 789////////////////////////////////////////////////////////////////////////////// 790 791void SkCanvas::updateDeviceCMCache() { 792 if (fDeviceCMDirty) { 793 const SkMatrix& totalMatrix = this->getTotalMatrix(); 794 const SkRasterClip& totalClip = fMCRec->fRasterClip; 795 DeviceCM* layer = fMCRec->fTopLayer; 796 797 if (NULL == layer->fNext) { // only one layer 798 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 799 } else { 800 SkRasterClip clip(totalClip); 801 do { 802 layer->updateMC(totalMatrix, clip, fClipStack, &clip); 803 } while ((layer = layer->fNext) != NULL); 804 } 805 fDeviceCMDirty = false; 806 } 807} 808 809/////////////////////////////////////////////////////////////////////////////// 810 811int SkCanvas::internalSave() { 812 int saveCount = this->getSaveCount(); // record this before the actual save 813 814 MCRec* newTop = (MCRec*)fMCStack.push_back(); 815 new (newTop) MCRec(*fMCRec); // balanced in restore() 816 fMCRec = newTop; 817 818 fClipStack.save(); 819 820 return saveCount; 821} 822 823int SkCanvas::save() { 824 this->willSave(); 825 return this->internalSave(); 826} 827 828static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 829#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 830 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 831#else 832 return true; 833#endif 834} 835 836bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 837 SkIRect* intersection, const SkImageFilter* imageFilter) { 838 SkIRect clipBounds; 839 SkRegion::Op op = SkRegion::kIntersect_Op; 840 if (!this->getClipDeviceBounds(&clipBounds)) { 841 return false; 842 } 843 844 if (imageFilter) { 845 imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds); 846 // Filters may grow the bounds beyond the device bounds. 847 op = SkRegion::kReplace_Op; 848 } 849 SkIRect ir; 850 if (bounds) { 851 SkRect r; 852 853 this->getTotalMatrix().mapRect(&r, *bounds); 854 r.roundOut(&ir); 855 // early exit if the layer's bounds are clipped out 856 if (!ir.intersect(clipBounds)) { 857 if (bounds_affects_clip(flags)) { 858 fMCRec->fRasterClip.setEmpty(); 859 } 860 return false; 861 } 862 } else { // no user bounds, so just use the clip 863 ir = clipBounds; 864 } 865 866 if (bounds_affects_clip(flags)) { 867 fClipStack.clipDevRect(ir, op); 868 // early exit if the clip is now empty 869 if (!fMCRec->fRasterClip.op(ir, op)) { 870 return false; 871 } 872 } 873 874 if (intersection) { 875 *intersection = ir; 876 } 877 return true; 878} 879 880int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) { 881 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag); 882 return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy); 883} 884 885int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 886 SaveFlags flags) { 887 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags); 888 return this->internalSaveLayer(bounds, paint, flags, false, strategy); 889} 890 891int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags, 892 bool justForImageFilter, SaveLayerStrategy strategy) { 893#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 894 flags |= kClipToLayer_SaveFlag; 895#endif 896 897 // do this before we create the layer. We don't call the public save() since 898 // that would invoke a possibly overridden virtual 899 int count = this->internalSave(); 900 901 fDeviceCMDirty = true; 902 903 SkIRect ir; 904 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) { 905 return count; 906 } 907 908 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 909 // the clipRectBounds() call above? 910 if (kNoLayer_SaveLayerStrategy == strategy) { 911 return count; 912 } 913 914 // Kill the imagefilter if our device doesn't allow it 915 SkLazyPaint lazyP; 916 if (paint && paint->getImageFilter()) { 917 if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 918 if (justForImageFilter) { 919 // early exit if the layer was just for the imageFilter 920 return count; 921 } 922 SkPaint* p = lazyP.set(*paint); 923 p->setImageFilter(NULL); 924 paint = p; 925 } 926 } 927 928 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); 929 SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(), 930 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 931 932 SkBaseDevice* device; 933 if (paint && paint->getImageFilter()) { 934 device = this->getDevice(); 935 if (device) { 936 device = device->createCompatibleDeviceForImageFilter(info); 937 } 938 } else { 939 device = this->createLayerDevice(info); 940 } 941 if (NULL == device) { 942 SkDebugf("Unable to create device for layer."); 943 return count; 944 } 945 this->setupDevice(device); 946 947 device->setOrigin(ir.fLeft, ir.fTop); 948 DeviceCM* layer = SkNEW_ARGS(DeviceCM, 949 (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip)); 950 device->unref(); 951 952 layer->fNext = fMCRec->fTopLayer; 953 fMCRec->fLayer = layer; 954 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 955 956 fSaveLayerCount += 1; 957 return count; 958} 959 960int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 961 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); 962} 963 964int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 965 SaveFlags flags) { 966 if (0xFF == alpha) { 967 return this->saveLayer(bounds, NULL, flags); 968 } else { 969 SkPaint tmpPaint; 970 tmpPaint.setAlpha(alpha); 971 return this->saveLayer(bounds, &tmpPaint, flags); 972 } 973} 974 975void SkCanvas::restore() { 976 // check for underflow 977 if (fMCStack.count() > 1) { 978 this->willRestore(); 979 this->internalRestore(); 980 this->didRestore(); 981 } 982} 983 984void SkCanvas::internalRestore() { 985 SkASSERT(fMCStack.count() != 0); 986 987 fDeviceCMDirty = true; 988 fCachedLocalClipBoundsDirty = true; 989 990 fClipStack.restore(); 991 992 // reserve our layer (if any) 993 DeviceCM* layer = fMCRec->fLayer; // may be null 994 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 995 fMCRec->fLayer = NULL; 996 997 // now do the normal restore() 998 fMCRec->~MCRec(); // balanced in save() 999 fMCStack.pop_back(); 1000 fMCRec = (MCRec*)fMCStack.back(); 1001 1002 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1003 since if we're being recorded, we don't want to record this (the 1004 recorder will have already recorded the restore). 1005 */ 1006 if (layer) { 1007 if (layer->fNext) { 1008 const SkIPoint& origin = layer->fDevice->getOrigin(); 1009 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1010 layer->fPaint); 1011 // reset this, since internalDrawDevice will have set it to true 1012 fDeviceCMDirty = true; 1013 1014 SkASSERT(fSaveLayerCount > 0); 1015 fSaveLayerCount -= 1; 1016 } 1017 SkDELETE(layer); 1018 } 1019} 1020 1021int SkCanvas::getSaveCount() const { 1022 return fMCStack.count(); 1023} 1024 1025void SkCanvas::restoreToCount(int count) { 1026 // sanity check 1027 if (count < 1) { 1028 count = 1; 1029 } 1030 1031 int n = this->getSaveCount() - count; 1032 for (int i = 0; i < n; ++i) { 1033 this->restore(); 1034 } 1035} 1036 1037bool SkCanvas::isDrawingToLayer() const { 1038 return fSaveLayerCount > 0; 1039} 1040 1041SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 1042 if (NULL == props) { 1043 props = &fProps; 1044 } 1045 return this->onNewSurface(info, *props); 1046} 1047 1048SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1049 SkBaseDevice* dev = this->getDevice(); 1050 return dev ? dev->newSurface(info, props) : NULL; 1051} 1052 1053SkImageInfo SkCanvas::imageInfo() const { 1054 SkBaseDevice* dev = this->getDevice(); 1055 if (dev) { 1056 return dev->imageInfo(); 1057 } else { 1058 return SkImageInfo::MakeUnknown(0, 0); 1059 } 1060} 1061 1062const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1063 return this->onPeekPixels(info, rowBytes); 1064} 1065 1066const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) { 1067 SkBaseDevice* dev = this->getDevice(); 1068 return dev ? dev->peekPixels(info, rowBytes) : NULL; 1069} 1070 1071void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { 1072 void* pixels = this->onAccessTopLayerPixels(info, rowBytes); 1073 if (pixels && origin) { 1074 *origin = this->getTopDevice(false)->getOrigin(); 1075 } 1076 return pixels; 1077} 1078 1079void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) { 1080 SkBaseDevice* dev = this->getTopDevice(); 1081 return dev ? dev->accessPixels(info, rowBytes) : NULL; 1082} 1083 1084SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) { 1085 fAddr = canvas->peekPixels(&fInfo, &fRowBytes); 1086 if (NULL == fAddr) { 1087 fInfo = canvas->imageInfo(); 1088 if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) { 1089 return; // failure, fAddr is NULL 1090 } 1091 if (!canvas->readPixels(&fBitmap, 0, 0)) { 1092 return; // failure, fAddr is NULL 1093 } 1094 fAddr = fBitmap.getPixels(); 1095 fRowBytes = fBitmap.rowBytes(); 1096 } 1097 SkASSERT(fAddr); // success 1098} 1099 1100bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const { 1101 if (fAddr) { 1102 return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes); 1103 } else { 1104 bitmap->reset(); 1105 return false; 1106 } 1107} 1108 1109void SkCanvas::onPushCull(const SkRect& cullRect) { 1110 // do nothing. Subclasses may do something 1111} 1112 1113void SkCanvas::onPopCull() { 1114 // do nothing. Subclasses may do something 1115} 1116 1117///////////////////////////////////////////////////////////////////////////// 1118#ifdef SK_DEBUG 1119// Ensure that cull rects are monotonically nested in device space. 1120void SkCanvas::validateCull(const SkIRect& devCull) { 1121 if (fCullStack.isEmpty() 1122 || devCull.isEmpty() 1123 || fCullStack.top().contains(devCull)) { 1124 return; 1125 } 1126 1127 SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n", 1128 devCull.x(), devCull.y(), devCull.right(), devCull.bottom(), 1129 fCullStack.top().x(), fCullStack.top().y(), 1130 fCullStack.top().right(), fCullStack.top().bottom())); 1131 1132#ifdef ASSERT_NESTED_CULLING 1133 SkDEBUGFAIL("Invalid cull."); 1134#endif 1135} 1136#endif 1137 1138void SkCanvas::pushCull(const SkRect& cullRect) { 1139 ++fCullCount; 1140 this->onPushCull(cullRect); 1141 1142#ifdef SK_DEBUG 1143 // Map the cull rect into device space. 1144 SkRect mappedCull; 1145 this->getTotalMatrix().mapRect(&mappedCull, cullRect); 1146 1147 // Take clipping into account. 1148 SkIRect devClip, devCull; 1149 mappedCull.roundOut(&devCull); 1150 this->getClipDeviceBounds(&devClip); 1151 if (!devCull.intersect(devClip)) { 1152 devCull.setEmpty(); 1153 } 1154 1155 this->validateCull(devCull); 1156 fCullStack.push(devCull); // balanced in popCull 1157#endif 1158} 1159 1160void SkCanvas::popCull() { 1161 SkASSERT(fCullStack.count() == fCullCount); 1162 1163 if (fCullCount > 0) { 1164 --fCullCount; 1165 this->onPopCull(); 1166 1167 SkDEBUGCODE(fCullStack.pop()); 1168 } 1169} 1170 1171///////////////////////////////////////////////////////////////////////////// 1172 1173void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 1174 const SkMatrix& matrix, const SkPaint* paint) { 1175 if (bitmap.drawsNothing()) { 1176 return; 1177 } 1178 1179 SkLazyPaint lazy; 1180 if (NULL == paint) { 1181 paint = lazy.init(); 1182 } 1183 1184 SkDEBUGCODE(bitmap.validate();) 1185 1186 SkRect storage; 1187 const SkRect* bounds = NULL; 1188 if (paint && paint->canComputeFastBounds()) { 1189 bitmap.getBounds(&storage); 1190 matrix.mapRect(&storage); 1191 bounds = &paint->computeFastBounds(storage, &storage); 1192 } 1193 1194 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1195 1196 while (iter.next()) { 1197 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 1198 } 1199 1200 LOOPER_END 1201} 1202 1203void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 1204 const SkPaint* paint) { 1205 SkPaint tmp; 1206 if (NULL == paint) { 1207 paint = &tmp; 1208 } 1209 1210 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1211 while (iter.next()) { 1212 SkBaseDevice* dstDev = iter.fDevice; 1213 paint = &looper.paint(); 1214 SkImageFilter* filter = paint->getImageFilter(); 1215 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1216 if (filter && !dstDev->canHandleImageFilter(filter)) { 1217 SkDeviceImageFilterProxy proxy(dstDev); 1218 SkBitmap dst; 1219 SkIPoint offset = SkIPoint::Make(0, 0); 1220 const SkBitmap& src = srcDev->accessBitmap(false); 1221 SkMatrix matrix = *iter.fMatrix; 1222 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1223 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height()); 1224 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache()); 1225 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1226 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { 1227 SkPaint tmpUnfiltered(*paint); 1228 tmpUnfiltered.setImageFilter(NULL); 1229 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1230 tmpUnfiltered); 1231 } 1232 } else { 1233 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1234 } 1235 } 1236 LOOPER_END 1237} 1238 1239void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 1240 const SkPaint* paint) { 1241 if (bitmap.drawsNothing()) { 1242 return; 1243 } 1244 SkDEBUGCODE(bitmap.validate();) 1245 1246 SkPaint tmp; 1247 if (NULL == paint) { 1248 paint = &tmp; 1249 } 1250 1251 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1252 1253 while (iter.next()) { 1254 paint = &looper.paint(); 1255 SkImageFilter* filter = paint->getImageFilter(); 1256 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1257 if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 1258 SkDeviceImageFilterProxy proxy(iter.fDevice); 1259 SkBitmap dst; 1260 SkIPoint offset = SkIPoint::Make(0, 0); 1261 SkMatrix matrix = *iter.fMatrix; 1262 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1263 const SkIRect clipBounds = bitmap.bounds(); 1264 SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache()); 1265 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1266 if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) { 1267 SkPaint tmpUnfiltered(*paint); 1268 tmpUnfiltered.setImageFilter(NULL); 1269 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1270 tmpUnfiltered); 1271 } 1272 } else { 1273 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 1274 } 1275 } 1276 LOOPER_END 1277} 1278 1279///////////////////////////////////////////////////////////////////////////// 1280void SkCanvas::translate(SkScalar dx, SkScalar dy) { 1281 SkMatrix m; 1282 m.setTranslate(dx, dy); 1283 this->concat(m); 1284} 1285 1286void SkCanvas::scale(SkScalar sx, SkScalar sy) { 1287 SkMatrix m; 1288 m.setScale(sx, sy); 1289 this->concat(m); 1290} 1291 1292void SkCanvas::rotate(SkScalar degrees) { 1293 SkMatrix m; 1294 m.setRotate(degrees); 1295 this->concat(m); 1296} 1297 1298void SkCanvas::skew(SkScalar sx, SkScalar sy) { 1299 SkMatrix m; 1300 m.setSkew(sx, sy); 1301 this->concat(m); 1302} 1303 1304void SkCanvas::concat(const SkMatrix& matrix) { 1305 if (matrix.isIdentity()) { 1306 return; 1307 } 1308 1309 fDeviceCMDirty = true; 1310 fCachedLocalClipBoundsDirty = true; 1311 fMCRec->fMatrix.preConcat(matrix); 1312 1313 this->didConcat(matrix); 1314} 1315 1316void SkCanvas::setMatrix(const SkMatrix& matrix) { 1317 fDeviceCMDirty = true; 1318 fCachedLocalClipBoundsDirty = true; 1319 fMCRec->fMatrix = matrix; 1320 this->didSetMatrix(matrix); 1321} 1322 1323void SkCanvas::resetMatrix() { 1324 SkMatrix matrix; 1325 1326 matrix.reset(); 1327 this->setMatrix(matrix); 1328} 1329 1330////////////////////////////////////////////////////////////////////////////// 1331 1332void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1333 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1334 this->onClipRect(rect, op, edgeStyle); 1335} 1336 1337void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1338#ifdef SK_ENABLE_CLIP_QUICKREJECT 1339 if (SkRegion::kIntersect_Op == op) { 1340 if (fMCRec->fRasterClip.isEmpty()) { 1341 return false; 1342 } 1343 1344 if (this->quickReject(rect)) { 1345 fDeviceCMDirty = true; 1346 fCachedLocalClipBoundsDirty = true; 1347 1348 fClipStack.clipEmpty(); 1349 return fMCRec->fRasterClip.setEmpty(); 1350 } 1351 } 1352#endif 1353 1354 AutoValidateClip avc(this); 1355 1356 fDeviceCMDirty = true; 1357 fCachedLocalClipBoundsDirty = true; 1358 if (!fAllowSoftClip) { 1359 edgeStyle = kHard_ClipEdgeStyle; 1360 } 1361 1362 if (fMCRec->fMatrix.rectStaysRect()) { 1363 // for these simpler matrices, we can stay a rect even after applying 1364 // the matrix. This means we don't have to a) make a path, and b) tell 1365 // the region code to scan-convert the path, only to discover that it 1366 // is really just a rect. 1367 SkRect r; 1368 1369 fMCRec->fMatrix.mapRect(&r, rect); 1370 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1371 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle); 1372 } else { 1373 // since we're rotated or some such thing, we convert the rect to a path 1374 // and clip against that, since it can handle any matrix. However, to 1375 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1376 // we explicitly call "our" version of clipPath. 1377 SkPath path; 1378 1379 path.addRect(rect); 1380 this->SkCanvas::onClipPath(path, op, edgeStyle); 1381 } 1382} 1383 1384static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath, 1385 SkRegion::Op op, bool doAA) { 1386 rc->op(devPath, canvas->getBaseLayerSize(), op, doAA); 1387} 1388 1389void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1390 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1391 if (rrect.isRect()) { 1392 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1393 } else { 1394 this->onClipRRect(rrect, op, edgeStyle); 1395 } 1396} 1397 1398void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1399 SkRRect transformedRRect; 1400 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1401 AutoValidateClip avc(this); 1402 1403 fDeviceCMDirty = true; 1404 fCachedLocalClipBoundsDirty = true; 1405 if (!fAllowSoftClip) { 1406 edgeStyle = kHard_ClipEdgeStyle; 1407 } 1408 1409 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1410 1411 SkPath devPath; 1412 devPath.addRRect(transformedRRect); 1413 1414 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1415 return; 1416 } 1417 1418 SkPath path; 1419 path.addRRect(rrect); 1420 // call the non-virtual version 1421 this->SkCanvas::onClipPath(path, op, edgeStyle); 1422} 1423 1424void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1425 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1426 SkRect r; 1427 if (!path.isInverseFillType() && path.isRect(&r)) { 1428 this->onClipRect(r, op, edgeStyle); 1429 } else { 1430 this->onClipPath(path, op, edgeStyle); 1431 } 1432} 1433 1434void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1435#ifdef SK_ENABLE_CLIP_QUICKREJECT 1436 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1437 if (fMCRec->fRasterClip.isEmpty()) { 1438 return false; 1439 } 1440 1441 if (this->quickReject(path.getBounds())) { 1442 fDeviceCMDirty = true; 1443 fCachedLocalClipBoundsDirty = true; 1444 1445 fClipStack.clipEmpty(); 1446 return fMCRec->fRasterClip.setEmpty(); 1447 } 1448 } 1449#endif 1450 1451 AutoValidateClip avc(this); 1452 1453 fDeviceCMDirty = true; 1454 fCachedLocalClipBoundsDirty = true; 1455 if (!fAllowSoftClip) { 1456 edgeStyle = kHard_ClipEdgeStyle; 1457 } 1458 1459 SkPath devPath; 1460 path.transform(fMCRec->fMatrix, &devPath); 1461 1462 // Check if the transfomation, or the original path itself 1463 // made us empty. Note this can also happen if we contained NaN 1464 // values. computing the bounds detects this, and will set our 1465 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1466 if (devPath.getBounds().isEmpty()) { 1467 // resetting the path will remove any NaN or other wanky values 1468 // that might upset our scan converter. 1469 devPath.reset(); 1470 } 1471 1472 // if we called path.swap() we could avoid a deep copy of this path 1473 fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1474 1475 if (fAllowSimplifyClip) { 1476 devPath.reset(); 1477 devPath.setFillType(SkPath::kInverseEvenOdd_FillType); 1478 const SkClipStack* clipStack = getClipStack(); 1479 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); 1480 const SkClipStack::Element* element; 1481 while ((element = iter.next())) { 1482 SkClipStack::Element::Type type = element->getType(); 1483 SkPath operand; 1484 if (type != SkClipStack::Element::kEmpty_Type) { 1485 element->asPath(&operand); 1486 } 1487 SkRegion::Op elementOp = element->getOp(); 1488 if (elementOp == SkRegion::kReplace_Op) { 1489 devPath = operand; 1490 } else { 1491 Op(devPath, operand, (SkPathOp) elementOp, &devPath); 1492 } 1493 // if the prev and curr clips disagree about aa -vs- not, favor the aa request. 1494 // perhaps we need an API change to avoid this sort of mixed-signals about 1495 // clipping. 1496 if (element->isAA()) { 1497 edgeStyle = kSoft_ClipEdgeStyle; 1498 } 1499 } 1500 op = SkRegion::kReplace_Op; 1501 } 1502 1503 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); 1504} 1505 1506void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1507 this->onClipRegion(rgn, op); 1508} 1509 1510void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1511 AutoValidateClip avc(this); 1512 1513 fDeviceCMDirty = true; 1514 fCachedLocalClipBoundsDirty = true; 1515 1516 // todo: signal fClipStack that we have a region, and therefore (I guess) 1517 // we have to ignore it, and use the region directly? 1518 fClipStack.clipDevRect(rgn.getBounds(), op); 1519 1520 fMCRec->fRasterClip.op(rgn, op); 1521} 1522 1523#ifdef SK_DEBUG 1524void SkCanvas::validateClip() const { 1525 // construct clipRgn from the clipstack 1526 const SkBaseDevice* device = this->getDevice(); 1527 if (!device) { 1528 SkASSERT(this->isClipEmpty()); 1529 return; 1530 } 1531 1532 SkIRect ir; 1533 ir.set(0, 0, device->width(), device->height()); 1534 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1535 1536 SkClipStack::B2TIter iter(fClipStack); 1537 const SkClipStack::Element* element; 1538 while ((element = iter.next()) != NULL) { 1539 switch (element->getType()) { 1540 case SkClipStack::Element::kRect_Type: 1541 element->getRect().round(&ir); 1542 tmpClip.op(ir, element->getOp()); 1543 break; 1544 case SkClipStack::Element::kEmpty_Type: 1545 tmpClip.setEmpty(); 1546 break; 1547 default: { 1548 SkPath path; 1549 element->asPath(&path); 1550 rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA()); 1551 break; 1552 } 1553 } 1554 } 1555} 1556#endif 1557 1558void SkCanvas::replayClips(ClipVisitor* visitor) const { 1559 SkClipStack::B2TIter iter(fClipStack); 1560 const SkClipStack::Element* element; 1561 1562 while ((element = iter.next()) != NULL) { 1563 element->replay(visitor); 1564 } 1565} 1566 1567/////////////////////////////////////////////////////////////////////////////// 1568 1569bool SkCanvas::isClipEmpty() const { 1570 return fMCRec->fRasterClip.isEmpty(); 1571} 1572 1573bool SkCanvas::isClipRect() const { 1574 return fMCRec->fRasterClip.isRect(); 1575} 1576 1577bool SkCanvas::quickReject(const SkRect& rect) const { 1578 if (!rect.isFinite()) 1579 return true; 1580 1581 if (fMCRec->fRasterClip.isEmpty()) { 1582 return true; 1583 } 1584 1585 if (fMCRec->fMatrix.hasPerspective()) { 1586 SkRect dst; 1587 fMCRec->fMatrix.mapRect(&dst, rect); 1588 SkIRect idst; 1589 dst.roundOut(&idst); 1590 return !SkIRect::Intersects(idst, fMCRec->fRasterClip.getBounds()); 1591 } else { 1592 const SkRect& clipR = this->getLocalClipBounds(); 1593 1594 // for speed, do the most likely reject compares first 1595 // TODO: should we use | instead, or compare all 4 at once? 1596 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1597 return true; 1598 } 1599 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1600 return true; 1601 } 1602 return false; 1603 } 1604} 1605 1606bool SkCanvas::quickReject(const SkPath& path) const { 1607 return path.isEmpty() || this->quickReject(path.getBounds()); 1608} 1609 1610bool SkCanvas::getClipBounds(SkRect* bounds) const { 1611 SkIRect ibounds; 1612 if (!this->getClipDeviceBounds(&ibounds)) { 1613 return false; 1614 } 1615 1616 SkMatrix inverse; 1617 // if we can't invert the CTM, we can't return local clip bounds 1618 if (!fMCRec->fMatrix.invert(&inverse)) { 1619 if (bounds) { 1620 bounds->setEmpty(); 1621 } 1622 return false; 1623 } 1624 1625 if (bounds) { 1626 SkRect r; 1627 // adjust it outwards in case we are antialiasing 1628 const int inset = 1; 1629 1630 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1631 ibounds.fRight + inset, ibounds.fBottom + inset); 1632 inverse.mapRect(bounds, r); 1633 } 1634 return true; 1635} 1636 1637bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1638 const SkRasterClip& clip = fMCRec->fRasterClip; 1639 if (clip.isEmpty()) { 1640 if (bounds) { 1641 bounds->setEmpty(); 1642 } 1643 return false; 1644 } 1645 1646 if (bounds) { 1647 *bounds = clip.getBounds(); 1648 } 1649 return true; 1650} 1651 1652const SkMatrix& SkCanvas::getTotalMatrix() const { 1653 return fMCRec->fMatrix; 1654} 1655 1656const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1657 return fMCRec->fRasterClip.forceGetBW(); 1658} 1659 1660GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { 1661 SkBaseDevice* dev = this->getTopDevice(); 1662 return dev ? dev->accessRenderTarget() : NULL; 1663} 1664 1665SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) { 1666 SkBaseDevice* device = this->getTopDevice(); 1667 return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL; 1668} 1669 1670GrContext* SkCanvas::getGrContext() { 1671#if SK_SUPPORT_GPU 1672 SkBaseDevice* device = this->getTopDevice(); 1673 if (device) { 1674 GrRenderTarget* renderTarget = device->accessRenderTarget(); 1675 if (renderTarget) { 1676 return renderTarget->getContext(); 1677 } 1678 } 1679#endif 1680 1681 return NULL; 1682 1683} 1684 1685void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1686 const SkPaint& paint) { 1687 if (outer.isEmpty()) { 1688 return; 1689 } 1690 if (inner.isEmpty()) { 1691 this->drawRRect(outer, paint); 1692 return; 1693 } 1694 1695 // We don't have this method (yet), but technically this is what we should 1696 // be able to assert... 1697 // SkASSERT(outer.contains(inner)); 1698 // 1699 // For now at least check for containment of bounds 1700 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1701 1702 this->onDrawDRRect(outer, inner, paint); 1703} 1704 1705////////////////////////////////////////////////////////////////////////////// 1706// These are the virtual drawing methods 1707////////////////////////////////////////////////////////////////////////////// 1708 1709void SkCanvas::clear(SkColor color) { 1710 SkDrawIter iter(this); 1711 this->predrawNotify(); 1712 while (iter.next()) { 1713 iter.fDevice->clear(color); 1714 } 1715} 1716 1717void SkCanvas::onDiscard() { 1718 if (fSurfaceBase) { 1719 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 1720 } 1721} 1722 1723void SkCanvas::drawPaint(const SkPaint& paint) { 1724 this->internalDrawPaint(paint); 1725} 1726 1727void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1728 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 1729 1730 while (iter.next()) { 1731 iter.fDevice->drawPaint(iter, looper.paint()); 1732 } 1733 1734 LOOPER_END 1735} 1736 1737void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 1738 const SkPaint& paint) { 1739 if ((long)count <= 0) { 1740 return; 1741 } 1742 1743 SkRect r, storage; 1744 const SkRect* bounds = NULL; 1745 if (paint.canComputeFastBounds()) { 1746 // special-case 2 points (common for drawing a single line) 1747 if (2 == count) { 1748 r.set(pts[0], pts[1]); 1749 } else { 1750 r.set(pts, SkToInt(count)); 1751 } 1752 bounds = &paint.computeFastStrokeBounds(r, &storage); 1753 if (this->quickReject(*bounds)) { 1754 return; 1755 } 1756 } 1757 1758 SkASSERT(pts != NULL); 1759 1760 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 1761 1762 while (iter.next()) { 1763 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1764 } 1765 1766 LOOPER_END 1767} 1768 1769void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1770 SkRect storage; 1771 const SkRect* bounds = NULL; 1772 if (paint.canComputeFastBounds()) { 1773 bounds = &paint.computeFastBounds(r, &storage); 1774 if (this->quickReject(*bounds)) { 1775 return; 1776 } 1777 } 1778 1779 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 1780 1781 while (iter.next()) { 1782 iter.fDevice->drawRect(iter, r, looper.paint()); 1783 } 1784 1785 LOOPER_END 1786} 1787 1788void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1789 SkRect storage; 1790 const SkRect* bounds = NULL; 1791 if (paint.canComputeFastBounds()) { 1792 bounds = &paint.computeFastBounds(oval, &storage); 1793 if (this->quickReject(*bounds)) { 1794 return; 1795 } 1796 } 1797 1798 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 1799 1800 while (iter.next()) { 1801 iter.fDevice->drawOval(iter, oval, looper.paint()); 1802 } 1803 1804 LOOPER_END 1805} 1806 1807void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1808 SkRect storage; 1809 const SkRect* bounds = NULL; 1810 if (paint.canComputeFastBounds()) { 1811 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 1812 if (this->quickReject(*bounds)) { 1813 return; 1814 } 1815 } 1816 1817 if (rrect.isRect()) { 1818 // call the non-virtual version 1819 this->SkCanvas::drawRect(rrect.getBounds(), paint); 1820 return; 1821 } else if (rrect.isOval()) { 1822 // call the non-virtual version 1823 this->SkCanvas::drawOval(rrect.getBounds(), paint); 1824 return; 1825 } 1826 1827 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1828 1829 while (iter.next()) { 1830 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1831 } 1832 1833 LOOPER_END 1834} 1835 1836void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1837 const SkPaint& paint) { 1838 SkRect storage; 1839 const SkRect* bounds = NULL; 1840 if (paint.canComputeFastBounds()) { 1841 bounds = &paint.computeFastBounds(outer.getBounds(), &storage); 1842 if (this->quickReject(*bounds)) { 1843 return; 1844 } 1845 } 1846 1847 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1848 1849 while (iter.next()) { 1850 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 1851 } 1852 1853 LOOPER_END 1854} 1855 1856void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1857 if (!path.isFinite()) { 1858 return; 1859 } 1860 1861 SkRect storage; 1862 const SkRect* bounds = NULL; 1863 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1864 const SkRect& pathBounds = path.getBounds(); 1865 bounds = &paint.computeFastBounds(pathBounds, &storage); 1866 if (this->quickReject(*bounds)) { 1867 return; 1868 } 1869 } 1870 1871 const SkRect& r = path.getBounds(); 1872 if (r.width() <= 0 && r.height() <= 0) { 1873 if (path.isInverseFillType()) { 1874 this->internalDrawPaint(paint); 1875 } 1876 return; 1877 } 1878 1879 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 1880 1881 while (iter.next()) { 1882 iter.fDevice->drawPath(iter, path, looper.paint()); 1883 } 1884 1885 LOOPER_END 1886} 1887 1888void SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top, 1889 const SkPaint* paint) { 1890 image->draw(this, left, top, paint); 1891} 1892 1893void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, 1894 const SkRect& dst, 1895 const SkPaint* paint) { 1896 image->drawRect(this, src, dst, paint); 1897} 1898 1899void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 1900 const SkPaint* paint) { 1901 SkDEBUGCODE(bitmap.validate();) 1902 1903 if (NULL == paint || paint->canComputeFastBounds()) { 1904 SkRect bounds = { 1905 x, y, 1906 x + SkIntToScalar(bitmap.width()), 1907 y + SkIntToScalar(bitmap.height()) 1908 }; 1909 if (paint) { 1910 (void)paint->computeFastBounds(bounds, &bounds); 1911 } 1912 if (this->quickReject(bounds)) { 1913 return; 1914 } 1915 } 1916 1917 SkMatrix matrix; 1918 matrix.setTranslate(x, y); 1919 this->internalDrawBitmap(bitmap, matrix, paint); 1920} 1921 1922// this one is non-virtual, so it can be called safely by other canvas apis 1923void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 1924 const SkRect& dst, const SkPaint* paint, 1925 DrawBitmapRectFlags flags) { 1926 if (bitmap.drawsNothing() || dst.isEmpty()) { 1927 return; 1928 } 1929 1930 SkRect storage; 1931 const SkRect* bounds = &dst; 1932 if (NULL == paint || paint->canComputeFastBounds()) { 1933 if (paint) { 1934 bounds = &paint->computeFastBounds(dst, &storage); 1935 } 1936 if (this->quickReject(*bounds)) { 1937 return; 1938 } 1939 } 1940 1941 SkLazyPaint lazy; 1942 if (NULL == paint) { 1943 paint = lazy.init(); 1944 } 1945 1946 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1947 1948 while (iter.next()) { 1949 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 1950 } 1951 1952 LOOPER_END 1953} 1954 1955void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 1956 const SkRect& dst, const SkPaint* paint, 1957 DrawBitmapRectFlags flags) { 1958 SkDEBUGCODE(bitmap.validate();) 1959 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 1960} 1961 1962void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 1963 const SkPaint* paint) { 1964 SkDEBUGCODE(bitmap.validate();) 1965 this->internalDrawBitmap(bitmap, matrix, paint); 1966} 1967 1968void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 1969 const SkIRect& center, const SkRect& dst, 1970 const SkPaint* paint) { 1971 if (bitmap.drawsNothing()) { 1972 return; 1973 } 1974 if (NULL == paint || paint->canComputeFastBounds()) { 1975 SkRect storage; 1976 const SkRect* bounds = &dst; 1977 if (paint) { 1978 bounds = &paint->computeFastBounds(dst, &storage); 1979 } 1980 if (this->quickReject(*bounds)) { 1981 return; 1982 } 1983 } 1984 1985 const int32_t w = bitmap.width(); 1986 const int32_t h = bitmap.height(); 1987 1988 SkIRect c = center; 1989 // pin center to the bounds of the bitmap 1990 c.fLeft = SkMax32(0, center.fLeft); 1991 c.fTop = SkMax32(0, center.fTop); 1992 c.fRight = SkPin32(center.fRight, c.fLeft, w); 1993 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 1994 1995 const SkScalar srcX[4] = { 1996 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 1997 }; 1998 const SkScalar srcY[4] = { 1999 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 2000 }; 2001 SkScalar dstX[4] = { 2002 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 2003 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 2004 }; 2005 SkScalar dstY[4] = { 2006 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 2007 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 2008 }; 2009 2010 if (dstX[1] > dstX[2]) { 2011 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 2012 dstX[2] = dstX[1]; 2013 } 2014 2015 if (dstY[1] > dstY[2]) { 2016 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 2017 dstY[2] = dstY[1]; 2018 } 2019 2020 for (int y = 0; y < 3; y++) { 2021 SkRect s, d; 2022 2023 s.fTop = srcY[y]; 2024 s.fBottom = srcY[y+1]; 2025 d.fTop = dstY[y]; 2026 d.fBottom = dstY[y+1]; 2027 for (int x = 0; x < 3; x++) { 2028 s.fLeft = srcX[x]; 2029 s.fRight = srcX[x+1]; 2030 d.fLeft = dstX[x]; 2031 d.fRight = dstX[x+1]; 2032 this->internalDrawBitmapRect(bitmap, &s, d, paint, 2033 kNone_DrawBitmapRectFlag); 2034 } 2035 } 2036} 2037 2038void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 2039 const SkRect& dst, const SkPaint* paint) { 2040 SkDEBUGCODE(bitmap.validate();) 2041 2042 // Need a device entry-point, so gpu can use a mesh 2043 this->internalDrawBitmapNine(bitmap, center, dst, paint); 2044} 2045 2046class SkDeviceFilteredPaint { 2047public: 2048 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2049 SkBaseDevice::TextFlags flags; 2050 if (device->filterTextFlags(paint, &flags)) { 2051 SkPaint* newPaint = fLazy.set(paint); 2052 newPaint->setFlags(flags.fFlags); 2053 fPaint = newPaint; 2054 } else { 2055 fPaint = &paint; 2056 } 2057 } 2058 2059 const SkPaint& paint() const { return *fPaint; } 2060 2061private: 2062 const SkPaint* fPaint; 2063 SkLazyPaint fLazy; 2064}; 2065 2066void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2067 const SkRect& r, SkScalar textSize) { 2068 if (paint.getStyle() == SkPaint::kFill_Style) { 2069 draw.fDevice->drawRect(draw, r, paint); 2070 } else { 2071 SkPaint p(paint); 2072 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2073 draw.fDevice->drawRect(draw, r, p); 2074 } 2075} 2076 2077void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2078 const char text[], size_t byteLength, 2079 SkScalar x, SkScalar y) { 2080 SkASSERT(byteLength == 0 || text != NULL); 2081 2082 // nothing to draw 2083 if (text == NULL || byteLength == 0 || 2084 draw.fClip->isEmpty() || 2085 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2086 return; 2087 } 2088 2089 SkScalar width = 0; 2090 SkPoint start; 2091 2092 start.set(0, 0); // to avoid warning 2093 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2094 SkPaint::kStrikeThruText_Flag)) { 2095 width = paint.measureText(text, byteLength); 2096 2097 SkScalar offsetX = 0; 2098 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2099 offsetX = SkScalarHalf(width); 2100 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2101 offsetX = width; 2102 } 2103 start.set(x - offsetX, y); 2104 } 2105 2106 if (0 == width) { 2107 return; 2108 } 2109 2110 uint32_t flags = paint.getFlags(); 2111 2112 if (flags & (SkPaint::kUnderlineText_Flag | 2113 SkPaint::kStrikeThruText_Flag)) { 2114 SkScalar textSize = paint.getTextSize(); 2115 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2116 SkRect r; 2117 2118 r.fLeft = start.fX; 2119 r.fRight = start.fX + width; 2120 2121 if (flags & SkPaint::kUnderlineText_Flag) { 2122 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2123 start.fY); 2124 r.fTop = offset; 2125 r.fBottom = offset + height; 2126 DrawRect(draw, paint, r, textSize); 2127 } 2128 if (flags & SkPaint::kStrikeThruText_Flag) { 2129 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2130 start.fY); 2131 r.fTop = offset; 2132 r.fBottom = offset + height; 2133 DrawRect(draw, paint, r, textSize); 2134 } 2135 } 2136} 2137 2138void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2139 const SkPaint& paint) { 2140 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2141 2142 while (iter.next()) { 2143 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2144 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2145 DrawTextDecorations(iter, dfp.paint(), 2146 static_cast<const char*>(text), byteLength, x, y); 2147 } 2148 2149 LOOPER_END 2150} 2151 2152void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2153 const SkPaint& paint) { 2154 SkPoint textOffset = SkPoint::Make(0, 0); 2155 2156 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2157 2158 while (iter.next()) { 2159 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2160 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2161 dfp.paint()); 2162 } 2163 2164 LOOPER_END 2165} 2166 2167void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2168 SkScalar constY, const SkPaint& paint) { 2169 2170 SkPoint textOffset = SkPoint::Make(0, constY); 2171 2172 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2173 2174 while (iter.next()) { 2175 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2176 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2177 dfp.paint()); 2178 } 2179 2180 LOOPER_END 2181} 2182 2183void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2184 const SkMatrix* matrix, const SkPaint& paint) { 2185 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2186 2187 while (iter.next()) { 2188 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2189 matrix, looper.paint()); 2190 } 2191 2192 LOOPER_END 2193} 2194 2195void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2196 const SkPaint& paint) { 2197 2198 if (paint.canComputeFastBounds()) { 2199 SkRect storage; 2200 2201 if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) { 2202 return; 2203 } 2204 } 2205 2206 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2207 2208 while (iter.next()) { 2209 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2210 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint()); 2211 } 2212 2213 LOOPER_END 2214} 2215 2216// These will become non-virtual, so they always call the (virtual) onDraw... method 2217void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2218 const SkPaint& paint) { 2219 this->onDrawText(text, byteLength, x, y, paint); 2220} 2221void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2222 const SkPaint& paint) { 2223 this->onDrawPosText(text, byteLength, pos, paint); 2224} 2225void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2226 SkScalar constY, const SkPaint& paint) { 2227 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2228} 2229void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2230 const SkMatrix* matrix, const SkPaint& paint) { 2231 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2232} 2233void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2234 const SkPaint& paint) { 2235 if (blob) { 2236 this->onDrawTextBlob(blob, x, y, paint); 2237 } 2238} 2239 2240void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 2241 const SkPoint verts[], const SkPoint texs[], 2242 const SkColor colors[], SkXfermode* xmode, 2243 const uint16_t indices[], int indexCount, 2244 const SkPaint& paint) { 2245 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2246 2247 while (iter.next()) { 2248 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2249 colors, xmode, indices, indexCount, 2250 looper.paint()); 2251 } 2252 2253 LOOPER_END 2254} 2255 2256void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2257 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2258 if (NULL == cubics) { 2259 return; 2260 } 2261 2262 // Since a patch is always within the convex hull of the control points, we discard it when its 2263 // bounding rectangle is completely outside the current clip. 2264 SkRect bounds; 2265 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2266 if (this->quickReject(bounds)) { 2267 return; 2268 } 2269 2270 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2271} 2272 2273void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2274 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2275 2276 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2277 2278 while (iter.next()) { 2279 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2280 } 2281 2282 LOOPER_END 2283} 2284 2285////////////////////////////////////////////////////////////////////////////// 2286// These methods are NOT virtual, and therefore must call back into virtual 2287// methods, rather than actually drawing themselves. 2288////////////////////////////////////////////////////////////////////////////// 2289 2290void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2291 SkXfermode::Mode mode) { 2292 SkPaint paint; 2293 2294 paint.setARGB(a, r, g, b); 2295 if (SkXfermode::kSrcOver_Mode != mode) { 2296 paint.setXfermodeMode(mode); 2297 } 2298 this->drawPaint(paint); 2299} 2300 2301void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2302 SkPaint paint; 2303 2304 paint.setColor(c); 2305 if (SkXfermode::kSrcOver_Mode != mode) { 2306 paint.setXfermodeMode(mode); 2307 } 2308 this->drawPaint(paint); 2309} 2310 2311void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2312 SkPoint pt; 2313 2314 pt.set(x, y); 2315 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2316} 2317 2318void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2319 SkPoint pt; 2320 SkPaint paint; 2321 2322 pt.set(x, y); 2323 paint.setColor(color); 2324 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2325} 2326 2327void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2328 const SkPaint& paint) { 2329 SkPoint pts[2]; 2330 2331 pts[0].set(x0, y0); 2332 pts[1].set(x1, y1); 2333 this->drawPoints(kLines_PointMode, 2, pts, paint); 2334} 2335 2336void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2337 SkScalar right, SkScalar bottom, 2338 const SkPaint& paint) { 2339 SkRect r; 2340 2341 r.set(left, top, right, bottom); 2342 this->drawRect(r, paint); 2343} 2344 2345void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2346 const SkPaint& paint) { 2347 if (radius < 0) { 2348 radius = 0; 2349 } 2350 2351 SkRect r; 2352 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2353 this->drawOval(r, paint); 2354} 2355 2356void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2357 const SkPaint& paint) { 2358 if (rx > 0 && ry > 0) { 2359 if (paint.canComputeFastBounds()) { 2360 SkRect storage; 2361 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2362 return; 2363 } 2364 } 2365 SkRRect rrect; 2366 rrect.setRectXY(r, rx, ry); 2367 this->drawRRect(rrect, paint); 2368 } else { 2369 this->drawRect(r, paint); 2370 } 2371} 2372 2373void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2374 SkScalar sweepAngle, bool useCenter, 2375 const SkPaint& paint) { 2376 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2377 this->drawOval(oval, paint); 2378 } else { 2379 SkPath path; 2380 if (useCenter) { 2381 path.moveTo(oval.centerX(), oval.centerY()); 2382 } 2383 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2384 if (useCenter) { 2385 path.close(); 2386 } 2387 this->drawPath(path, paint); 2388 } 2389} 2390 2391void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2392 const SkPath& path, SkScalar hOffset, 2393 SkScalar vOffset, const SkPaint& paint) { 2394 SkMatrix matrix; 2395 2396 matrix.setTranslate(hOffset, vOffset); 2397 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2398} 2399 2400/////////////////////////////////////////////////////////////////////////////// 2401void SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) { 2402 SkBaseDevice* device = this->getDevice(); 2403 if (device) { 2404 device->EXPERIMENTAL_optimize(picture); 2405 } 2406} 2407 2408void SkCanvas::drawPicture(const SkPicture* picture) { 2409 if (picture) { 2410 this->onDrawPicture(picture, NULL, NULL); 2411 } 2412} 2413 2414void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2415 if (picture) { 2416 if (matrix && matrix->isIdentity()) { 2417 matrix = NULL; 2418 } 2419 this->onDrawPicture(picture, matrix, paint); 2420 } 2421} 2422 2423void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2424 const SkPaint* paint) { 2425 SkBaseDevice* device = this->getTopDevice(); 2426 if (device) { 2427 // Canvas has to first give the device the opportunity to render 2428 // the picture itself. 2429 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) { 2430 return; // the device has rendered the entire picture 2431 } 2432 } 2433 2434 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2435 2436 picture->playback(this); 2437} 2438 2439/////////////////////////////////////////////////////////////////////////////// 2440/////////////////////////////////////////////////////////////////////////////// 2441 2442SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2443 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 2444 2445 SkASSERT(canvas); 2446 2447 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2448 fDone = !fImpl->next(); 2449} 2450 2451SkCanvas::LayerIter::~LayerIter() { 2452 fImpl->~SkDrawIter(); 2453} 2454 2455void SkCanvas::LayerIter::next() { 2456 fDone = !fImpl->next(); 2457} 2458 2459SkBaseDevice* SkCanvas::LayerIter::device() const { 2460 return fImpl->getDevice(); 2461} 2462 2463const SkMatrix& SkCanvas::LayerIter::matrix() const { 2464 return fImpl->getMatrix(); 2465} 2466 2467const SkPaint& SkCanvas::LayerIter::paint() const { 2468 const SkPaint* paint = fImpl->getPaint(); 2469 if (NULL == paint) { 2470 paint = &fDefaultPaint; 2471 } 2472 return *paint; 2473} 2474 2475const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2476int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2477int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2478 2479/////////////////////////////////////////////////////////////////////////////// 2480 2481SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 2482 2483/////////////////////////////////////////////////////////////////////////////// 2484 2485static bool supported_for_raster_canvas(const SkImageInfo& info) { 2486 switch (info.alphaType()) { 2487 case kPremul_SkAlphaType: 2488 case kOpaque_SkAlphaType: 2489 break; 2490 default: 2491 return false; 2492 } 2493 2494 switch (info.colorType()) { 2495 case kAlpha_8_SkColorType: 2496 case kRGB_565_SkColorType: 2497 case kN32_SkColorType: 2498 break; 2499 default: 2500 return false; 2501 } 2502 2503 return true; 2504} 2505 2506SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) { 2507 if (!supported_for_raster_canvas(info)) { 2508 return NULL; 2509 } 2510 2511 SkBitmap bitmap; 2512 if (!bitmap.tryAllocPixels(info)) { 2513 return NULL; 2514 } 2515 2516 // should this functionality be moved into allocPixels()? 2517 if (!bitmap.info().isOpaque()) { 2518 bitmap.eraseColor(0); 2519 } 2520 return SkNEW_ARGS(SkCanvas, (bitmap)); 2521} 2522 2523SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 2524 if (!supported_for_raster_canvas(info)) { 2525 return NULL; 2526 } 2527 2528 SkBitmap bitmap; 2529 if (!bitmap.installPixels(info, pixels, rowBytes)) { 2530 return NULL; 2531 } 2532 return SkNEW_ARGS(SkCanvas, (bitmap)); 2533} 2534 2535/////////////////////////////////////////////////////////////////////////////// 2536 2537SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 2538 const SkPaint* paint, const SkRect& bounds) 2539 : fCanvas(canvas) 2540 , fSaveCount(canvas->getSaveCount()) 2541{ 2542 if (paint) { 2543 SkRect newBounds = bounds; 2544 if (matrix) { 2545 matrix->mapRect(&newBounds); 2546 } 2547 canvas->saveLayer(&newBounds, paint); 2548 } else if (matrix) { 2549 canvas->save(); 2550 } 2551 2552 if (matrix) { 2553 canvas->concat(*matrix); 2554 } 2555} 2556 2557SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2558 fCanvas->restoreToCount(fSaveCount); 2559} 2560