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