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