SkCanvas.cpp revision 3054be16dfdb0d06233770cbfc338958edef44ea
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("disabled-by-default-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("disabled-by-default-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::onDiscard() { 1710 if (fSurfaceBase) { 1711 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 1712 } 1713} 1714 1715void SkCanvas::drawPaint(const SkPaint& paint) { 1716 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 1717 this->internalDrawPaint(paint); 1718} 1719 1720void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1721 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 1722 1723 while (iter.next()) { 1724 iter.fDevice->drawPaint(iter, looper.paint()); 1725 } 1726 1727 LOOPER_END 1728} 1729 1730void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 1731 const SkPaint& paint) { 1732 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 1733 if ((long)count <= 0) { 1734 return; 1735 } 1736 1737 SkRect r, storage; 1738 const SkRect* bounds = NULL; 1739 if (paint.canComputeFastBounds()) { 1740 // special-case 2 points (common for drawing a single line) 1741 if (2 == count) { 1742 r.set(pts[0], pts[1]); 1743 } else { 1744 r.set(pts, SkToInt(count)); 1745 } 1746 bounds = &paint.computeFastStrokeBounds(r, &storage); 1747 if (this->quickReject(*bounds)) { 1748 return; 1749 } 1750 } 1751 1752 SkASSERT(pts != NULL); 1753 1754 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 1755 1756 while (iter.next()) { 1757 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1758 } 1759 1760 LOOPER_END 1761} 1762 1763void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1764 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 1765 SkRect storage; 1766 const SkRect* bounds = NULL; 1767 if (paint.canComputeFastBounds()) { 1768 bounds = &paint.computeFastBounds(r, &storage); 1769 if (this->quickReject(*bounds)) { 1770 return; 1771 } 1772 } 1773 1774 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 1775 1776 while (iter.next()) { 1777 iter.fDevice->drawRect(iter, r, looper.paint()); 1778 } 1779 1780 LOOPER_END 1781} 1782 1783void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1784 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 1785 SkRect storage; 1786 const SkRect* bounds = NULL; 1787 if (paint.canComputeFastBounds()) { 1788 bounds = &paint.computeFastBounds(oval, &storage); 1789 if (this->quickReject(*bounds)) { 1790 return; 1791 } 1792 } 1793 1794 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 1795 1796 while (iter.next()) { 1797 iter.fDevice->drawOval(iter, oval, looper.paint()); 1798 } 1799 1800 LOOPER_END 1801} 1802 1803void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1804 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 1805 SkRect storage; 1806 const SkRect* bounds = NULL; 1807 if (paint.canComputeFastBounds()) { 1808 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 1809 if (this->quickReject(*bounds)) { 1810 return; 1811 } 1812 } 1813 1814 if (rrect.isRect()) { 1815 // call the non-virtual version 1816 this->SkCanvas::drawRect(rrect.getBounds(), paint); 1817 return; 1818 } else if (rrect.isOval()) { 1819 // call the non-virtual version 1820 this->SkCanvas::drawOval(rrect.getBounds(), paint); 1821 return; 1822 } 1823 1824 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1825 1826 while (iter.next()) { 1827 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1828 } 1829 1830 LOOPER_END 1831} 1832 1833void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1834 const SkPaint& paint) { 1835 SkRect storage; 1836 const SkRect* bounds = NULL; 1837 if (paint.canComputeFastBounds()) { 1838 bounds = &paint.computeFastBounds(outer.getBounds(), &storage); 1839 if (this->quickReject(*bounds)) { 1840 return; 1841 } 1842 } 1843 1844 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1845 1846 while (iter.next()) { 1847 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 1848 } 1849 1850 LOOPER_END 1851} 1852 1853void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1854 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 1855 if (!path.isFinite()) { 1856 return; 1857 } 1858 1859 SkRect storage; 1860 const SkRect* bounds = NULL; 1861 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1862 const SkRect& pathBounds = path.getBounds(); 1863 bounds = &paint.computeFastBounds(pathBounds, &storage); 1864 if (this->quickReject(*bounds)) { 1865 return; 1866 } 1867 } 1868 1869 const SkRect& r = path.getBounds(); 1870 if (r.width() <= 0 && r.height() <= 0) { 1871 if (path.isInverseFillType()) { 1872 this->internalDrawPaint(paint); 1873 } 1874 return; 1875 } 1876 1877 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 1878 1879 while (iter.next()) { 1880 iter.fDevice->drawPath(iter, path, looper.paint()); 1881 } 1882 1883 LOOPER_END 1884} 1885 1886void SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top, 1887 const SkPaint* paint) { 1888 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 1889 image->draw(this, left, top, paint); 1890} 1891 1892void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, 1893 const SkRect& dst, 1894 const SkPaint* paint) { 1895 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 1896 image->drawRect(this, src, dst, paint); 1897} 1898 1899void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 1900 const SkPaint* paint) { 1901 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 1902 SkDEBUGCODE(bitmap.validate();) 1903 1904 if (NULL == paint || paint->canComputeFastBounds()) { 1905 SkRect bounds = { 1906 x, y, 1907 x + SkIntToScalar(bitmap.width()), 1908 y + SkIntToScalar(bitmap.height()) 1909 }; 1910 if (paint) { 1911 (void)paint->computeFastBounds(bounds, &bounds); 1912 } 1913 if (this->quickReject(bounds)) { 1914 return; 1915 } 1916 } 1917 1918 SkMatrix matrix; 1919 matrix.setTranslate(x, y); 1920 this->internalDrawBitmap(bitmap, matrix, paint); 1921} 1922 1923// this one is non-virtual, so it can be called safely by other canvas apis 1924void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 1925 const SkRect& dst, const SkPaint* paint, 1926 DrawBitmapRectFlags flags) { 1927 if (bitmap.drawsNothing() || dst.isEmpty()) { 1928 return; 1929 } 1930 1931 SkRect storage; 1932 const SkRect* bounds = &dst; 1933 if (NULL == paint || paint->canComputeFastBounds()) { 1934 if (paint) { 1935 bounds = &paint->computeFastBounds(dst, &storage); 1936 } 1937 if (this->quickReject(*bounds)) { 1938 return; 1939 } 1940 } 1941 1942 SkLazyPaint lazy; 1943 if (NULL == paint) { 1944 paint = lazy.init(); 1945 } 1946 1947 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1948 1949 while (iter.next()) { 1950 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 1951 } 1952 1953 LOOPER_END 1954} 1955 1956void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 1957 const SkRect& dst, const SkPaint* paint, 1958 DrawBitmapRectFlags flags) { 1959 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 1960 SkDEBUGCODE(bitmap.validate();) 1961 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 1962} 1963 1964void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 1965 const SkPaint* paint) { 1966 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapMatrix()"); 1967 SkDEBUGCODE(bitmap.validate();) 1968 this->internalDrawBitmap(bitmap, matrix, paint); 1969} 1970 1971void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 1972 const SkIRect& center, const SkRect& dst, 1973 const SkPaint* paint) { 1974 if (bitmap.drawsNothing()) { 1975 return; 1976 } 1977 if (NULL == paint || paint->canComputeFastBounds()) { 1978 SkRect storage; 1979 const SkRect* bounds = &dst; 1980 if (paint) { 1981 bounds = &paint->computeFastBounds(dst, &storage); 1982 } 1983 if (this->quickReject(*bounds)) { 1984 return; 1985 } 1986 } 1987 1988 const int32_t w = bitmap.width(); 1989 const int32_t h = bitmap.height(); 1990 1991 SkIRect c = center; 1992 // pin center to the bounds of the bitmap 1993 c.fLeft = SkMax32(0, center.fLeft); 1994 c.fTop = SkMax32(0, center.fTop); 1995 c.fRight = SkPin32(center.fRight, c.fLeft, w); 1996 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 1997 1998 const SkScalar srcX[4] = { 1999 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 2000 }; 2001 const SkScalar srcY[4] = { 2002 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 2003 }; 2004 SkScalar dstX[4] = { 2005 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 2006 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 2007 }; 2008 SkScalar dstY[4] = { 2009 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 2010 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 2011 }; 2012 2013 if (dstX[1] > dstX[2]) { 2014 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 2015 dstX[2] = dstX[1]; 2016 } 2017 2018 if (dstY[1] > dstY[2]) { 2019 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 2020 dstY[2] = dstY[1]; 2021 } 2022 2023 for (int y = 0; y < 3; y++) { 2024 SkRect s, d; 2025 2026 s.fTop = srcY[y]; 2027 s.fBottom = srcY[y+1]; 2028 d.fTop = dstY[y]; 2029 d.fBottom = dstY[y+1]; 2030 for (int x = 0; x < 3; x++) { 2031 s.fLeft = srcX[x]; 2032 s.fRight = srcX[x+1]; 2033 d.fLeft = dstX[x]; 2034 d.fRight = dstX[x+1]; 2035 this->internalDrawBitmapRect(bitmap, &s, d, paint, 2036 kNone_DrawBitmapRectFlag); 2037 } 2038 } 2039} 2040 2041void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 2042 const SkRect& dst, const SkPaint* paint) { 2043 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2044 SkDEBUGCODE(bitmap.validate();) 2045 2046 // Need a device entry-point, so gpu can use a mesh 2047 this->internalDrawBitmapNine(bitmap, center, dst, paint); 2048} 2049 2050class SkDeviceFilteredPaint { 2051public: 2052 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2053 uint32_t filteredFlags = device->filterTextFlags(paint); 2054 if (filteredFlags != paint.getFlags()) { 2055 SkPaint* newPaint = fLazy.set(paint); 2056 newPaint->setFlags(filteredFlags); 2057 fPaint = newPaint; 2058 } else { 2059 fPaint = &paint; 2060 } 2061 } 2062 2063 const SkPaint& paint() const { return *fPaint; } 2064 2065private: 2066 const SkPaint* fPaint; 2067 SkLazyPaint fLazy; 2068}; 2069 2070void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2071 const SkRect& r, SkScalar textSize) { 2072 if (paint.getStyle() == SkPaint::kFill_Style) { 2073 draw.fDevice->drawRect(draw, r, paint); 2074 } else { 2075 SkPaint p(paint); 2076 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2077 draw.fDevice->drawRect(draw, r, p); 2078 } 2079} 2080 2081void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2082 const char text[], size_t byteLength, 2083 SkScalar x, SkScalar y) { 2084 SkASSERT(byteLength == 0 || text != NULL); 2085 2086 // nothing to draw 2087 if (text == NULL || byteLength == 0 || 2088 draw.fClip->isEmpty() || 2089 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2090 return; 2091 } 2092 2093 SkScalar width = 0; 2094 SkPoint start; 2095 2096 start.set(0, 0); // to avoid warning 2097 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2098 SkPaint::kStrikeThruText_Flag)) { 2099 width = paint.measureText(text, byteLength); 2100 2101 SkScalar offsetX = 0; 2102 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2103 offsetX = SkScalarHalf(width); 2104 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2105 offsetX = width; 2106 } 2107 start.set(x - offsetX, y); 2108 } 2109 2110 if (0 == width) { 2111 return; 2112 } 2113 2114 uint32_t flags = paint.getFlags(); 2115 2116 if (flags & (SkPaint::kUnderlineText_Flag | 2117 SkPaint::kStrikeThruText_Flag)) { 2118 SkScalar textSize = paint.getTextSize(); 2119 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2120 SkRect r; 2121 2122 r.fLeft = start.fX; 2123 r.fRight = start.fX + width; 2124 2125 if (flags & SkPaint::kUnderlineText_Flag) { 2126 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2127 start.fY); 2128 r.fTop = offset; 2129 r.fBottom = offset + height; 2130 DrawRect(draw, paint, r, textSize); 2131 } 2132 if (flags & SkPaint::kStrikeThruText_Flag) { 2133 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2134 start.fY); 2135 r.fTop = offset; 2136 r.fBottom = offset + height; 2137 DrawRect(draw, paint, r, textSize); 2138 } 2139 } 2140} 2141 2142void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2143 const SkPaint& paint) { 2144 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2145 2146 while (iter.next()) { 2147 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2148 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2149 DrawTextDecorations(iter, dfp.paint(), 2150 static_cast<const char*>(text), byteLength, x, y); 2151 } 2152 2153 LOOPER_END 2154} 2155 2156void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2157 const SkPaint& paint) { 2158 SkPoint textOffset = SkPoint::Make(0, 0); 2159 2160 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2161 2162 while (iter.next()) { 2163 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2164 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2165 dfp.paint()); 2166 } 2167 2168 LOOPER_END 2169} 2170 2171void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2172 SkScalar constY, const SkPaint& paint) { 2173 2174 SkPoint textOffset = SkPoint::Make(0, constY); 2175 2176 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2177 2178 while (iter.next()) { 2179 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2180 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2181 dfp.paint()); 2182 } 2183 2184 LOOPER_END 2185} 2186 2187void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2188 const SkMatrix* matrix, const SkPaint& paint) { 2189 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2190 2191 while (iter.next()) { 2192 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2193 matrix, looper.paint()); 2194 } 2195 2196 LOOPER_END 2197} 2198 2199void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2200 const SkPaint& paint) { 2201 2202 if (paint.canComputeFastBounds()) { 2203 SkRect storage; 2204 2205 if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) { 2206 return; 2207 } 2208 } 2209 2210 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2211 2212 while (iter.next()) { 2213 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2214 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint()); 2215 } 2216 2217 LOOPER_END 2218} 2219 2220// These will become non-virtual, so they always call the (virtual) onDraw... method 2221void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2222 const SkPaint& paint) { 2223 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2224 this->onDrawText(text, byteLength, x, y, paint); 2225} 2226void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2227 const SkPaint& paint) { 2228 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2229 this->onDrawPosText(text, byteLength, pos, paint); 2230} 2231void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2232 SkScalar constY, const SkPaint& paint) { 2233 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2234 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2235} 2236void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2237 const SkMatrix* matrix, const SkPaint& paint) { 2238 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2239 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2240} 2241void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2242 const SkPaint& paint) { 2243 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2244 if (blob) { 2245 this->onDrawTextBlob(blob, x, y, paint); 2246 } 2247} 2248 2249void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 2250 const SkPoint verts[], const SkPoint texs[], 2251 const SkColor colors[], SkXfermode* xmode, 2252 const uint16_t indices[], int indexCount, 2253 const SkPaint& paint) { 2254 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2255 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2256 2257 while (iter.next()) { 2258 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2259 colors, xmode, indices, indexCount, 2260 looper.paint()); 2261 } 2262 2263 LOOPER_END 2264} 2265 2266void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2267 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2268 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2269 if (NULL == cubics) { 2270 return; 2271 } 2272 2273 // Since a patch is always within the convex hull of the control points, we discard it when its 2274 // bounding rectangle is completely outside the current clip. 2275 SkRect bounds; 2276 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2277 if (this->quickReject(bounds)) { 2278 return; 2279 } 2280 2281 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2282} 2283 2284void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2285 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2286 2287 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2288 2289 while (iter.next()) { 2290 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2291 } 2292 2293 LOOPER_END 2294} 2295 2296void SkCanvas::EXPERIMENTAL_drawDrawable(SkCanvasDrawable* dr) { 2297 if (dr && !this->quickReject(dr->getBounds())) { 2298 this->onDrawDrawable(dr); 2299 } 2300} 2301 2302void SkCanvas::onDrawDrawable(SkCanvasDrawable* dr) { 2303 dr->draw(this); 2304} 2305 2306////////////////////////////////////////////////////////////////////////////// 2307// These methods are NOT virtual, and therefore must call back into virtual 2308// methods, rather than actually drawing themselves. 2309////////////////////////////////////////////////////////////////////////////// 2310 2311void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2312 SkXfermode::Mode mode) { 2313 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2314 SkPaint paint; 2315 2316 paint.setARGB(a, r, g, b); 2317 if (SkXfermode::kSrcOver_Mode != mode) { 2318 paint.setXfermodeMode(mode); 2319 } 2320 this->drawPaint(paint); 2321} 2322 2323void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2324 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2325 SkPaint paint; 2326 2327 paint.setColor(c); 2328 if (SkXfermode::kSrcOver_Mode != mode) { 2329 paint.setXfermodeMode(mode); 2330 } 2331 this->drawPaint(paint); 2332} 2333 2334void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2335 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2336 SkPoint pt; 2337 2338 pt.set(x, y); 2339 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2340} 2341 2342void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2343 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2344 SkPoint pt; 2345 SkPaint paint; 2346 2347 pt.set(x, y); 2348 paint.setColor(color); 2349 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2350} 2351 2352void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2353 const SkPaint& paint) { 2354 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 2355 SkPoint pts[2]; 2356 2357 pts[0].set(x0, y0); 2358 pts[1].set(x1, y1); 2359 this->drawPoints(kLines_PointMode, 2, pts, paint); 2360} 2361 2362void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2363 SkScalar right, SkScalar bottom, 2364 const SkPaint& paint) { 2365 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 2366 SkRect r; 2367 2368 r.set(left, top, right, bottom); 2369 this->drawRect(r, paint); 2370} 2371 2372void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2373 const SkPaint& paint) { 2374 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 2375 if (radius < 0) { 2376 radius = 0; 2377 } 2378 2379 SkRect r; 2380 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2381 this->drawOval(r, paint); 2382} 2383 2384void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2385 const SkPaint& paint) { 2386 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 2387 if (rx > 0 && ry > 0) { 2388 if (paint.canComputeFastBounds()) { 2389 SkRect storage; 2390 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2391 return; 2392 } 2393 } 2394 SkRRect rrect; 2395 rrect.setRectXY(r, rx, ry); 2396 this->drawRRect(rrect, paint); 2397 } else { 2398 this->drawRect(r, paint); 2399 } 2400} 2401 2402void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2403 SkScalar sweepAngle, bool useCenter, 2404 const SkPaint& paint) { 2405 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2406 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2407 this->drawOval(oval, paint); 2408 } else { 2409 SkPath path; 2410 if (useCenter) { 2411 path.moveTo(oval.centerX(), oval.centerY()); 2412 } 2413 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2414 if (useCenter) { 2415 path.close(); 2416 } 2417 this->drawPath(path, paint); 2418 } 2419} 2420 2421void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2422 const SkPath& path, SkScalar hOffset, 2423 SkScalar vOffset, const SkPaint& paint) { 2424 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 2425 SkMatrix matrix; 2426 2427 matrix.setTranslate(hOffset, vOffset); 2428 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2429} 2430 2431/////////////////////////////////////////////////////////////////////////////// 2432void SkCanvas::drawPicture(const SkPicture* picture) { 2433 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 2434 if (picture) { 2435 this->onDrawPicture(picture, NULL, NULL); 2436 } 2437} 2438 2439void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2440 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)"); 2441 if (picture) { 2442 if (matrix && matrix->isIdentity()) { 2443 matrix = NULL; 2444 } 2445 this->onDrawPicture(picture, matrix, paint); 2446 } 2447} 2448 2449void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2450 const SkPaint* paint) { 2451 SkBaseDevice* device = this->getTopDevice(); 2452 if (device) { 2453 // Canvas has to first give the device the opportunity to render 2454 // the picture itself. 2455 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) { 2456 return; // the device has rendered the entire picture 2457 } 2458 } 2459 2460 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2461 2462 picture->playback(this); 2463} 2464 2465/////////////////////////////////////////////////////////////////////////////// 2466/////////////////////////////////////////////////////////////////////////////// 2467 2468SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2469 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 2470 2471 SkASSERT(canvas); 2472 2473 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2474 fDone = !fImpl->next(); 2475} 2476 2477SkCanvas::LayerIter::~LayerIter() { 2478 fImpl->~SkDrawIter(); 2479} 2480 2481void SkCanvas::LayerIter::next() { 2482 fDone = !fImpl->next(); 2483} 2484 2485SkBaseDevice* SkCanvas::LayerIter::device() const { 2486 return fImpl->getDevice(); 2487} 2488 2489const SkMatrix& SkCanvas::LayerIter::matrix() const { 2490 return fImpl->getMatrix(); 2491} 2492 2493const SkPaint& SkCanvas::LayerIter::paint() const { 2494 const SkPaint* paint = fImpl->getPaint(); 2495 if (NULL == paint) { 2496 paint = &fDefaultPaint; 2497 } 2498 return *paint; 2499} 2500 2501const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2502int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2503int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2504 2505/////////////////////////////////////////////////////////////////////////////// 2506 2507SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 2508 2509/////////////////////////////////////////////////////////////////////////////// 2510 2511static bool supported_for_raster_canvas(const SkImageInfo& info) { 2512 switch (info.alphaType()) { 2513 case kPremul_SkAlphaType: 2514 case kOpaque_SkAlphaType: 2515 break; 2516 default: 2517 return false; 2518 } 2519 2520 switch (info.colorType()) { 2521 case kAlpha_8_SkColorType: 2522 case kRGB_565_SkColorType: 2523 case kN32_SkColorType: 2524 break; 2525 default: 2526 return false; 2527 } 2528 2529 return true; 2530} 2531 2532SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 2533 if (!supported_for_raster_canvas(info)) { 2534 return NULL; 2535 } 2536 2537 SkBitmap bitmap; 2538 if (!bitmap.installPixels(info, pixels, rowBytes)) { 2539 return NULL; 2540 } 2541 return SkNEW_ARGS(SkCanvas, (bitmap)); 2542} 2543 2544/////////////////////////////////////////////////////////////////////////////// 2545 2546SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 2547 const SkPaint* paint, const SkRect& bounds) 2548 : fCanvas(canvas) 2549 , fSaveCount(canvas->getSaveCount()) 2550{ 2551 if (paint) { 2552 SkRect newBounds = bounds; 2553 if (matrix) { 2554 matrix->mapRect(&newBounds); 2555 } 2556 canvas->saveLayer(&newBounds, paint); 2557 } else if (matrix) { 2558 canvas->save(); 2559 } 2560 2561 if (matrix) { 2562 canvas->concat(*matrix); 2563 } 2564} 2565 2566SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2567 fCanvas->restoreToCount(fSaveCount); 2568} 2569