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