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