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