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