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