SkCanvas.cpp revision 180aec43451dd951fdaae81a92efc710ba093260
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 true, 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, false, 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, false, strategy); 894 return this->getSaveCount() - 1; 895} 896 897void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags, 898 bool justForImageFilter, 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 // Kill the imagefilter if our device doesn't allow it 921 SkLazyPaint lazyP; 922 if (paint && paint->getImageFilter()) { 923 if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 924 if (justForImageFilter) { 925 // early exit if the layer was just for the imageFilter 926 return; 927 } 928 SkPaint* p = lazyP.set(*paint); 929 p->setImageFilter(NULL); 930 paint = p; 931 } 932 } 933 934 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); 935 SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(), 936 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 937 938 SkBaseDevice* device = this->getTopDevice(); 939 if (NULL == device) { 940 SkDebugf("Unable to find device for layer."); 941 return; 942 } 943 944 SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage; 945 if (paint && paint->getImageFilter()) { 946 usage = SkBaseDevice::kImageFilter_Usage; 947 } 948 device = device->onCreateCompatibleDevice(SkBaseDevice::CreateInfo(info, usage, 949 fProps.pixelGeometry())); 950 if (NULL == device) { 951 SkErrorInternals::SetError( kInternalError_SkError, 952 "Unable to create device for layer."); 953 return; 954 } 955 956 device->setOrigin(ir.fLeft, ir.fTop); 957 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip)); 958 device->unref(); 959 960 layer->fNext = fMCRec->fTopLayer; 961 fMCRec->fLayer = layer; 962 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 963} 964 965int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 966 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); 967} 968 969int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 970 SaveFlags flags) { 971 if (0xFF == alpha) { 972 return this->saveLayer(bounds, NULL, flags); 973 } else { 974 SkPaint tmpPaint; 975 tmpPaint.setAlpha(alpha); 976 return this->saveLayer(bounds, &tmpPaint, flags); 977 } 978} 979 980void SkCanvas::internalRestore() { 981 SkASSERT(fMCStack.count() != 0); 982 983 fDeviceCMDirty = true; 984 fCachedLocalClipBoundsDirty = true; 985 986 fClipStack->restore(); 987 988 // reserve our layer (if any) 989 DeviceCM* layer = fMCRec->fLayer; // may be null 990 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 991 fMCRec->fLayer = NULL; 992 993 // now do the normal restore() 994 fMCRec->~MCRec(); // balanced in save() 995 fMCStack.pop_back(); 996 fMCRec = (MCRec*)fMCStack.back(); 997 998 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 999 since if we're being recorded, we don't want to record this (the 1000 recorder will have already recorded the restore). 1001 */ 1002 if (layer) { 1003 if (layer->fNext) { 1004 const SkIPoint& origin = layer->fDevice->getOrigin(); 1005 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1006 layer->fPaint); 1007 // reset this, since internalDrawDevice will have set it to true 1008 fDeviceCMDirty = true; 1009 } 1010 SkDELETE(layer); 1011 } 1012} 1013 1014SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 1015 if (NULL == props) { 1016 props = &fProps; 1017 } 1018 return this->onNewSurface(info, *props); 1019} 1020 1021SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1022 SkBaseDevice* dev = this->getDevice(); 1023 return dev ? dev->newSurface(info, props) : NULL; 1024} 1025 1026SkImageInfo SkCanvas::imageInfo() const { 1027 SkBaseDevice* dev = this->getDevice(); 1028 if (dev) { 1029 return dev->imageInfo(); 1030 } else { 1031 return SkImageInfo::MakeUnknown(0, 0); 1032 } 1033} 1034 1035const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1036 return this->onPeekPixels(info, rowBytes); 1037} 1038 1039const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) { 1040 SkBaseDevice* dev = this->getDevice(); 1041 return dev ? dev->peekPixels(info, rowBytes) : NULL; 1042} 1043 1044void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { 1045 void* pixels = this->onAccessTopLayerPixels(info, rowBytes); 1046 if (pixels && origin) { 1047 *origin = this->getTopDevice(false)->getOrigin(); 1048 } 1049 return pixels; 1050} 1051 1052void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) { 1053 SkBaseDevice* dev = this->getTopDevice(); 1054 return dev ? dev->accessPixels(info, rowBytes) : NULL; 1055} 1056 1057SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) { 1058 fAddr = canvas->peekPixels(&fInfo, &fRowBytes); 1059 if (NULL == fAddr) { 1060 fInfo = canvas->imageInfo(); 1061 if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) { 1062 return; // failure, fAddr is NULL 1063 } 1064 if (!canvas->readPixels(&fBitmap, 0, 0)) { 1065 return; // failure, fAddr is NULL 1066 } 1067 fAddr = fBitmap.getPixels(); 1068 fRowBytes = fBitmap.rowBytes(); 1069 } 1070 SkASSERT(fAddr); // success 1071} 1072 1073bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const { 1074 if (fAddr) { 1075 return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes); 1076 } else { 1077 bitmap->reset(); 1078 return false; 1079 } 1080} 1081 1082///////////////////////////////////////////////////////////////////////////// 1083void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 1084 const SkMatrix& matrix, const SkPaint* paint) { 1085 if (bitmap.drawsNothing()) { 1086 return; 1087 } 1088 1089 SkLazyPaint lazy; 1090 if (NULL == paint) { 1091 paint = lazy.init(); 1092 } 1093 1094 SkDEBUGCODE(bitmap.validate();) 1095 1096 SkRect storage; 1097 const SkRect* bounds = NULL; 1098 if (paint && paint->canComputeFastBounds()) { 1099 bitmap.getBounds(&storage); 1100 matrix.mapRect(&storage); 1101 bounds = &paint->computeFastBounds(storage, &storage); 1102 } 1103 1104 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1105 1106 while (iter.next()) { 1107 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 1108 } 1109 1110 LOOPER_END 1111} 1112 1113void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 1114 const SkPaint* paint) { 1115 SkPaint tmp; 1116 if (NULL == paint) { 1117 paint = &tmp; 1118 } 1119 1120 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1121 while (iter.next()) { 1122 SkBaseDevice* dstDev = iter.fDevice; 1123 paint = &looper.paint(); 1124 SkImageFilter* filter = paint->getImageFilter(); 1125 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1126 if (filter && !dstDev->canHandleImageFilter(filter)) { 1127 SkDeviceImageFilterProxy proxy(dstDev, fProps); 1128 SkBitmap dst; 1129 SkIPoint offset = SkIPoint::Make(0, 0); 1130 const SkBitmap& src = srcDev->accessBitmap(false); 1131 SkMatrix matrix = *iter.fMatrix; 1132 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1133 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height()); 1134 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache()); 1135 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1136 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { 1137 SkPaint tmpUnfiltered(*paint); 1138 tmpUnfiltered.setImageFilter(NULL); 1139 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1140 tmpUnfiltered); 1141 } 1142 } else { 1143 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1144 } 1145 } 1146 LOOPER_END 1147} 1148 1149void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) { 1150 if (gTreatSpriteAsBitmap) { 1151 this->save(); 1152 this->resetMatrix(); 1153 this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint); 1154 this->restore(); 1155 return; 1156 } 1157 1158 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()"); 1159 if (bitmap.drawsNothing()) { 1160 return; 1161 } 1162 SkDEBUGCODE(bitmap.validate();) 1163 1164 SkPaint tmp; 1165 if (NULL == paint) { 1166 paint = &tmp; 1167 } 1168 1169 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1170 1171 while (iter.next()) { 1172 paint = &looper.paint(); 1173 SkImageFilter* filter = paint->getImageFilter(); 1174 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1175 if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 1176 SkDeviceImageFilterProxy proxy(iter.fDevice, fProps); 1177 SkBitmap dst; 1178 SkIPoint offset = SkIPoint::Make(0, 0); 1179 SkMatrix matrix = *iter.fMatrix; 1180 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1181 const SkIRect clipBounds = bitmap.bounds(); 1182 SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache()); 1183 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1184 if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) { 1185 SkPaint tmpUnfiltered(*paint); 1186 tmpUnfiltered.setImageFilter(NULL); 1187 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1188 tmpUnfiltered); 1189 } 1190 } else { 1191 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 1192 } 1193 } 1194 LOOPER_END 1195} 1196 1197///////////////////////////////////////////////////////////////////////////// 1198void SkCanvas::translate(SkScalar dx, SkScalar dy) { 1199 SkMatrix m; 1200 m.setTranslate(dx, dy); 1201 this->concat(m); 1202} 1203 1204void SkCanvas::scale(SkScalar sx, SkScalar sy) { 1205 SkMatrix m; 1206 m.setScale(sx, sy); 1207 this->concat(m); 1208} 1209 1210void SkCanvas::rotate(SkScalar degrees) { 1211 SkMatrix m; 1212 m.setRotate(degrees); 1213 this->concat(m); 1214} 1215 1216void SkCanvas::skew(SkScalar sx, SkScalar sy) { 1217 SkMatrix m; 1218 m.setSkew(sx, sy); 1219 this->concat(m); 1220} 1221 1222void SkCanvas::concat(const SkMatrix& matrix) { 1223 if (matrix.isIdentity()) { 1224 return; 1225 } 1226 1227 this->checkForDeferredSave(); 1228 fDeviceCMDirty = true; 1229 fCachedLocalClipBoundsDirty = true; 1230 fMCRec->fMatrix.preConcat(matrix); 1231 1232 this->didConcat(matrix); 1233} 1234 1235void SkCanvas::setMatrix(const SkMatrix& matrix) { 1236 this->checkForDeferredSave(); 1237 fDeviceCMDirty = true; 1238 fCachedLocalClipBoundsDirty = true; 1239 fMCRec->fMatrix = matrix; 1240 this->didSetMatrix(matrix); 1241} 1242 1243void SkCanvas::resetMatrix() { 1244 SkMatrix matrix; 1245 1246 matrix.reset(); 1247 this->setMatrix(matrix); 1248} 1249 1250////////////////////////////////////////////////////////////////////////////// 1251 1252void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1253 this->checkForDeferredSave(); 1254 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1255 this->onClipRect(rect, op, edgeStyle); 1256} 1257 1258void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1259#ifdef SK_ENABLE_CLIP_QUICKREJECT 1260 if (SkRegion::kIntersect_Op == op) { 1261 if (fMCRec->fRasterClip.isEmpty()) { 1262 return false; 1263 } 1264 1265 if (this->quickReject(rect)) { 1266 fDeviceCMDirty = true; 1267 fCachedLocalClipBoundsDirty = true; 1268 1269 fClipStack.clipEmpty(); 1270 return fMCRec->fRasterClip.setEmpty(); 1271 } 1272 } 1273#endif 1274 1275 AutoValidateClip avc(this); 1276 1277 fDeviceCMDirty = true; 1278 fCachedLocalClipBoundsDirty = true; 1279 if (!fAllowSoftClip) { 1280 edgeStyle = kHard_ClipEdgeStyle; 1281 } 1282 1283 if (fMCRec->fMatrix.rectStaysRect()) { 1284 // for these simpler matrices, we can stay a rect even after applying 1285 // the matrix. This means we don't have to a) make a path, and b) tell 1286 // the region code to scan-convert the path, only to discover that it 1287 // is really just a rect. 1288 SkRect r; 1289 1290 fMCRec->fMatrix.mapRect(&r, rect); 1291 fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1292 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle); 1293 } else { 1294 // since we're rotated or some such thing, we convert the rect to a path 1295 // and clip against that, since it can handle any matrix. However, to 1296 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1297 // we explicitly call "our" version of clipPath. 1298 SkPath path; 1299 1300 path.addRect(rect); 1301 this->SkCanvas::onClipPath(path, op, edgeStyle); 1302 } 1303} 1304 1305static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath, 1306 SkRegion::Op op, bool doAA) { 1307 rc->op(devPath, canvas->getBaseLayerSize(), op, doAA); 1308} 1309 1310void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1311 this->checkForDeferredSave(); 1312 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1313 if (rrect.isRect()) { 1314 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1315 } else { 1316 this->onClipRRect(rrect, op, edgeStyle); 1317 } 1318} 1319 1320void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1321 SkRRect transformedRRect; 1322 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1323 AutoValidateClip avc(this); 1324 1325 fDeviceCMDirty = true; 1326 fCachedLocalClipBoundsDirty = true; 1327 if (!fAllowSoftClip) { 1328 edgeStyle = kHard_ClipEdgeStyle; 1329 } 1330 1331 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1332 1333 SkPath devPath; 1334 devPath.addRRect(transformedRRect); 1335 1336 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1337 return; 1338 } 1339 1340 SkPath path; 1341 path.addRRect(rrect); 1342 // call the non-virtual version 1343 this->SkCanvas::onClipPath(path, op, edgeStyle); 1344} 1345 1346void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1347 this->checkForDeferredSave(); 1348 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1349 SkRect r; 1350 if (!path.isInverseFillType() && path.isRect(&r)) { 1351 this->onClipRect(r, op, edgeStyle); 1352 } else { 1353 this->onClipPath(path, op, edgeStyle); 1354 } 1355} 1356 1357void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1358#ifdef SK_ENABLE_CLIP_QUICKREJECT 1359 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1360 if (fMCRec->fRasterClip.isEmpty()) { 1361 return false; 1362 } 1363 1364 if (this->quickReject(path.getBounds())) { 1365 fDeviceCMDirty = true; 1366 fCachedLocalClipBoundsDirty = true; 1367 1368 fClipStack.clipEmpty(); 1369 return fMCRec->fRasterClip.setEmpty(); 1370 } 1371 } 1372#endif 1373 1374 AutoValidateClip avc(this); 1375 1376 fDeviceCMDirty = true; 1377 fCachedLocalClipBoundsDirty = true; 1378 if (!fAllowSoftClip) { 1379 edgeStyle = kHard_ClipEdgeStyle; 1380 } 1381 1382 SkPath devPath; 1383 path.transform(fMCRec->fMatrix, &devPath); 1384 1385 // Check if the transfomation, or the original path itself 1386 // made us empty. Note this can also happen if we contained NaN 1387 // values. computing the bounds detects this, and will set our 1388 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1389 if (devPath.getBounds().isEmpty()) { 1390 // resetting the path will remove any NaN or other wanky values 1391 // that might upset our scan converter. 1392 devPath.reset(); 1393 } 1394 1395 // if we called path.swap() we could avoid a deep copy of this path 1396 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1397 1398 if (fAllowSimplifyClip) { 1399 bool clipIsAA = getClipStack()->asPath(&devPath); 1400 if (clipIsAA) { 1401 edgeStyle = kSoft_ClipEdgeStyle; 1402 } 1403 1404 op = SkRegion::kReplace_Op; 1405 } 1406 1407 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); 1408} 1409 1410void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1411 this->checkForDeferredSave(); 1412 this->onClipRegion(rgn, op); 1413} 1414 1415void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1416 AutoValidateClip avc(this); 1417 1418 fDeviceCMDirty = true; 1419 fCachedLocalClipBoundsDirty = true; 1420 1421 // todo: signal fClipStack that we have a region, and therefore (I guess) 1422 // we have to ignore it, and use the region directly? 1423 fClipStack->clipDevRect(rgn.getBounds(), op); 1424 1425 fMCRec->fRasterClip.op(rgn, op); 1426} 1427 1428#ifdef SK_DEBUG 1429void SkCanvas::validateClip() const { 1430 // construct clipRgn from the clipstack 1431 const SkBaseDevice* device = this->getDevice(); 1432 if (!device) { 1433 SkASSERT(this->isClipEmpty()); 1434 return; 1435 } 1436 1437 SkIRect ir; 1438 ir.set(0, 0, device->width(), device->height()); 1439 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1440 1441 SkClipStack::B2TIter iter(*fClipStack); 1442 const SkClipStack::Element* element; 1443 while ((element = iter.next()) != NULL) { 1444 switch (element->getType()) { 1445 case SkClipStack::Element::kRect_Type: 1446 element->getRect().round(&ir); 1447 tmpClip.op(ir, element->getOp()); 1448 break; 1449 case SkClipStack::Element::kEmpty_Type: 1450 tmpClip.setEmpty(); 1451 break; 1452 default: { 1453 SkPath path; 1454 element->asPath(&path); 1455 rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA()); 1456 break; 1457 } 1458 } 1459 } 1460} 1461#endif 1462 1463void SkCanvas::replayClips(ClipVisitor* visitor) const { 1464 SkClipStack::B2TIter iter(*fClipStack); 1465 const SkClipStack::Element* element; 1466 1467 while ((element = iter.next()) != NULL) { 1468 element->replay(visitor); 1469 } 1470} 1471 1472/////////////////////////////////////////////////////////////////////////////// 1473 1474bool SkCanvas::isClipEmpty() const { 1475 return fMCRec->fRasterClip.isEmpty(); 1476} 1477 1478bool SkCanvas::isClipRect() const { 1479 return fMCRec->fRasterClip.isRect(); 1480} 1481 1482bool SkCanvas::quickReject(const SkRect& rect) const { 1483 if (!rect.isFinite()) 1484 return true; 1485 1486 if (fMCRec->fRasterClip.isEmpty()) { 1487 return true; 1488 } 1489 1490 if (fMCRec->fMatrix.hasPerspective()) { 1491 SkRect dst; 1492 fMCRec->fMatrix.mapRect(&dst, rect); 1493 return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds()); 1494 } else { 1495 const SkRect& clipR = this->getLocalClipBounds(); 1496 1497 // for speed, do the most likely reject compares first 1498 // TODO: should we use | instead, or compare all 4 at once? 1499 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1500 return true; 1501 } 1502 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1503 return true; 1504 } 1505 return false; 1506 } 1507} 1508 1509bool SkCanvas::quickReject(const SkPath& path) const { 1510 return path.isEmpty() || this->quickReject(path.getBounds()); 1511} 1512 1513bool SkCanvas::getClipBounds(SkRect* bounds) const { 1514 SkIRect ibounds; 1515 if (!this->getClipDeviceBounds(&ibounds)) { 1516 return false; 1517 } 1518 1519 SkMatrix inverse; 1520 // if we can't invert the CTM, we can't return local clip bounds 1521 if (!fMCRec->fMatrix.invert(&inverse)) { 1522 if (bounds) { 1523 bounds->setEmpty(); 1524 } 1525 return false; 1526 } 1527 1528 if (bounds) { 1529 SkRect r; 1530 // adjust it outwards in case we are antialiasing 1531 const int inset = 1; 1532 1533 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1534 ibounds.fRight + inset, ibounds.fBottom + inset); 1535 inverse.mapRect(bounds, r); 1536 } 1537 return true; 1538} 1539 1540bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1541 const SkRasterClip& clip = fMCRec->fRasterClip; 1542 if (clip.isEmpty()) { 1543 if (bounds) { 1544 bounds->setEmpty(); 1545 } 1546 return false; 1547 } 1548 1549 if (bounds) { 1550 *bounds = clip.getBounds(); 1551 } 1552 return true; 1553} 1554 1555const SkMatrix& SkCanvas::getTotalMatrix() const { 1556 return fMCRec->fMatrix; 1557} 1558 1559const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1560 return fMCRec->fRasterClip.forceGetBW(); 1561} 1562 1563GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { 1564 SkBaseDevice* dev = this->getTopDevice(); 1565 return dev ? dev->accessRenderTarget() : NULL; 1566} 1567 1568GrContext* SkCanvas::getGrContext() { 1569#if SK_SUPPORT_GPU 1570 SkBaseDevice* device = this->getTopDevice(); 1571 if (device) { 1572 GrRenderTarget* renderTarget = device->accessRenderTarget(); 1573 if (renderTarget) { 1574 return renderTarget->getContext(); 1575 } 1576 } 1577#endif 1578 1579 return NULL; 1580 1581} 1582 1583void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1584 const SkPaint& paint) { 1585 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()"); 1586 if (outer.isEmpty()) { 1587 return; 1588 } 1589 if (inner.isEmpty()) { 1590 this->drawRRect(outer, paint); 1591 return; 1592 } 1593 1594 // We don't have this method (yet), but technically this is what we should 1595 // be able to assert... 1596 // SkASSERT(outer.contains(inner)); 1597 // 1598 // For now at least check for containment of bounds 1599 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1600 1601 this->onDrawDRRect(outer, inner, paint); 1602} 1603 1604// These need to stop being virtual -- clients need to override the onDraw... versions 1605 1606void SkCanvas::drawPaint(const SkPaint& paint) { 1607 this->onDrawPaint(paint); 1608} 1609 1610void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1611 this->onDrawRect(r, paint); 1612} 1613 1614void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) { 1615 this->onDrawOval(r, paint); 1616} 1617 1618void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1619 this->onDrawRRect(rrect, paint); 1620} 1621 1622void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { 1623 this->onDrawPoints(mode, count, pts, paint); 1624} 1625 1626void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], 1627 const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, 1628 const uint16_t indices[], int indexCount, const SkPaint& paint) { 1629 this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 1630 indices, indexCount, paint); 1631} 1632 1633void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1634 this->onDrawPath(path, paint); 1635} 1636 1637void SkCanvas::drawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1638 this->onDrawImage(image, dx, dy, paint); 1639} 1640 1641void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1642 const SkPaint* paint) { 1643 this->onDrawImageRect(image, src, dst, paint); 1644} 1645 1646void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1647 this->onDrawBitmap(bitmap, dx, dy, paint); 1648} 1649 1650void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 1651 const SkPaint* paint, DrawBitmapRectFlags flags) { 1652 this->onDrawBitmapRect(bitmap, src, dst, paint, flags); 1653} 1654 1655void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 1656 const SkPaint* paint) { 1657 this->onDrawBitmapNine(bitmap, center, dst, paint); 1658} 1659 1660void SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { 1661 this->onDrawSprite(bitmap, left, top, paint); 1662} 1663 1664////////////////////////////////////////////////////////////////////////////// 1665// These are the virtual drawing methods 1666////////////////////////////////////////////////////////////////////////////// 1667 1668void SkCanvas::onDiscard() { 1669 if (fSurfaceBase) { 1670 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 1671 } 1672} 1673 1674void SkCanvas::onDrawPaint(const SkPaint& paint) { 1675 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 1676 this->internalDrawPaint(paint); 1677} 1678 1679void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1680 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 1681 1682 while (iter.next()) { 1683 iter.fDevice->drawPaint(iter, looper.paint()); 1684 } 1685 1686 LOOPER_END 1687} 1688 1689void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 1690 const SkPaint& paint) { 1691 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 1692 if ((long)count <= 0) { 1693 return; 1694 } 1695 1696 SkRect r, storage; 1697 const SkRect* bounds = NULL; 1698 if (paint.canComputeFastBounds()) { 1699 // special-case 2 points (common for drawing a single line) 1700 if (2 == count) { 1701 r.set(pts[0], pts[1]); 1702 } else { 1703 r.set(pts, SkToInt(count)); 1704 } 1705 bounds = &paint.computeFastStrokeBounds(r, &storage); 1706 if (this->quickReject(*bounds)) { 1707 return; 1708 } 1709 } 1710 1711 SkASSERT(pts != NULL); 1712 1713 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 1714 1715 while (iter.next()) { 1716 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1717 } 1718 1719 LOOPER_END 1720} 1721 1722void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { 1723 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 1724 SkRect storage; 1725 const SkRect* bounds = NULL; 1726 if (paint.canComputeFastBounds()) { 1727 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream. 1728 // To prevent accidental rejecting at this stage, we have to sort it before we check. 1729 SkRect tmp(r); 1730 tmp.sort(); 1731 1732 bounds = &paint.computeFastBounds(tmp, &storage); 1733 if (this->quickReject(*bounds)) { 1734 return; 1735 } 1736 } 1737 1738 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 1739 1740 while (iter.next()) { 1741 iter.fDevice->drawRect(iter, r, looper.paint()); 1742 } 1743 1744 LOOPER_END 1745} 1746 1747void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 1748 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 1749 SkRect storage; 1750 const SkRect* bounds = NULL; 1751 if (paint.canComputeFastBounds()) { 1752 bounds = &paint.computeFastBounds(oval, &storage); 1753 if (this->quickReject(*bounds)) { 1754 return; 1755 } 1756 } 1757 1758 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 1759 1760 while (iter.next()) { 1761 iter.fDevice->drawOval(iter, oval, looper.paint()); 1762 } 1763 1764 LOOPER_END 1765} 1766 1767void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 1768 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 1769 SkRect storage; 1770 const SkRect* bounds = NULL; 1771 if (paint.canComputeFastBounds()) { 1772 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 1773 if (this->quickReject(*bounds)) { 1774 return; 1775 } 1776 } 1777 1778 if (rrect.isRect()) { 1779 // call the non-virtual version 1780 this->SkCanvas::drawRect(rrect.getBounds(), paint); 1781 return; 1782 } else if (rrect.isOval()) { 1783 // call the non-virtual version 1784 this->SkCanvas::drawOval(rrect.getBounds(), paint); 1785 return; 1786 } 1787 1788 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1789 1790 while (iter.next()) { 1791 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1792 } 1793 1794 LOOPER_END 1795} 1796 1797void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1798 const SkPaint& paint) { 1799 SkRect storage; 1800 const SkRect* bounds = NULL; 1801 if (paint.canComputeFastBounds()) { 1802 bounds = &paint.computeFastBounds(outer.getBounds(), &storage); 1803 if (this->quickReject(*bounds)) { 1804 return; 1805 } 1806 } 1807 1808 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1809 1810 while (iter.next()) { 1811 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 1812 } 1813 1814 LOOPER_END 1815} 1816 1817void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 1818 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 1819 if (!path.isFinite()) { 1820 return; 1821 } 1822 1823 SkRect storage; 1824 const SkRect* bounds = NULL; 1825 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1826 const SkRect& pathBounds = path.getBounds(); 1827 bounds = &paint.computeFastBounds(pathBounds, &storage); 1828 if (this->quickReject(*bounds)) { 1829 return; 1830 } 1831 } 1832 1833 const SkRect& r = path.getBounds(); 1834 if (r.width() <= 0 && r.height() <= 0) { 1835 if (path.isInverseFillType()) { 1836 this->internalDrawPaint(paint); 1837 } 1838 return; 1839 } 1840 1841 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 1842 1843 while (iter.next()) { 1844 iter.fDevice->drawPath(iter, path, looper.paint()); 1845 } 1846 1847 LOOPER_END 1848} 1849 1850void SkCanvas::onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1851 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 1852 image->draw(this, dx, dy, paint); 1853} 1854 1855void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1856 const SkPaint* paint) { 1857 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 1858 image->drawRect(this, src, dst, paint); 1859} 1860 1861void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 1862 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 1863 SkDEBUGCODE(bitmap.validate();) 1864 1865 if (NULL == paint || paint->canComputeFastBounds()) { 1866 SkRect bounds = { 1867 x, y, 1868 x + SkIntToScalar(bitmap.width()), 1869 y + SkIntToScalar(bitmap.height()) 1870 }; 1871 if (paint) { 1872 (void)paint->computeFastBounds(bounds, &bounds); 1873 } 1874 if (this->quickReject(bounds)) { 1875 return; 1876 } 1877 } 1878 1879 SkMatrix matrix; 1880 matrix.setTranslate(x, y); 1881 this->internalDrawBitmap(bitmap, matrix, paint); 1882} 1883 1884// this one is non-virtual, so it can be called safely by other canvas apis 1885void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 1886 const SkRect& dst, const SkPaint* paint, 1887 DrawBitmapRectFlags flags) { 1888 if (bitmap.drawsNothing() || dst.isEmpty()) { 1889 return; 1890 } 1891 1892 SkRect storage; 1893 const SkRect* bounds = &dst; 1894 if (NULL == paint || paint->canComputeFastBounds()) { 1895 if (paint) { 1896 bounds = &paint->computeFastBounds(dst, &storage); 1897 } 1898 if (this->quickReject(*bounds)) { 1899 return; 1900 } 1901 } 1902 1903 SkLazyPaint lazy; 1904 if (NULL == paint) { 1905 paint = lazy.init(); 1906 } 1907 1908 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1909 1910 while (iter.next()) { 1911 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 1912 } 1913 1914 LOOPER_END 1915} 1916 1917void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 1918 const SkPaint* paint, DrawBitmapRectFlags flags) { 1919 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 1920 SkDEBUGCODE(bitmap.validate();) 1921 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 1922} 1923 1924void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 1925 const SkIRect& center, const SkRect& dst, 1926 const SkPaint* paint) { 1927 if (bitmap.drawsNothing()) { 1928 return; 1929 } 1930 if (NULL == paint || paint->canComputeFastBounds()) { 1931 SkRect storage; 1932 const SkRect* bounds = &dst; 1933 if (paint) { 1934 bounds = &paint->computeFastBounds(dst, &storage); 1935 } 1936 if (this->quickReject(*bounds)) { 1937 return; 1938 } 1939 } 1940 1941 const int32_t w = bitmap.width(); 1942 const int32_t h = bitmap.height(); 1943 1944 SkIRect c = center; 1945 // pin center to the bounds of the bitmap 1946 c.fLeft = SkMax32(0, center.fLeft); 1947 c.fTop = SkMax32(0, center.fTop); 1948 c.fRight = SkPin32(center.fRight, c.fLeft, w); 1949 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 1950 1951 const SkScalar srcX[4] = { 1952 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 1953 }; 1954 const SkScalar srcY[4] = { 1955 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 1956 }; 1957 SkScalar dstX[4] = { 1958 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 1959 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 1960 }; 1961 SkScalar dstY[4] = { 1962 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 1963 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 1964 }; 1965 1966 if (dstX[1] > dstX[2]) { 1967 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 1968 dstX[2] = dstX[1]; 1969 } 1970 1971 if (dstY[1] > dstY[2]) { 1972 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 1973 dstY[2] = dstY[1]; 1974 } 1975 1976 for (int y = 0; y < 3; y++) { 1977 SkRect s, d; 1978 1979 s.fTop = srcY[y]; 1980 s.fBottom = srcY[y+1]; 1981 d.fTop = dstY[y]; 1982 d.fBottom = dstY[y+1]; 1983 for (int x = 0; x < 3; x++) { 1984 s.fLeft = srcX[x]; 1985 s.fRight = srcX[x+1]; 1986 d.fLeft = dstX[x]; 1987 d.fRight = dstX[x+1]; 1988 this->internalDrawBitmapRect(bitmap, &s, d, paint, 1989 kNone_DrawBitmapRectFlag); 1990 } 1991 } 1992} 1993 1994void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 1995 const SkPaint* paint) { 1996 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 1997 SkDEBUGCODE(bitmap.validate();) 1998 1999 // Need a device entry-point, so gpu can use a mesh 2000 this->internalDrawBitmapNine(bitmap, center, dst, paint); 2001} 2002 2003class SkDeviceFilteredPaint { 2004public: 2005 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2006 uint32_t filteredFlags = device->filterTextFlags(paint); 2007 if (filteredFlags != paint.getFlags()) { 2008 SkPaint* newPaint = fLazy.set(paint); 2009 newPaint->setFlags(filteredFlags); 2010 fPaint = newPaint; 2011 } else { 2012 fPaint = &paint; 2013 } 2014 } 2015 2016 const SkPaint& paint() const { return *fPaint; } 2017 2018private: 2019 const SkPaint* fPaint; 2020 SkLazyPaint fLazy; 2021}; 2022 2023void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2024 const SkRect& r, SkScalar textSize) { 2025 if (paint.getStyle() == SkPaint::kFill_Style) { 2026 draw.fDevice->drawRect(draw, r, paint); 2027 } else { 2028 SkPaint p(paint); 2029 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2030 draw.fDevice->drawRect(draw, r, p); 2031 } 2032} 2033 2034void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2035 const char text[], size_t byteLength, 2036 SkScalar x, SkScalar y) { 2037 SkASSERT(byteLength == 0 || text != NULL); 2038 2039 // nothing to draw 2040 if (text == NULL || byteLength == 0 || 2041 draw.fClip->isEmpty() || 2042 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2043 return; 2044 } 2045 2046 SkScalar width = 0; 2047 SkPoint start; 2048 2049 start.set(0, 0); // to avoid warning 2050 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2051 SkPaint::kStrikeThruText_Flag)) { 2052 width = paint.measureText(text, byteLength); 2053 2054 SkScalar offsetX = 0; 2055 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2056 offsetX = SkScalarHalf(width); 2057 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2058 offsetX = width; 2059 } 2060 start.set(x - offsetX, y); 2061 } 2062 2063 if (0 == width) { 2064 return; 2065 } 2066 2067 uint32_t flags = paint.getFlags(); 2068 2069 if (flags & (SkPaint::kUnderlineText_Flag | 2070 SkPaint::kStrikeThruText_Flag)) { 2071 SkScalar textSize = paint.getTextSize(); 2072 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2073 SkRect r; 2074 2075 r.fLeft = start.fX; 2076 r.fRight = start.fX + width; 2077 2078 if (flags & SkPaint::kUnderlineText_Flag) { 2079 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2080 start.fY); 2081 r.fTop = offset; 2082 r.fBottom = offset + height; 2083 DrawRect(draw, paint, r, textSize); 2084 } 2085 if (flags & SkPaint::kStrikeThruText_Flag) { 2086 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2087 start.fY); 2088 r.fTop = offset; 2089 r.fBottom = offset + height; 2090 DrawRect(draw, paint, r, textSize); 2091 } 2092 } 2093} 2094 2095void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2096 const SkPaint& paint) { 2097 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2098 2099 while (iter.next()) { 2100 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2101 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2102 DrawTextDecorations(iter, dfp.paint(), 2103 static_cast<const char*>(text), byteLength, x, y); 2104 } 2105 2106 LOOPER_END 2107} 2108 2109void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2110 const SkPaint& paint) { 2111 SkPoint textOffset = SkPoint::Make(0, 0); 2112 2113 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2114 2115 while (iter.next()) { 2116 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2117 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2118 dfp.paint()); 2119 } 2120 2121 LOOPER_END 2122} 2123 2124void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2125 SkScalar constY, const SkPaint& paint) { 2126 2127 SkPoint textOffset = SkPoint::Make(0, constY); 2128 2129 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2130 2131 while (iter.next()) { 2132 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2133 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2134 dfp.paint()); 2135 } 2136 2137 LOOPER_END 2138} 2139 2140void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2141 const SkMatrix* matrix, const SkPaint& paint) { 2142 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2143 2144 while (iter.next()) { 2145 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2146 matrix, looper.paint()); 2147 } 2148 2149 LOOPER_END 2150} 2151 2152void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2153 const SkPaint& paint) { 2154 2155 SkRect storage; 2156 const SkRect* bounds = NULL; 2157 if (paint.canComputeFastBounds()) { 2158 storage = blob->bounds().makeOffset(x, y); 2159 bounds = &paint.computeFastBounds(storage, &storage); 2160 2161 if (this->quickReject(*bounds)) { 2162 return; 2163 } 2164 } 2165 2166 // We cannot filter in the looper as we normally do, because the paint is 2167 // incomplete at this point (text-related attributes are embedded within blob run paints). 2168 SkDrawFilter* drawFilter = fMCRec->fFilter; 2169 fMCRec->fFilter = NULL; 2170 2171 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2172 2173 while (iter.next()) { 2174 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2175 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); 2176 } 2177 2178 LOOPER_END 2179 2180 fMCRec->fFilter = drawFilter; 2181} 2182 2183// These will become non-virtual, so they always call the (virtual) onDraw... method 2184void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2185 const SkPaint& paint) { 2186 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2187 this->onDrawText(text, byteLength, x, y, paint); 2188} 2189void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2190 const SkPaint& paint) { 2191 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2192 this->onDrawPosText(text, byteLength, pos, paint); 2193} 2194void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2195 SkScalar constY, const SkPaint& paint) { 2196 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2197 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2198} 2199void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2200 const SkMatrix* matrix, const SkPaint& paint) { 2201 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2202 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2203} 2204void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2205 const SkPaint& paint) { 2206 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2207 if (blob) { 2208 this->onDrawTextBlob(blob, x, y, paint); 2209 } 2210} 2211 2212void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 2213 const SkPoint verts[], const SkPoint texs[], 2214 const SkColor colors[], SkXfermode* xmode, 2215 const uint16_t indices[], int indexCount, 2216 const SkPaint& paint) { 2217 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2218 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2219 2220 while (iter.next()) { 2221 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2222 colors, xmode, indices, indexCount, 2223 looper.paint()); 2224 } 2225 2226 LOOPER_END 2227} 2228 2229void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2230 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2231 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2232 if (NULL == cubics) { 2233 return; 2234 } 2235 2236 // Since a patch is always within the convex hull of the control points, we discard it when its 2237 // bounding rectangle is completely outside the current clip. 2238 SkRect bounds; 2239 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2240 if (this->quickReject(bounds)) { 2241 return; 2242 } 2243 2244 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2245} 2246 2247void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2248 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2249 2250 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2251 2252 while (iter.next()) { 2253 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2254 } 2255 2256 LOOPER_END 2257} 2258 2259void SkCanvas::drawDrawable(SkDrawable* dr) { 2260 if (dr && !this->quickReject(dr->getBounds())) { 2261 this->onDrawDrawable(dr); 2262 } 2263} 2264 2265void SkCanvas::onDrawDrawable(SkDrawable* dr) { 2266 dr->draw(this); 2267} 2268 2269////////////////////////////////////////////////////////////////////////////// 2270// These methods are NOT virtual, and therefore must call back into virtual 2271// methods, rather than actually drawing themselves. 2272////////////////////////////////////////////////////////////////////////////// 2273 2274void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2275 SkXfermode::Mode mode) { 2276 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2277 SkPaint paint; 2278 2279 paint.setARGB(a, r, g, b); 2280 if (SkXfermode::kSrcOver_Mode != mode) { 2281 paint.setXfermodeMode(mode); 2282 } 2283 this->drawPaint(paint); 2284} 2285 2286void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2287 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2288 SkPaint paint; 2289 2290 paint.setColor(c); 2291 if (SkXfermode::kSrcOver_Mode != mode) { 2292 paint.setXfermodeMode(mode); 2293 } 2294 this->drawPaint(paint); 2295} 2296 2297void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2298 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2299 SkPoint pt; 2300 2301 pt.set(x, y); 2302 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2303} 2304 2305void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2306 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2307 SkPoint pt; 2308 SkPaint paint; 2309 2310 pt.set(x, y); 2311 paint.setColor(color); 2312 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2313} 2314 2315void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2316 const SkPaint& paint) { 2317 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 2318 SkPoint pts[2]; 2319 2320 pts[0].set(x0, y0); 2321 pts[1].set(x1, y1); 2322 this->drawPoints(kLines_PointMode, 2, pts, paint); 2323} 2324 2325void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2326 SkScalar right, SkScalar bottom, 2327 const SkPaint& paint) { 2328 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 2329 SkRect r; 2330 2331 r.set(left, top, right, bottom); 2332 this->drawRect(r, paint); 2333} 2334 2335void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2336 const SkPaint& paint) { 2337 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 2338 if (radius < 0) { 2339 radius = 0; 2340 } 2341 2342 SkRect r; 2343 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2344 this->drawOval(r, paint); 2345} 2346 2347void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2348 const SkPaint& paint) { 2349 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 2350 if (rx > 0 && ry > 0) { 2351 if (paint.canComputeFastBounds()) { 2352 SkRect storage; 2353 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2354 return; 2355 } 2356 } 2357 SkRRect rrect; 2358 rrect.setRectXY(r, rx, ry); 2359 this->drawRRect(rrect, paint); 2360 } else { 2361 this->drawRect(r, paint); 2362 } 2363} 2364 2365void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2366 SkScalar sweepAngle, bool useCenter, 2367 const SkPaint& paint) { 2368 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2369 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2370 this->drawOval(oval, paint); 2371 } else { 2372 SkPath path; 2373 if (useCenter) { 2374 path.moveTo(oval.centerX(), oval.centerY()); 2375 } 2376 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2377 if (useCenter) { 2378 path.close(); 2379 } 2380 this->drawPath(path, paint); 2381 } 2382} 2383 2384void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2385 const SkPath& path, SkScalar hOffset, 2386 SkScalar vOffset, const SkPaint& paint) { 2387 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 2388 SkMatrix matrix; 2389 2390 matrix.setTranslate(hOffset, vOffset); 2391 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2392} 2393 2394/////////////////////////////////////////////////////////////////////////////// 2395void SkCanvas::drawPicture(const SkPicture* picture) { 2396 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 2397 if (picture) { 2398 this->onDrawPicture(picture, NULL, NULL); 2399 } 2400} 2401 2402void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2403 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)"); 2404 if (picture) { 2405 if (matrix && matrix->isIdentity()) { 2406 matrix = NULL; 2407 } 2408 this->onDrawPicture(picture, matrix, paint); 2409 } 2410} 2411 2412void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2413 const SkPaint* paint) { 2414 SkBaseDevice* device = this->getTopDevice(); 2415 if (device) { 2416 // Canvas has to first give the device the opportunity to render 2417 // the picture itself. 2418 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) { 2419 return; // the device has rendered the entire picture 2420 } 2421 } 2422 2423 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2424 2425 picture->playback(this); 2426} 2427 2428/////////////////////////////////////////////////////////////////////////////// 2429/////////////////////////////////////////////////////////////////////////////// 2430 2431SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2432 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 2433 2434 SkASSERT(canvas); 2435 2436 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2437 fDone = !fImpl->next(); 2438} 2439 2440SkCanvas::LayerIter::~LayerIter() { 2441 fImpl->~SkDrawIter(); 2442} 2443 2444void SkCanvas::LayerIter::next() { 2445 fDone = !fImpl->next(); 2446} 2447 2448SkBaseDevice* SkCanvas::LayerIter::device() const { 2449 return fImpl->getDevice(); 2450} 2451 2452const SkMatrix& SkCanvas::LayerIter::matrix() const { 2453 return fImpl->getMatrix(); 2454} 2455 2456const SkPaint& SkCanvas::LayerIter::paint() const { 2457 const SkPaint* paint = fImpl->getPaint(); 2458 if (NULL == paint) { 2459 paint = &fDefaultPaint; 2460 } 2461 return *paint; 2462} 2463 2464const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2465int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2466int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2467 2468/////////////////////////////////////////////////////////////////////////////// 2469 2470SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 2471 2472/////////////////////////////////////////////////////////////////////////////// 2473 2474static bool supported_for_raster_canvas(const SkImageInfo& info) { 2475 switch (info.alphaType()) { 2476 case kPremul_SkAlphaType: 2477 case kOpaque_SkAlphaType: 2478 break; 2479 default: 2480 return false; 2481 } 2482 2483 switch (info.colorType()) { 2484 case kAlpha_8_SkColorType: 2485 case kRGB_565_SkColorType: 2486 case kN32_SkColorType: 2487 break; 2488 default: 2489 return false; 2490 } 2491 2492 return true; 2493} 2494 2495SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 2496 if (!supported_for_raster_canvas(info)) { 2497 return NULL; 2498 } 2499 2500 SkBitmap bitmap; 2501 if (!bitmap.installPixels(info, pixels, rowBytes)) { 2502 return NULL; 2503 } 2504 return SkNEW_ARGS(SkCanvas, (bitmap)); 2505} 2506 2507/////////////////////////////////////////////////////////////////////////////// 2508 2509SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 2510 const SkPaint* paint, const SkRect& bounds) 2511 : fCanvas(canvas) 2512 , fSaveCount(canvas->getSaveCount()) 2513{ 2514 if (paint) { 2515 SkRect newBounds = bounds; 2516 if (matrix) { 2517 matrix->mapRect(&newBounds); 2518 } 2519 canvas->saveLayer(&newBounds, paint); 2520 } else if (matrix) { 2521 canvas->save(); 2522 } 2523 2524 if (matrix) { 2525 canvas->concat(*matrix); 2526 } 2527} 2528 2529SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2530 fCanvas->restoreToCount(fSaveCount); 2531} 2532