SkCanvas.cpp revision 9637ea91b88ff8f8e95325bfc41417ffc4d5ee0b
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 "SkBitmapDevice.h" 9#include "SkCanvas.h" 10#include "SkCanvasPriv.h" 11#include "SkClipStack.h" 12#include "SkColorFilter.h" 13#include "SkDraw.h" 14#include "SkDrawable.h" 15#include "SkDrawFilter.h" 16#include "SkDrawLooper.h" 17#include "SkErrorInternals.h" 18#include "SkImage.h" 19#include "SkImage_Base.h" 20#include "SkImageFilter.h" 21#include "SkImageFilterCache.h" 22#include "SkLatticeIter.h" 23#include "SkMatrixUtils.h" 24#include "SkMetaData.h" 25#include "SkNx.h" 26#include "SkPaintPriv.h" 27#include "SkPatchUtils.h" 28#include "SkPicture.h" 29#include "SkRasterClip.h" 30#include "SkReadPixelsRec.h" 31#include "SkRRect.h" 32#include "SkShadowPaintFilterCanvas.h" 33#include "SkShadowShader.h" 34#include "SkSmallAllocator.h" 35#include "SkSpecialImage.h" 36#include "SkSurface_Base.h" 37#include "SkTextBlob.h" 38#include "SkTextFormatParams.h" 39#include "SkTLazy.h" 40#include "SkTraceEvent.h" 41 42#include <new> 43 44#if SK_SUPPORT_GPU 45#include "GrContext.h" 46#include "GrRenderTarget.h" 47#include "SkGrPriv.h" 48#endif 49 50#define RETURN_ON_NULL(ptr) do { if (nullptr == (ptr)) return; } while (0) 51 52//#define SK_SUPPORT_PRECHECK_CLIPRECT 53 54/* 55 * Return true if the drawing this rect would hit every pixels in the canvas. 56 * 57 * Returns false if 58 * - rect does not contain the canvas' bounds 59 * - paint is not fill 60 * - paint would blur or otherwise change the coverage of the rect 61 */ 62bool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint, 63 ShaderOverrideOpacity overrideOpacity) const { 64 static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity == 65 (int)kNone_ShaderOverrideOpacity, 66 "need_matching_enums0"); 67 static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity == 68 (int)kOpaque_ShaderOverrideOpacity, 69 "need_matching_enums1"); 70 static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity == 71 (int)kNotOpaque_ShaderOverrideOpacity, 72 "need_matching_enums2"); 73 74 const SkISize size = this->getBaseLayerSize(); 75 const SkRect bounds = SkRect::MakeIWH(size.width(), size.height()); 76 if (!this->getClipStack()->quickContains(bounds)) { 77 return false; 78 } 79 80 if (rect) { 81 if (!this->getTotalMatrix().isScaleTranslate()) { 82 return false; // conservative 83 } 84 85 SkRect devRect; 86 this->getTotalMatrix().mapRectScaleTranslate(&devRect, *rect); 87 if (!devRect.contains(bounds)) { 88 return false; 89 } 90 } 91 92 if (paint) { 93 SkPaint::Style paintStyle = paint->getStyle(); 94 if (!(paintStyle == SkPaint::kFill_Style || 95 paintStyle == SkPaint::kStrokeAndFill_Style)) { 96 return false; 97 } 98 if (paint->getMaskFilter() || paint->getLooper() 99 || paint->getPathEffect() || paint->getImageFilter()) { 100 return false; // conservative 101 } 102 } 103 return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity); 104} 105 106/////////////////////////////////////////////////////////////////////////////////////////////////// 107 108static bool gIgnoreSaveLayerBounds; 109void SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) { 110 gIgnoreSaveLayerBounds = ignore; 111} 112bool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() { 113 return gIgnoreSaveLayerBounds; 114} 115 116static bool gTreatSpriteAsBitmap; 117void SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) { 118 gTreatSpriteAsBitmap = spriteAsBitmap; 119} 120bool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() { 121 return gTreatSpriteAsBitmap; 122} 123 124// experimental for faster tiled drawing... 125//#define SK_ENABLE_CLIP_QUICKREJECT 126//#define SK_TRACE_SAVERESTORE 127 128#ifdef SK_TRACE_SAVERESTORE 129 static int gLayerCounter; 130 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 131 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 132 133 static int gRecCounter; 134 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 135 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 136 137 static int gCanvasCounter; 138 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 139 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 140#else 141 #define inc_layer() 142 #define dec_layer() 143 #define inc_rec() 144 #define dec_rec() 145 #define inc_canvas() 146 #define dec_canvas() 147#endif 148 149typedef SkTLazy<SkPaint> SkLazyPaint; 150 151void SkCanvas::predrawNotify(bool willOverwritesEntireSurface) { 152 if (fSurfaceBase) { 153 fSurfaceBase->aboutToDraw(willOverwritesEntireSurface 154 ? SkSurface::kDiscard_ContentChangeMode 155 : SkSurface::kRetain_ContentChangeMode); 156 } 157} 158 159void SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint, 160 ShaderOverrideOpacity overrideOpacity) { 161 if (fSurfaceBase) { 162 SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode; 163 // Since willOverwriteAllPixels() may not be complete free to call, we only do so if 164 // there is an outstanding snapshot, since w/o that, there will be no copy-on-write 165 // and therefore we don't care which mode we're in. 166 // 167 if (fSurfaceBase->outstandingImageSnapshot()) { 168 if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) { 169 mode = SkSurface::kDiscard_ContentChangeMode; 170 } 171 } 172 fSurfaceBase->aboutToDraw(mode); 173 } 174} 175 176/////////////////////////////////////////////////////////////////////////////// 177 178/* This is the record we keep for each SkBaseDevice that the user installs. 179 The clip/matrix/proc are fields that reflect the top of the save/restore 180 stack. Whenever the canvas changes, it marks a dirty flag, and then before 181 these are used (assuming we're not on a layer) we rebuild these cache 182 values: they reflect the top of the save stack, but translated and clipped 183 by the device's XY offset and bitmap-bounds. 184*/ 185struct DeviceCM { 186 DeviceCM* fNext; 187 SkBaseDevice* fDevice; 188 SkRasterClip fClip; 189 SkPaint* fPaint; // may be null (in the future) 190 const SkMatrix* fMatrix; 191 SkMatrix fMatrixStorage; 192 SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer 193 194 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, 195 bool conservativeRasterClip, const SkMatrix& stashed) 196 : fNext(nullptr) 197 , fClip(conservativeRasterClip) 198 , fStashedMatrix(stashed) 199 { 200 SkSafeRef(device); 201 fDevice = device; 202 fPaint = paint ? new SkPaint(*paint) : nullptr; 203 } 204 205 ~DeviceCM() { 206 SkSafeUnref(fDevice); 207 delete fPaint; 208 } 209 210 void reset(const SkIRect& bounds) { 211 SkASSERT(!fPaint); 212 SkASSERT(!fNext); 213 SkASSERT(fDevice); 214 fClip.setRect(bounds); 215 } 216 217 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 218 const SkClipStack& clipStack, SkRasterClip* updateClip) { 219 int x = fDevice->getOrigin().x(); 220 int y = fDevice->getOrigin().y(); 221 int width = fDevice->width(); 222 int height = fDevice->height(); 223 224 if ((x | y) == 0) { 225 fMatrix = &totalMatrix; 226 fClip = totalClip; 227 } else { 228 fMatrixStorage = totalMatrix; 229 fMatrixStorage.postTranslate(SkIntToScalar(-x), 230 SkIntToScalar(-y)); 231 fMatrix = &fMatrixStorage; 232 233 totalClip.translate(-x, -y, &fClip); 234 } 235 236 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 237 238 // intersect clip, but don't translate it (yet) 239 240 if (updateClip) { 241 updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 242 SkRegion::kDifference_Op); 243 } 244 245 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 246 247#ifdef SK_DEBUG 248 if (!fClip.isEmpty()) { 249 SkIRect deviceR; 250 deviceR.set(0, 0, width, height); 251 SkASSERT(deviceR.contains(fClip.getBounds())); 252 } 253#endif 254 } 255}; 256 257/* This is the record we keep for each save/restore level in the stack. 258 Since a level optionally copies the matrix and/or stack, we have pointers 259 for these fields. If the value is copied for this level, the copy is 260 stored in the ...Storage field, and the pointer points to that. If the 261 value is not copied for this level, we ignore ...Storage, and just point 262 at the corresponding value in the previous level in the stack. 263*/ 264class SkCanvas::MCRec { 265public: 266 SkDrawFilter* fFilter; // the current filter (or null) 267 DeviceCM* fLayer; 268 /* If there are any layers in the stack, this points to the top-most 269 one that is at or below this level in the stack (so we know what 270 bitmap/device to draw into from this level. This value is NOT 271 reference counted, since the real owner is either our fLayer field, 272 or a previous one in a lower level.) 273 */ 274 DeviceCM* fTopLayer; 275 SkRasterClip fRasterClip; 276 SkMatrix fMatrix; 277 int fDeferredSaveCount; 278 279 // This is the current cumulative depth (aggregate of all done translateZ calls) 280 SkScalar fCurDrawDepth; 281 282 MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { 283 fFilter = nullptr; 284 fLayer = nullptr; 285 fTopLayer = nullptr; 286 fMatrix.reset(); 287 fDeferredSaveCount = 0; 288 fCurDrawDepth = 0; 289 290 // don't bother initializing fNext 291 inc_rec(); 292 } 293 MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix), 294 fCurDrawDepth(prev.fCurDrawDepth) { 295 fFilter = SkSafeRef(prev.fFilter); 296 fLayer = nullptr; 297 fTopLayer = prev.fTopLayer; 298 fDeferredSaveCount = 0; 299 300 // don't bother initializing fNext 301 inc_rec(); 302 } 303 ~MCRec() { 304 SkSafeUnref(fFilter); 305 delete fLayer; 306 dec_rec(); 307 } 308 309 void reset(const SkIRect& bounds) { 310 SkASSERT(fLayer); 311 SkASSERT(fDeferredSaveCount == 0); 312 313 fMatrix.reset(); 314 fRasterClip.setRect(bounds); 315 fLayer->reset(bounds); 316 } 317}; 318 319class SkDrawIter : public SkDraw { 320public: 321 SkDrawIter(SkCanvas* canvas) { 322 canvas = canvas->canvasForDrawIter(); 323 fCanvas = canvas; 324 canvas->updateDeviceCMCache(); 325 326 fClipStack = canvas->fClipStack; 327 fCurrLayer = canvas->fMCRec->fTopLayer; 328 } 329 330 bool next() { 331 // skip over recs with empty clips 332 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 333 fCurrLayer = fCurrLayer->fNext; 334 } 335 336 const DeviceCM* rec = fCurrLayer; 337 if (rec && rec->fDevice) { 338 339 fMatrix = rec->fMatrix; 340 fRC = &rec->fClip; 341 fDevice = rec->fDevice; 342 if (!fDevice->accessPixels(&fDst)) { 343 fDst.reset(fDevice->imageInfo(), nullptr, 0); 344 } 345 fPaint = rec->fPaint; 346 SkDEBUGCODE(this->validate();) 347 348 fCurrLayer = rec->fNext; 349 // fCurrLayer may be nullptr now 350 351 return true; 352 } 353 return false; 354 } 355 356 SkBaseDevice* getDevice() const { return fDevice; } 357 const SkRasterClip& getClip() const { return *fRC; } 358 int getX() const { return fDevice->getOrigin().x(); } 359 int getY() const { return fDevice->getOrigin().y(); } 360 const SkMatrix& getMatrix() const { return *fMatrix; } 361 const SkPaint* getPaint() const { return fPaint; } 362 363private: 364 SkCanvas* fCanvas; 365 const DeviceCM* fCurrLayer; 366 const SkPaint* fPaint; // May be null. 367 368 typedef SkDraw INHERITED; 369}; 370 371///////////////////////////////////////////////////////////////////////////// 372 373static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) { 374 return lazy->isValid() ? lazy->get() : lazy->set(orig); 375} 376 377/** 378 * If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that 379 * colorfilter, else return nullptr. 380 */ 381static sk_sp<SkColorFilter> image_to_color_filter(const SkPaint& paint) { 382 SkImageFilter* imgf = paint.getImageFilter(); 383 if (!imgf) { 384 return nullptr; 385 } 386 387 SkColorFilter* imgCFPtr; 388 if (!imgf->asAColorFilter(&imgCFPtr)) { 389 return nullptr; 390 } 391 sk_sp<SkColorFilter> imgCF(imgCFPtr); 392 393 SkColorFilter* paintCF = paint.getColorFilter(); 394 if (nullptr == paintCF) { 395 // there is no existing paint colorfilter, so we can just return the imagefilter's 396 return imgCF; 397 } 398 399 // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF) 400 // and we need to combine them into a single colorfilter. 401 return SkColorFilter::MakeComposeFilter(std::move(imgCF), sk_ref_sp(paintCF)); 402} 403 404/** 405 * There are many bounds in skia. A circle's bounds is just its center extended by its radius. 406 * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw 407 * outside of its raw-bounds by 1/2 the stroke width. SkPaint has lots of optional 408 * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters, 409 * patheffects, stroking, etc. This function takes a raw bounds and a paint, and returns the 410 * conservative "effective" bounds based on the settings in the paint... with one exception. This 411 * function does *not* look at the imagefilter, which can also modify the effective bounds. It is 412 * deliberately ignored. 413 */ 414static const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint, 415 const SkRect& rawBounds, 416 SkRect* storage) { 417 SkPaint tmpUnfiltered(paint); 418 tmpUnfiltered.setImageFilter(nullptr); 419 if (tmpUnfiltered.canComputeFastBounds()) { 420 return tmpUnfiltered.computeFastBounds(rawBounds, storage); 421 } else { 422 return rawBounds; 423 } 424} 425 426class AutoDrawLooper { 427public: 428 // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the 429 // paint. It's used to determine the size of the offscreen layer for filters. 430 // If null, the clip will be used instead. 431 AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, bool skipLayerForImageFilter = false, 432 const SkRect* rawBounds = nullptr) : fOrigPaint(paint) { 433 fCanvas = canvas; 434#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 435 fFilter = canvas->getDrawFilter(); 436#else 437 fFilter = nullptr; 438#endif 439 fPaint = &fOrigPaint; 440 fSaveCount = canvas->getSaveCount(); 441 fTempLayerForImageFilter = false; 442 fDone = false; 443 444 auto simplifiedCF = image_to_color_filter(fOrigPaint); 445 if (simplifiedCF) { 446 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); 447 paint->setColorFilter(std::move(simplifiedCF)); 448 paint->setImageFilter(nullptr); 449 fPaint = paint; 450 } 451 452 if (!skipLayerForImageFilter && fPaint->getImageFilter()) { 453 /** 454 * We implement ImageFilters for a given draw by creating a layer, then applying the 455 * imagefilter to the pixels of that layer (its backing surface/image), and then 456 * we call restore() to xfer that layer to the main canvas. 457 * 458 * 1. SaveLayer (with a paint containing the current imagefilter and xfermode) 459 * 2. Generate the src pixels: 460 * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper) 461 * return (fPaint). We then draw the primitive (using srcover) into a cleared 462 * buffer/surface. 463 * 3. Restore the layer created in #1 464 * The imagefilter is passed the buffer/surface from the layer (now filled with the 465 * src pixels of the primitive). It returns a new "filtered" buffer, which we 466 * draw onto the previous layer using the xfermode from the original paint. 467 */ 468 SkPaint tmp; 469 tmp.setImageFilter(fPaint->getImageFilter()); 470 tmp.setXfermode(sk_ref_sp(fPaint->getXfermode())); 471 SkRect storage; 472 if (rawBounds) { 473 // Make rawBounds include all paint outsets except for those due to image filters. 474 rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage); 475 } 476 (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp), 477 SkCanvas::kFullLayer_SaveLayerStrategy); 478 fTempLayerForImageFilter = true; 479 // we remove the imagefilter/xfermode inside doNext() 480 } 481 482 if (SkDrawLooper* looper = paint.getLooper()) { 483 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>( 484 looper->contextSize()); 485 fLooperContext = looper->createContext(canvas, buffer); 486 fIsSimple = false; 487 } else { 488 fLooperContext = nullptr; 489 // can we be marked as simple? 490 fIsSimple = !fFilter && !fTempLayerForImageFilter; 491 } 492 } 493 494 ~AutoDrawLooper() { 495 if (fTempLayerForImageFilter) { 496 fCanvas->internalRestore(); 497 } 498 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 499 } 500 501 const SkPaint& paint() const { 502 SkASSERT(fPaint); 503 return *fPaint; 504 } 505 506 bool next(SkDrawFilter::Type drawType) { 507 if (fDone) { 508 return false; 509 } else if (fIsSimple) { 510 fDone = true; 511 return !fPaint->nothingToDraw(); 512 } else { 513 return this->doNext(drawType); 514 } 515 } 516 517private: 518 SkLazyPaint fLazyPaintInit; // base paint storage in case we need to modify it 519 SkLazyPaint fLazyPaintPerLooper; // per-draw-looper storage, so the looper can modify it 520 SkCanvas* fCanvas; 521 const SkPaint& fOrigPaint; 522 SkDrawFilter* fFilter; 523 const SkPaint* fPaint; 524 int fSaveCount; 525 bool fTempLayerForImageFilter; 526 bool fDone; 527 bool fIsSimple; 528 SkDrawLooper::Context* fLooperContext; 529 SkSmallAllocator<1, 32> fLooperContextAllocator; 530 531 bool doNext(SkDrawFilter::Type drawType); 532}; 533 534bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 535 fPaint = nullptr; 536 SkASSERT(!fIsSimple); 537 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter); 538 539 SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ? 540 *fLazyPaintInit.get() : fOrigPaint); 541 542 if (fTempLayerForImageFilter) { 543 paint->setImageFilter(nullptr); 544 paint->setXfermode(nullptr); 545 } 546 547 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 548 fDone = true; 549 return false; 550 } 551 if (fFilter) { 552 if (!fFilter->filter(paint, drawType)) { 553 fDone = true; 554 return false; 555 } 556 if (nullptr == fLooperContext) { 557 // no looper means we only draw once 558 fDone = true; 559 } 560 } 561 fPaint = paint; 562 563 // if we only came in here for the imagefilter, mark us as done 564 if (!fLooperContext && !fFilter) { 565 fDone = true; 566 } 567 568 // call this after any possible paint modifiers 569 if (fPaint->nothingToDraw()) { 570 fPaint = nullptr; 571 return false; 572 } 573 return true; 574} 575 576////////// macros to place around the internal draw calls ////////////////// 577 578#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds) \ 579 this->predrawNotify(); \ 580 AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \ 581 while (looper.next(SkDrawFilter::kBitmap_Type)) { \ 582 SkDrawIter iter(this); 583 584 585#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ 586 this->predrawNotify(); \ 587 AutoDrawLooper looper(this, paint, true); \ 588 while (looper.next(type)) { \ 589 SkDrawIter iter(this); 590 591#define LOOPER_BEGIN(paint, type, bounds) \ 592 this->predrawNotify(); \ 593 AutoDrawLooper looper(this, paint, false, bounds); \ 594 while (looper.next(type)) { \ 595 SkDrawIter iter(this); 596 597#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque) \ 598 this->predrawNotify(bounds, &paint, auxOpaque); \ 599 AutoDrawLooper looper(this, paint, false, bounds); \ 600 while (looper.next(type)) { \ 601 SkDrawIter iter(this); 602 603#define LOOPER_END } 604 605//////////////////////////////////////////////////////////////////////////// 606 607static inline SkRect qr_clip_bounds(const SkIRect& bounds) { 608 if (bounds.isEmpty()) { 609 return SkRect::MakeEmpty(); 610 } 611 612 // Expand bounds out by 1 in case we are anti-aliasing. We store the 613 // bounds as floats to enable a faster quick reject implementation. 614 SkRect dst; 615 SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft); 616 return dst; 617} 618 619void SkCanvas::resetForNextPicture(const SkIRect& bounds) { 620 this->restoreToCount(1); 621 fClipStack->reset(); 622 fMCRec->reset(bounds); 623 624 // We're peering through a lot of structs here. Only at this scope do we 625 // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice). 626 static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size()); 627 fDeviceClipBounds = qr_clip_bounds(bounds); 628 fIsScaleTranslate = true; 629} 630 631SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { 632 if (device && device->forceConservativeRasterClip()) { 633 flags = InitFlags(flags | kConservativeRasterClip_InitFlag); 634 } 635 // Since init() is only called once by our constructors, it is safe to perform this 636 // const-cast. 637 *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag); 638 639 fAllowSoftClip = true; 640 fAllowSimplifyClip = false; 641 fDeviceCMDirty = true; 642 fSaveCount = 1; 643 fMetaData = nullptr; 644#ifdef SK_EXPERIMENTAL_SHADOWING 645 fLights = nullptr; 646#endif 647 648 fClipStack.reset(new SkClipStack); 649 650 fMCRec = (MCRec*)fMCStack.push_back(); 651 new (fMCRec) MCRec(fConservativeRasterClip); 652 fIsScaleTranslate = true; 653 654 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); 655 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; 656 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip, 657 fMCRec->fMatrix); 658 659 fMCRec->fTopLayer = fMCRec->fLayer; 660 661 fSurfaceBase = nullptr; 662 663 if (device) { 664 // The root device and the canvas should always have the same pixel geometry 665 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry()); 666 fMCRec->fLayer->fDevice = SkRef(device); 667 fMCRec->fRasterClip.setRect(device->getGlobalBounds()); 668 fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds()); 669 } 670 671 return device; 672} 673 674SkCanvas::SkCanvas() 675 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 676 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 677 , fConservativeRasterClip(false) 678{ 679 inc_canvas(); 680 681 this->init(nullptr, kDefault_InitFlags); 682} 683 684static SkBitmap make_nopixels(int width, int height) { 685 SkBitmap bitmap; 686 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); 687 return bitmap; 688} 689 690class SkNoPixelsBitmapDevice : public SkBitmapDevice { 691public: 692 SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps) 693 : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps) 694 { 695 this->setOrigin(bounds.x(), bounds.y()); 696 } 697 698private: 699 700 typedef SkBitmapDevice INHERITED; 701}; 702 703SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props) 704 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 705 , fProps(SkSurfacePropsCopyOrDefault(props)) 706 , fConservativeRasterClip(false) 707{ 708 inc_canvas(); 709 710 this->init(new SkNoPixelsBitmapDevice(SkIRect::MakeWH(width, height), fProps), 711 kDefault_InitFlags)->unref(); 712} 713 714SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags) 715 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 716 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 717 , fConservativeRasterClip(false) 718{ 719 inc_canvas(); 720 721 this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags)->unref(); 722} 723 724SkCanvas::SkCanvas(SkBaseDevice* device) 725 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 726 , fProps(device->surfaceProps()) 727 , fConservativeRasterClip(false) 728{ 729 inc_canvas(); 730 731 this->init(device, kDefault_InitFlags); 732} 733 734SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) 735 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 736 , fProps(device->surfaceProps()) 737 , fConservativeRasterClip(false) 738{ 739 inc_canvas(); 740 741 this->init(device, flags); 742} 743 744SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) 745 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 746 , fProps(props) 747 , fConservativeRasterClip(false) 748{ 749 inc_canvas(); 750 751 SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps)); 752 this->init(device, kDefault_InitFlags); 753} 754 755SkCanvas::SkCanvas(const SkBitmap& bitmap) 756 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 757 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 758 , fConservativeRasterClip(false) 759{ 760 inc_canvas(); 761 762 SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps)); 763 this->init(device, kDefault_InitFlags); 764} 765 766SkCanvas::~SkCanvas() { 767 // free up the contents of our deque 768 this->restoreToCount(1); // restore everything but the last 769 770 this->internalRestore(); // restore the last, since we're going away 771 772 delete fMetaData; 773 774 dec_canvas(); 775} 776 777#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 778SkDrawFilter* SkCanvas::getDrawFilter() const { 779 return fMCRec->fFilter; 780} 781 782SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 783 this->checkForDeferredSave(); 784 SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 785 return filter; 786} 787#endif 788 789SkMetaData& SkCanvas::getMetaData() { 790 // metadata users are rare, so we lazily allocate it. If that changes we 791 // can decide to just make it a field in the device (rather than a ptr) 792 if (nullptr == fMetaData) { 793 fMetaData = new SkMetaData; 794 } 795 return *fMetaData; 796} 797 798/////////////////////////////////////////////////////////////////////////////// 799 800void SkCanvas::flush() { 801 this->onFlush(); 802} 803 804void SkCanvas::onFlush() { 805 SkBaseDevice* device = this->getDevice(); 806 if (device) { 807 device->flush(); 808 } 809} 810 811SkISize SkCanvas::getBaseLayerSize() const { 812 SkBaseDevice* d = this->getDevice(); 813 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 814} 815 816SkIRect SkCanvas::getTopLayerBounds() const { 817 SkBaseDevice* d = this->getTopDevice(); 818 if (!d) { 819 return SkIRect::MakeEmpty(); 820 } 821 return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height()); 822} 823 824SkBaseDevice* SkCanvas::getDevice() const { 825 // return root device 826 MCRec* rec = (MCRec*) fMCStack.front(); 827 SkASSERT(rec && rec->fLayer); 828 return rec->fLayer->fDevice; 829} 830 831SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 832 if (updateMatrixClip) { 833 const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 834 } 835 return fMCRec->fTopLayer->fDevice; 836} 837 838bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) { 839 if (kUnknown_SkColorType == bitmap->colorType()) { 840 return false; 841 } 842 843 bool weAllocated = false; 844 if (nullptr == bitmap->pixelRef()) { 845 if (!bitmap->tryAllocPixels()) { 846 return false; 847 } 848 weAllocated = true; 849 } 850 851 SkAutoPixmapUnlock unlocker; 852 if (bitmap->requestLock(&unlocker)) { 853 const SkPixmap& pm = unlocker.pixmap(); 854 if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) { 855 return true; 856 } 857 } 858 859 if (weAllocated) { 860 bitmap->setPixelRef(nullptr); 861 } 862 return false; 863} 864 865bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 866 SkIRect r = srcRect; 867 const SkISize size = this->getBaseLayerSize(); 868 if (!r.intersect(0, 0, size.width(), size.height())) { 869 bitmap->reset(); 870 return false; 871 } 872 873 if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) { 874 // bitmap will already be reset. 875 return false; 876 } 877 if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) { 878 bitmap->reset(); 879 return false; 880 } 881 return true; 882} 883 884bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) { 885 SkBaseDevice* device = this->getDevice(); 886 if (!device) { 887 return false; 888 } 889 const SkISize size = this->getBaseLayerSize(); 890 891 SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y); 892 if (!rec.trim(size.width(), size.height())) { 893 return false; 894 } 895 896 // The device can assert that the requested area is always contained in its bounds 897 return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY); 898} 899 900bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 901 SkAutoPixmapUnlock unlocker; 902 if (bitmap.requestLock(&unlocker)) { 903 const SkPixmap& pm = unlocker.pixmap(); 904 return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y); 905 } 906 return false; 907} 908 909bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes, 910 int x, int y) { 911 switch (origInfo.colorType()) { 912 case kUnknown_SkColorType: 913 case kIndex_8_SkColorType: 914 return false; 915 default: 916 break; 917 } 918 if (nullptr == pixels || rowBytes < origInfo.minRowBytes()) { 919 return false; 920 } 921 922 const SkISize size = this->getBaseLayerSize(); 923 SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height()); 924 if (!target.intersect(0, 0, size.width(), size.height())) { 925 return false; 926 } 927 928 SkBaseDevice* device = this->getDevice(); 929 if (!device) { 930 return false; 931 } 932 933 // the intersect may have shrunk info's logical size 934 const SkImageInfo info = origInfo.makeWH(target.width(), target.height()); 935 936 // if x or y are negative, then we have to adjust pixels 937 if (x > 0) { 938 x = 0; 939 } 940 if (y > 0) { 941 y = 0; 942 } 943 // here x,y are either 0 or negative 944 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel()); 945 946 // Tell our owning surface to bump its generation ID 947 const bool completeOverwrite = info.dimensions() == size; 948 this->predrawNotify(completeOverwrite); 949 950 // The device can assert that the requested area is always contained in its bounds 951 return device->writePixels(info, pixels, rowBytes, target.x(), target.y()); 952} 953 954SkCanvas* SkCanvas::canvasForDrawIter() { 955 return this; 956} 957 958////////////////////////////////////////////////////////////////////////////// 959 960void SkCanvas::updateDeviceCMCache() { 961 if (fDeviceCMDirty) { 962 const SkMatrix& totalMatrix = this->getTotalMatrix(); 963 const SkRasterClip& totalClip = fMCRec->fRasterClip; 964 DeviceCM* layer = fMCRec->fTopLayer; 965 966 if (nullptr == layer->fNext) { // only one layer 967 layer->updateMC(totalMatrix, totalClip, *fClipStack, nullptr); 968 } else { 969 SkRasterClip clip(totalClip); 970 do { 971 layer->updateMC(totalMatrix, clip, *fClipStack, &clip); 972 } while ((layer = layer->fNext) != nullptr); 973 } 974 fDeviceCMDirty = false; 975 } 976} 977 978/////////////////////////////////////////////////////////////////////////////// 979 980void SkCanvas::checkForDeferredSave() { 981 if (fMCRec->fDeferredSaveCount > 0) { 982 this->doSave(); 983 } 984} 985 986int SkCanvas::getSaveCount() const { 987#ifdef SK_DEBUG 988 int count = 0; 989 SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart); 990 for (;;) { 991 const MCRec* rec = (const MCRec*)iter.next(); 992 if (!rec) { 993 break; 994 } 995 count += 1 + rec->fDeferredSaveCount; 996 } 997 SkASSERT(count == fSaveCount); 998#endif 999 return fSaveCount; 1000} 1001 1002int SkCanvas::save() { 1003 fSaveCount += 1; 1004 fMCRec->fDeferredSaveCount += 1; 1005 return this->getSaveCount() - 1; // return our prev value 1006} 1007 1008void SkCanvas::doSave() { 1009 this->willSave(); 1010 1011 SkASSERT(fMCRec->fDeferredSaveCount > 0); 1012 fMCRec->fDeferredSaveCount -= 1; 1013 this->internalSave(); 1014} 1015 1016void SkCanvas::restore() { 1017 if (fMCRec->fDeferredSaveCount > 0) { 1018 SkASSERT(fSaveCount > 1); 1019 fSaveCount -= 1; 1020 fMCRec->fDeferredSaveCount -= 1; 1021 } else { 1022 // check for underflow 1023 if (fMCStack.count() > 1) { 1024 this->willRestore(); 1025 SkASSERT(fSaveCount > 1); 1026 fSaveCount -= 1; 1027 this->internalRestore(); 1028 this->didRestore(); 1029 } 1030 } 1031} 1032 1033void SkCanvas::restoreToCount(int count) { 1034 // sanity check 1035 if (count < 1) { 1036 count = 1; 1037 } 1038 1039 int n = this->getSaveCount() - count; 1040 for (int i = 0; i < n; ++i) { 1041 this->restore(); 1042 } 1043} 1044 1045void SkCanvas::internalSave() { 1046 MCRec* newTop = (MCRec*)fMCStack.push_back(); 1047 new (newTop) MCRec(*fMCRec); // balanced in restore() 1048 fMCRec = newTop; 1049 1050 fClipStack->save(); 1051} 1052 1053bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) { 1054#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 1055 return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag); 1056#else 1057 return true; 1058#endif 1059} 1060 1061bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags, 1062 SkIRect* intersection, const SkImageFilter* imageFilter) { 1063 SkIRect clipBounds; 1064 if (!this->getClipDeviceBounds(&clipBounds)) { 1065 return false; 1066 } 1067 1068 const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix() 1069 1070 if (imageFilter) { 1071 clipBounds = imageFilter->filterBounds(clipBounds, ctm); 1072 if (bounds && !imageFilter->canComputeFastBounds()) { 1073 bounds = nullptr; 1074 } 1075 } 1076 SkIRect ir; 1077 if (bounds) { 1078 SkRect r; 1079 1080 ctm.mapRect(&r, *bounds); 1081 r.roundOut(&ir); 1082 // early exit if the layer's bounds are clipped out 1083 if (!ir.intersect(clipBounds)) { 1084 if (BoundsAffectsClip(saveLayerFlags)) { 1085 fMCRec->fRasterClip.setEmpty(); 1086 fDeviceClipBounds.setEmpty(); 1087 } 1088 return false; 1089 } 1090 } else { // no user bounds, so just use the clip 1091 ir = clipBounds; 1092 } 1093 SkASSERT(!ir.isEmpty()); 1094 1095 if (BoundsAffectsClip(saveLayerFlags)) { 1096 // Simplify the current clips since they will be applied properly during restore() 1097 fClipStack->clipDevRect(ir, SkRegion::kReplace_Op); 1098 fMCRec->fRasterClip.setRect(ir); 1099 fDeviceClipBounds = qr_clip_bounds(ir); 1100 } 1101 1102 if (intersection) { 1103 *intersection = ir; 1104 } 1105 return true; 1106} 1107 1108 1109int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) { 1110 return this->saveLayer(SaveLayerRec(bounds, paint, 0)); 1111} 1112 1113int SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) { 1114 return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag)); 1115} 1116 1117int SkCanvas::saveLayer(const SaveLayerRec& origRec) { 1118 SaveLayerRec rec(origRec); 1119 if (gIgnoreSaveLayerBounds) { 1120 rec.fBounds = nullptr; 1121 } 1122 SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec); 1123 fSaveCount += 1; 1124 this->internalSaveLayer(rec, strategy); 1125 return this->getSaveCount() - 1; 1126} 1127 1128void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter, 1129 SkBaseDevice* dst, const SkMatrix& ctm, 1130 const SkClipStack* clipStack) { 1131 SkDraw draw; 1132 SkRasterClip rc; 1133 rc.setRect(SkIRect::MakeWH(dst->width(), dst->height())); 1134 if (!dst->accessPixels(&draw.fDst)) { 1135 draw.fDst.reset(dst->imageInfo(), nullptr, 0); 1136 } 1137 draw.fMatrix = &SkMatrix::I(); 1138 draw.fRC = &rc; 1139 draw.fClipStack = clipStack; 1140 draw.fDevice = dst; 1141 1142 SkPaint p; 1143 p.setImageFilter(filter->makeWithLocalMatrix(ctm)); 1144 1145 int x = src->getOrigin().x() - dst->getOrigin().x(); 1146 int y = src->getOrigin().y() - dst->getOrigin().y(); 1147 auto special = src->snapSpecial(); 1148 if (special) { 1149 dst->drawSpecial(draw, special.get(), x, y, p); 1150 } 1151} 1152 1153static SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque, 1154 const SkPaint* paint) { 1155 // need to force L32 for now if we have an image filter. Once filters support other colortypes 1156 // e.g. sRGB or F16, we can remove this check 1157 // SRGBTODO: Can we remove this check now? 1158 const bool hasImageFilter = paint && paint->getImageFilter(); 1159 1160 SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 1161 if ((prev.bytesPerPixel() < 4) || hasImageFilter) { 1162 // force to L32 1163 return SkImageInfo::MakeN32(w, h, alphaType); 1164 } else { 1165 // keep the same characteristics as the prev 1166 return SkImageInfo::Make(w, h, prev.colorType(), alphaType, sk_ref_sp(prev.colorSpace())); 1167 } 1168} 1169 1170void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) { 1171 const SkRect* bounds = rec.fBounds; 1172 const SkPaint* paint = rec.fPaint; 1173 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags; 1174 1175#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 1176 saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag; 1177#endif 1178 1179 SkLazyPaint lazyP; 1180 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL; 1181 SkMatrix stashedMatrix = fMCRec->fMatrix; 1182 SkMatrix remainder; 1183 SkSize scale; 1184 /* 1185 * ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc. 1186 * but they do handle scaling. To accommodate this, we do the following: 1187 * 1188 * 1. Stash off the current CTM 1189 * 2. Decompose the CTM into SCALE and REMAINDER 1190 * 3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that 1191 * contains the REMAINDER 1192 * 4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM) 1193 * 5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output 1194 * of the original imagefilter, and draw that (via drawSprite) 1195 * 6. Unwack the CTM to its original state (i.e. stashedMatrix) 1196 * 1197 * Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer 1198 * a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter. 1199 */ 1200 if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() && 1201 stashedMatrix.decomposeScale(&scale, &remainder)) 1202 { 1203 // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix 1204 this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height())); 1205 SkPaint* p = lazyP.set(*paint); 1206 p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder, 1207 SkFilterQuality::kLow_SkFilterQuality, 1208 sk_ref_sp(imageFilter))); 1209 imageFilter = p->getImageFilter(); 1210 paint = p; 1211 } 1212 1213 // do this before we create the layer. We don't call the public save() since 1214 // that would invoke a possibly overridden virtual 1215 this->internalSave(); 1216 1217 fDeviceCMDirty = true; 1218 1219 SkIRect ir; 1220 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) { 1221 return; 1222 } 1223 1224 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 1225 // the clipRectBounds() call above? 1226 if (kNoLayer_SaveLayerStrategy == strategy) { 1227 return; 1228 } 1229 1230 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag); 1231 SkPixelGeometry geo = fProps.pixelGeometry(); 1232 if (paint) { 1233 // TODO: perhaps add a query to filters so we might preserve opaqueness... 1234 if (paint->getImageFilter() || paint->getColorFilter()) { 1235 isOpaque = false; 1236 geo = kUnknown_SkPixelGeometry; 1237 } 1238 } 1239 1240 SkBaseDevice* priorDevice = this->getTopDevice(); 1241 if (nullptr == priorDevice) { 1242 SkDebugf("Unable to find device for layer."); 1243 return; 1244 } 1245 1246 SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque, 1247 paint); 1248 1249 SkAutoTUnref<SkBaseDevice> newDevice; 1250 { 1251 const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() || 1252 (saveLayerFlags & kPreserveLCDText_SaveLayerFlag); 1253 const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; 1254 const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo, 1255 preserveLCDText); 1256 newDevice.reset(priorDevice->onCreateDevice(createInfo, paint)); 1257 if (!newDevice) { 1258 SkErrorInternals::SetError(kInternalError_SkError, 1259 "Unable to create device for layer."); 1260 return; 1261 } 1262 } 1263 newDevice->setOrigin(ir.fLeft, ir.fTop); 1264 1265 DeviceCM* layer = new DeviceCM(newDevice, paint, this, fConservativeRasterClip, stashedMatrix); 1266 1267 layer->fNext = fMCRec->fTopLayer; 1268 fMCRec->fLayer = layer; 1269 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 1270 1271 if (rec.fBackdrop) { 1272 DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice, 1273 fMCRec->fMatrix, this->getClipStack()); 1274 } 1275} 1276 1277int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 1278 if (0xFF == alpha) { 1279 return this->saveLayer(bounds, nullptr); 1280 } else { 1281 SkPaint tmpPaint; 1282 tmpPaint.setAlpha(alpha); 1283 return this->saveLayer(bounds, &tmpPaint); 1284 } 1285} 1286 1287void SkCanvas::internalRestore() { 1288 SkASSERT(fMCStack.count() != 0); 1289 1290 fDeviceCMDirty = true; 1291 1292 fClipStack->restore(); 1293 1294 // reserve our layer (if any) 1295 DeviceCM* layer = fMCRec->fLayer; // may be null 1296 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 1297 fMCRec->fLayer = nullptr; 1298 1299 // now do the normal restore() 1300 fMCRec->~MCRec(); // balanced in save() 1301 fMCStack.pop_back(); 1302 fMCRec = (MCRec*)fMCStack.back(); 1303 1304 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1305 since if we're being recorded, we don't want to record this (the 1306 recorder will have already recorded the restore). 1307 */ 1308 if (layer) { 1309 if (layer->fNext) { 1310 const SkIPoint& origin = layer->fDevice->getOrigin(); 1311 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), layer->fPaint); 1312 // restore what we smashed in internalSaveLayer 1313 fMCRec->fMatrix = layer->fStashedMatrix; 1314 // reset this, since internalDrawDevice will have set it to true 1315 fDeviceCMDirty = true; 1316 delete layer; 1317 } else { 1318 // we're at the root 1319 SkASSERT(layer == (void*)fDeviceCMStorage); 1320 layer->~DeviceCM(); 1321 // no need to update fMCRec, 'cause we're killing the canvas 1322 } 1323 } 1324 1325 if (fMCRec) { 1326 fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate(); 1327 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1328 } 1329} 1330 1331sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 1332 if (nullptr == props) { 1333 props = &fProps; 1334 } 1335 return this->onNewSurface(info, *props); 1336} 1337 1338sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1339 SkBaseDevice* dev = this->getDevice(); 1340 return dev ? dev->makeSurface(info, props) : nullptr; 1341} 1342 1343SkImageInfo SkCanvas::imageInfo() const { 1344 return this->onImageInfo(); 1345} 1346 1347SkImageInfo SkCanvas::onImageInfo() const { 1348 SkBaseDevice* dev = this->getDevice(); 1349 if (dev) { 1350 return dev->imageInfo(); 1351 } else { 1352 return SkImageInfo::MakeUnknown(0, 0); 1353 } 1354} 1355 1356bool SkCanvas::getProps(SkSurfaceProps* props) const { 1357 return this->onGetProps(props); 1358} 1359 1360bool SkCanvas::onGetProps(SkSurfaceProps* props) const { 1361 SkBaseDevice* dev = this->getDevice(); 1362 if (dev) { 1363 if (props) { 1364 *props = fProps; 1365 } 1366 return true; 1367 } else { 1368 return false; 1369 } 1370} 1371 1372#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS 1373const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1374 SkPixmap pmap; 1375 if (this->peekPixels(&pmap)) { 1376 if (info) { 1377 *info = pmap.info(); 1378 } 1379 if (rowBytes) { 1380 *rowBytes = pmap.rowBytes(); 1381 } 1382 return pmap.addr(); 1383 } 1384 return nullptr; 1385} 1386#endif 1387 1388bool SkCanvas::peekPixels(SkPixmap* pmap) { 1389 return this->onPeekPixels(pmap); 1390} 1391 1392bool SkCanvas::onPeekPixels(SkPixmap* pmap) { 1393 SkBaseDevice* dev = this->getDevice(); 1394 return dev && dev->peekPixels(pmap); 1395} 1396 1397void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { 1398 SkPixmap pmap; 1399 if (!this->onAccessTopLayerPixels(&pmap)) { 1400 return nullptr; 1401 } 1402 if (info) { 1403 *info = pmap.info(); 1404 } 1405 if (rowBytes) { 1406 *rowBytes = pmap.rowBytes(); 1407 } 1408 if (origin) { 1409 *origin = this->getTopDevice(false)->getOrigin(); 1410 } 1411 return pmap.writable_addr(); 1412} 1413 1414bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) { 1415 SkBaseDevice* dev = this->getTopDevice(); 1416 return dev && dev->accessPixels(pmap); 1417} 1418 1419///////////////////////////////////////////////////////////////////////////// 1420 1421void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) { 1422 SkPaint tmp; 1423 if (nullptr == paint) { 1424 paint = &tmp; 1425 } 1426 1427 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1428 1429 while (iter.next()) { 1430 SkBaseDevice* dstDev = iter.fDevice; 1431 paint = &looper.paint(); 1432 SkImageFilter* filter = paint->getImageFilter(); 1433 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1434 if (filter) { 1435 dstDev->drawSpecial(iter, srcDev->snapSpecial().get(), pos.x(), pos.y(), *paint); 1436 } else { 1437 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1438 } 1439 } 1440 1441 LOOPER_END 1442} 1443 1444///////////////////////////////////////////////////////////////////////////// 1445 1446void SkCanvas::translate(SkScalar dx, SkScalar dy) { 1447 SkMatrix m; 1448 m.setTranslate(dx, dy); 1449 this->concat(m); 1450} 1451 1452void SkCanvas::scale(SkScalar sx, SkScalar sy) { 1453 SkMatrix m; 1454 m.setScale(sx, sy); 1455 this->concat(m); 1456} 1457 1458void SkCanvas::rotate(SkScalar degrees) { 1459 SkMatrix m; 1460 m.setRotate(degrees); 1461 this->concat(m); 1462} 1463 1464void SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) { 1465 SkMatrix m; 1466 m.setRotate(degrees, px, py); 1467 this->concat(m); 1468} 1469 1470void SkCanvas::skew(SkScalar sx, SkScalar sy) { 1471 SkMatrix m; 1472 m.setSkew(sx, sy); 1473 this->concat(m); 1474} 1475 1476void SkCanvas::concat(const SkMatrix& matrix) { 1477 if (matrix.isIdentity()) { 1478 return; 1479 } 1480 1481 this->checkForDeferredSave(); 1482 fDeviceCMDirty = true; 1483 fMCRec->fMatrix.preConcat(matrix); 1484 fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate(); 1485 this->didConcat(matrix); 1486} 1487 1488void SkCanvas::internalSetMatrix(const SkMatrix& matrix) { 1489 fDeviceCMDirty = true; 1490 fMCRec->fMatrix = matrix; 1491} 1492 1493void SkCanvas::setMatrix(const SkMatrix& matrix) { 1494 this->checkForDeferredSave(); 1495 this->internalSetMatrix(matrix); 1496 fIsScaleTranslate = matrix.isScaleTranslate(); 1497 this->didSetMatrix(matrix); 1498} 1499 1500void SkCanvas::resetMatrix() { 1501 this->setMatrix(SkMatrix::I()); 1502} 1503 1504#ifdef SK_EXPERIMENTAL_SHADOWING 1505void SkCanvas::translateZ(SkScalar z) { 1506 this->checkForDeferredSave(); 1507 this->fMCRec->fCurDrawDepth += z; 1508 this->didTranslateZ(z); 1509} 1510 1511SkScalar SkCanvas::getZ() const { 1512 return this->fMCRec->fCurDrawDepth; 1513} 1514 1515void SkCanvas::setLights(sk_sp<SkLights> lights) { 1516 this->fLights = lights; 1517} 1518 1519sk_sp<SkLights> SkCanvas::getLights() const { 1520 return this->fLights; 1521} 1522#endif 1523 1524////////////////////////////////////////////////////////////////////////////// 1525 1526void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1527 if (!fAllowSoftClip) { 1528 doAA = false; 1529 } 1530 1531#ifdef SK_SUPPORT_PRECHECK_CLIPRECT 1532 // Check if we can quick-accept the clip call (and do nothing) 1533 // 1534 if (SkRegion::kIntersect_Op == op && !doAA && fMCRec->fMatrix.isScaleTranslate()) { 1535 SkRect devR; 1536 fMCRec->fMatrix.mapRectScaleTranslate(&devR, rect); 1537 // NOTE: this check is CTM specific, since we might round differently with a different 1538 // CTM. Thus this is only 100% reliable if there is not global CTM scale to be 1539 // applied later (i.e. if this is going into a picture). 1540 if (devR.round().contains(fMCRec->fRasterClip.getBounds())) { 1541#if 0 1542 SkDebugf("ignored clipRect [%g %g %g %g]\n", 1543 rect.left(), rect.top(), rect.right(), rect.bottom()); 1544#endif 1545 return; 1546 } 1547 } 1548#endif 1549 1550 this->checkForDeferredSave(); 1551 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1552 this->onClipRect(rect, op, edgeStyle); 1553} 1554 1555void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1556#ifdef SK_ENABLE_CLIP_QUICKREJECT 1557 if (SkRegion::kIntersect_Op == op) { 1558 if (fMCRec->fRasterClip.isEmpty()) { 1559 return; 1560 } 1561 1562 if (this->quickReject(rect)) { 1563 fDeviceCMDirty = true; 1564 fCachedLocalClipBoundsDirty = true; 1565 1566 fClipStack->clipEmpty(); 1567 (void)fMCRec->fRasterClip.setEmpty(); 1568 fDeviceClipBounds.setEmpty(); 1569 return; 1570 } 1571 } 1572#endif 1573 1574 const bool isScaleTrans = fMCRec->fMatrix.isScaleTranslate(); 1575 SkRect devR; 1576 if (isScaleTrans) { 1577 fMCRec->fMatrix.mapRectScaleTranslate(&devR, rect); 1578 } 1579 1580#ifndef SK_SUPPORT_PRECHECK_CLIPRECT 1581 if (SkRegion::kIntersect_Op == op && 1582 kHard_ClipEdgeStyle == edgeStyle 1583 && isScaleTrans) 1584 { 1585 if (devR.round().contains(fMCRec->fRasterClip.getBounds())) { 1586#if 0 1587 SkDebugf("------- ignored clipRect [%g %g %g %g]\n", 1588 rect.left(), rect.top(), rect.right(), rect.bottom()); 1589#endif 1590 return; 1591 } 1592 } 1593#endif 1594 1595 AutoValidateClip avc(this); 1596 1597 fDeviceCMDirty = true; 1598 1599 if (isScaleTrans) { 1600 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle; 1601 fClipStack->clipDevRect(devR, op, isAA); 1602 fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA); 1603 } else { 1604 // since we're rotated or some such thing, we convert the rect to a path 1605 // and clip against that, since it can handle any matrix. However, to 1606 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1607 // we explicitly call "our" version of clipPath. 1608 SkPath path; 1609 1610 path.addRect(rect); 1611 this->SkCanvas::onClipPath(path, op, edgeStyle); 1612 } 1613 1614 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1615} 1616 1617void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1618 this->checkForDeferredSave(); 1619 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1620 if (rrect.isRect()) { 1621 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1622 } else { 1623 this->onClipRRect(rrect, op, edgeStyle); 1624 } 1625} 1626 1627void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1628 SkRRect transformedRRect; 1629 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1630 AutoValidateClip avc(this); 1631 1632 fDeviceCMDirty = true; 1633 if (!fAllowSoftClip) { 1634 edgeStyle = kHard_ClipEdgeStyle; 1635 } 1636 1637 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1638 1639 fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op, 1640 kSoft_ClipEdgeStyle == edgeStyle); 1641 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1642 return; 1643 } 1644 1645 SkPath path; 1646 path.addRRect(rrect); 1647 // call the non-virtual version 1648 this->SkCanvas::onClipPath(path, op, edgeStyle); 1649} 1650 1651void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1652 this->checkForDeferredSave(); 1653 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1654 1655 if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) { 1656 SkRect r; 1657 if (path.isRect(&r)) { 1658 this->onClipRect(r, op, edgeStyle); 1659 return; 1660 } 1661 SkRRect rrect; 1662 if (path.isOval(&r)) { 1663 rrect.setOval(r); 1664 this->onClipRRect(rrect, op, edgeStyle); 1665 return; 1666 } 1667 if (path.isRRect(&rrect)) { 1668 this->onClipRRect(rrect, op, edgeStyle); 1669 return; 1670 } 1671 } 1672 1673 this->onClipPath(path, op, edgeStyle); 1674} 1675 1676void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1677#ifdef SK_ENABLE_CLIP_QUICKREJECT 1678 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1679 if (fMCRec->fRasterClip.isEmpty()) { 1680 return; 1681 } 1682 1683 if (this->quickReject(path.getBounds())) { 1684 fDeviceCMDirty = true; 1685 fCachedLocalClipBoundsDirty = true; 1686 1687 fClipStack->clipEmpty(); 1688 (void)fMCRec->fRasterClip.setEmpty(); 1689 fDeviceClipBounds.setEmpty(); 1690 return; 1691 } 1692 } 1693#endif 1694 1695 AutoValidateClip avc(this); 1696 1697 fDeviceCMDirty = true; 1698 if (!fAllowSoftClip) { 1699 edgeStyle = kHard_ClipEdgeStyle; 1700 } 1701 1702 SkPath devPath; 1703 path.transform(fMCRec->fMatrix, &devPath); 1704 1705 // Check if the transfomation, or the original path itself 1706 // made us empty. Note this can also happen if we contained NaN 1707 // values. computing the bounds detects this, and will set our 1708 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1709 if (devPath.getBounds().isEmpty()) { 1710 // resetting the path will remove any NaN or other wanky values 1711 // that might upset our scan converter. 1712 devPath.reset(); 1713 } 1714 1715 // if we called path.swap() we could avoid a deep copy of this path 1716 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1717 1718 if (fAllowSimplifyClip) { 1719 bool clipIsAA = getClipStack()->asPath(&devPath); 1720 if (clipIsAA) { 1721 edgeStyle = kSoft_ClipEdgeStyle; 1722 } 1723 1724 op = SkRegion::kReplace_Op; 1725 } 1726 1727 fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle); 1728 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1729} 1730 1731void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1732 this->checkForDeferredSave(); 1733 this->onClipRegion(rgn, op); 1734} 1735 1736void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1737 AutoValidateClip avc(this); 1738 1739 fDeviceCMDirty = true; 1740 1741 // todo: signal fClipStack that we have a region, and therefore (I guess) 1742 // we have to ignore it, and use the region directly? 1743 fClipStack->clipDevRect(rgn.getBounds(), op); 1744 1745 fMCRec->fRasterClip.op(rgn, op); 1746 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1747} 1748 1749#ifdef SK_DEBUG 1750void SkCanvas::validateClip() const { 1751 // construct clipRgn from the clipstack 1752 const SkBaseDevice* device = this->getDevice(); 1753 if (!device) { 1754 SkASSERT(this->isClipEmpty()); 1755 return; 1756 } 1757 1758 SkIRect ir; 1759 ir.set(0, 0, device->width(), device->height()); 1760 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1761 1762 SkClipStack::B2TIter iter(*fClipStack); 1763 const SkClipStack::Element* element; 1764 while ((element = iter.next()) != nullptr) { 1765 switch (element->getType()) { 1766 case SkClipStack::Element::kRect_Type: 1767 element->getRect().round(&ir); 1768 tmpClip.op(ir, element->getOp()); 1769 break; 1770 case SkClipStack::Element::kEmpty_Type: 1771 tmpClip.setEmpty(); 1772 break; 1773 default: { 1774 SkPath path; 1775 element->asPath(&path); 1776 tmpClip.op(path, this->getTopLayerBounds(), element->getOp(), element->isAA()); 1777 break; 1778 } 1779 } 1780 } 1781} 1782#endif 1783 1784void SkCanvas::replayClips(ClipVisitor* visitor) const { 1785 SkClipStack::B2TIter iter(*fClipStack); 1786 const SkClipStack::Element* element; 1787 1788 while ((element = iter.next()) != nullptr) { 1789 element->replay(visitor); 1790 } 1791} 1792 1793/////////////////////////////////////////////////////////////////////////////// 1794 1795bool SkCanvas::isClipEmpty() const { 1796 return fMCRec->fRasterClip.isEmpty(); 1797} 1798 1799bool SkCanvas::isClipRect() const { 1800 return fMCRec->fRasterClip.isRect(); 1801} 1802 1803static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) { 1804#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 1805 __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec); 1806 __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec); 1807 __m128 mask = _mm_cmplt_ps(lLtT, RrBb); 1808 return 0xF != _mm_movemask_ps(mask); 1809#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON) 1810 float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0]; 1811 float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1]; 1812 uint32x4_t mask = vcltq_f32(lLtT, RrBb); 1813 return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask); 1814#else 1815 SkRect devRectAsRect; 1816 SkRect devClipAsRect; 1817 devRect.store(&devRectAsRect.fLeft); 1818 devClip.store(&devClipAsRect.fLeft); 1819 return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect); 1820#endif 1821} 1822 1823// It's important for this function to not be inlined. Otherwise the compiler will share code 1824// between the fast path and the slow path, resulting in two slow paths. 1825static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip, 1826 const SkMatrix& matrix) { 1827 SkRect deviceRect; 1828 matrix.mapRect(&deviceRect, src); 1829 return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip); 1830} 1831 1832bool SkCanvas::quickReject(const SkRect& src) const { 1833#ifdef SK_DEBUG 1834 // Verify that fDeviceClipBounds are set properly. 1835 SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1836 if (fMCRec->fRasterClip.isEmpty()) { 1837 SkASSERT(fDeviceClipBounds.isEmpty()); 1838 } else { 1839 SkASSERT(tmp == fDeviceClipBounds); 1840 } 1841 1842 // Verify that fIsScaleTranslate is set properly. 1843 SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate()); 1844#endif 1845 1846 if (!fIsScaleTranslate) { 1847 return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix); 1848 } 1849 1850 // We inline the implementation of mapScaleTranslate() for the fast path. 1851 float sx = fMCRec->fMatrix.getScaleX(); 1852 float sy = fMCRec->fMatrix.getScaleY(); 1853 float tx = fMCRec->fMatrix.getTranslateX(); 1854 float ty = fMCRec->fMatrix.getTranslateY(); 1855 Sk4f scale(sx, sy, sx, sy); 1856 Sk4f trans(tx, ty, tx, ty); 1857 1858 // Apply matrix. 1859 Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans; 1860 1861 // Make sure left < right, top < bottom. 1862 Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]); 1863 Sk4f min = Sk4f::Min(ltrb, rblt); 1864 Sk4f max = Sk4f::Max(ltrb, rblt); 1865 // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on 1866 // ARM this sequence generates the fastest (a single instruction). 1867 Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]); 1868 1869 // Check if the device rect is NaN or outside the clip. 1870 return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft)); 1871} 1872 1873bool SkCanvas::quickReject(const SkPath& path) const { 1874 return path.isEmpty() || this->quickReject(path.getBounds()); 1875} 1876 1877bool SkCanvas::getClipBounds(SkRect* bounds) const { 1878 SkIRect ibounds; 1879 if (!this->getClipDeviceBounds(&ibounds)) { 1880 return false; 1881 } 1882 1883 SkMatrix inverse; 1884 // if we can't invert the CTM, we can't return local clip bounds 1885 if (!fMCRec->fMatrix.invert(&inverse)) { 1886 if (bounds) { 1887 bounds->setEmpty(); 1888 } 1889 return false; 1890 } 1891 1892 if (bounds) { 1893 SkRect r; 1894 // adjust it outwards in case we are antialiasing 1895 const int inset = 1; 1896 1897 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1898 ibounds.fRight + inset, ibounds.fBottom + inset); 1899 inverse.mapRect(bounds, r); 1900 } 1901 return true; 1902} 1903 1904bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1905 const SkRasterClip& clip = fMCRec->fRasterClip; 1906 if (clip.isEmpty()) { 1907 if (bounds) { 1908 bounds->setEmpty(); 1909 } 1910 return false; 1911 } 1912 1913 if (bounds) { 1914 *bounds = clip.getBounds(); 1915 } 1916 return true; 1917} 1918 1919const SkMatrix& SkCanvas::getTotalMatrix() const { 1920 return fMCRec->fMatrix; 1921} 1922 1923const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1924 return fMCRec->fRasterClip.forceGetBW(); 1925} 1926 1927GrDrawContext* SkCanvas::internal_private_accessTopLayerDrawContext() { 1928 SkBaseDevice* dev = this->getTopDevice(); 1929 return dev ? dev->accessDrawContext() : nullptr; 1930} 1931 1932GrContext* SkCanvas::getGrContext() { 1933 SkBaseDevice* device = this->getTopDevice(); 1934 return device ? device->context() : nullptr; 1935} 1936 1937void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1938 const SkPaint& paint) { 1939 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()"); 1940 if (outer.isEmpty()) { 1941 return; 1942 } 1943 if (inner.isEmpty()) { 1944 this->drawRRect(outer, paint); 1945 return; 1946 } 1947 1948 // We don't have this method (yet), but technically this is what we should 1949 // be able to assert... 1950 // SkASSERT(outer.contains(inner)); 1951 // 1952 // For now at least check for containment of bounds 1953 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1954 1955 this->onDrawDRRect(outer, inner, paint); 1956} 1957 1958// These need to stop being virtual -- clients need to override the onDraw... versions 1959 1960void SkCanvas::drawPaint(const SkPaint& paint) { 1961 this->onDrawPaint(paint); 1962} 1963 1964void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1965 this->onDrawRect(r, paint); 1966} 1967 1968void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) { 1969 this->onDrawOval(r, paint); 1970} 1971 1972void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1973 this->onDrawRRect(rrect, paint); 1974} 1975 1976void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { 1977 this->onDrawPoints(mode, count, pts, paint); 1978} 1979 1980void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], 1981 const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, 1982 const uint16_t indices[], int indexCount, const SkPaint& paint) { 1983 this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 1984 indices, indexCount, paint); 1985} 1986 1987void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1988 this->onDrawPath(path, paint); 1989} 1990 1991void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1992 RETURN_ON_NULL(image); 1993 this->onDrawImage(image, x, y, paint); 1994} 1995 1996void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, 1997 const SkPaint* paint, SrcRectConstraint constraint) { 1998 RETURN_ON_NULL(image); 1999 if (dst.isEmpty() || src.isEmpty()) { 2000 return; 2001 } 2002 this->onDrawImageRect(image, &src, dst, paint, constraint); 2003} 2004 2005void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst, 2006 const SkPaint* paint, SrcRectConstraint constraint) { 2007 RETURN_ON_NULL(image); 2008 this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint); 2009} 2010 2011void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint, 2012 SrcRectConstraint constraint) { 2013 RETURN_ON_NULL(image); 2014 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint, 2015 constraint); 2016} 2017 2018void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 2019 const SkPaint* paint) { 2020 RETURN_ON_NULL(image); 2021 if (dst.isEmpty()) { 2022 return; 2023 } 2024 if (SkLatticeIter::Valid(image->width(), image->height(), center)) { 2025 this->onDrawImageNine(image, center, dst, paint); 2026 } else { 2027 this->drawImageRect(image, dst, paint); 2028 } 2029} 2030 2031void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 2032 const SkPaint* paint) { 2033 RETURN_ON_NULL(image); 2034 if (dst.isEmpty()) { 2035 return; 2036 } 2037 if (SkLatticeIter::Valid(image->width(), image->height(), lattice)) { 2038 this->onDrawImageLattice(image, lattice, dst, paint); 2039 } else { 2040 this->drawImageRect(image, dst, paint); 2041 } 2042} 2043 2044void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { 2045 if (bitmap.drawsNothing()) { 2046 return; 2047 } 2048 this->onDrawBitmap(bitmap, dx, dy, paint); 2049} 2050 2051void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst, 2052 const SkPaint* paint, SrcRectConstraint constraint) { 2053 if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) { 2054 return; 2055 } 2056 this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint); 2057} 2058 2059void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst, 2060 const SkPaint* paint, SrcRectConstraint constraint) { 2061 this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint); 2062} 2063 2064void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, 2065 SrcRectConstraint constraint) { 2066 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint, 2067 constraint); 2068} 2069 2070void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2071 const SkPaint* paint) { 2072 if (bitmap.drawsNothing() || dst.isEmpty()) { 2073 return; 2074 } 2075 if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) { 2076 this->onDrawBitmapNine(bitmap, center, dst, paint); 2077 } else { 2078 this->drawBitmapRect(bitmap, dst, paint); 2079 } 2080} 2081 2082void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst, 2083 const SkPaint* paint) { 2084 if (bitmap.drawsNothing() || dst.isEmpty()) { 2085 return; 2086 } 2087 if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), lattice)) { 2088 this->onDrawBitmapLattice(bitmap, lattice, dst, paint); 2089 } else { 2090 this->drawBitmapRect(bitmap, dst, paint); 2091 } 2092} 2093 2094void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2095 const SkColor colors[], int count, SkXfermode::Mode mode, 2096 const SkRect* cull, const SkPaint* paint) { 2097 RETURN_ON_NULL(atlas); 2098 if (count <= 0) { 2099 return; 2100 } 2101 SkASSERT(atlas); 2102 SkASSERT(xform); 2103 SkASSERT(tex); 2104 this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); 2105} 2106 2107void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) { 2108 if (key) { 2109 this->onDrawAnnotation(rect, key, value); 2110 } 2111} 2112 2113void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 2114 const SkPaint* paint, SrcRectConstraint constraint) { 2115 if (src) { 2116 this->drawImageRect(image, *src, dst, paint, constraint); 2117 } else { 2118 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), 2119 dst, paint, constraint); 2120 } 2121} 2122void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2123 const SkPaint* paint, SrcRectConstraint constraint) { 2124 if (src) { 2125 this->drawBitmapRect(bitmap, *src, dst, paint, constraint); 2126 } else { 2127 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), 2128 dst, paint, constraint); 2129 } 2130} 2131 2132void SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) { 2133 SkIRect layer_bounds = this->getTopLayerBounds(); 2134 if (matrix) { 2135 *matrix = this->getTotalMatrix(); 2136 matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top()); 2137 } 2138 if (clip_bounds) { 2139 this->getClipDeviceBounds(clip_bounds); 2140 clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top()); 2141 } 2142} 2143 2144////////////////////////////////////////////////////////////////////////////// 2145// These are the virtual drawing methods 2146////////////////////////////////////////////////////////////////////////////// 2147 2148void SkCanvas::onDiscard() { 2149 if (fSurfaceBase) { 2150 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 2151 } 2152} 2153 2154void SkCanvas::onDrawPaint(const SkPaint& paint) { 2155 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 2156 this->internalDrawPaint(paint); 2157} 2158 2159void SkCanvas::internalDrawPaint(const SkPaint& paint) { 2160 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false) 2161 2162 while (iter.next()) { 2163 iter.fDevice->drawPaint(iter, looper.paint()); 2164 } 2165 2166 LOOPER_END 2167} 2168 2169void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 2170 const SkPaint& paint) { 2171 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 2172 if ((long)count <= 0) { 2173 return; 2174 } 2175 2176 SkRect r, storage; 2177 const SkRect* bounds = nullptr; 2178 if (paint.canComputeFastBounds()) { 2179 // special-case 2 points (common for drawing a single line) 2180 if (2 == count) { 2181 r.set(pts[0], pts[1]); 2182 } else { 2183 r.set(pts, SkToInt(count)); 2184 } 2185 if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) { 2186 return; 2187 } 2188 bounds = &r; 2189 } 2190 2191 SkASSERT(pts != nullptr); 2192 2193 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 2194 2195 while (iter.next()) { 2196 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 2197 } 2198 2199 LOOPER_END 2200} 2201 2202void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { 2203 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 2204 SkRect storage; 2205 const SkRect* bounds = nullptr; 2206 if (paint.canComputeFastBounds()) { 2207 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream. 2208 // To prevent accidental rejecting at this stage, we have to sort it before we check. 2209 SkRect tmp(r); 2210 tmp.sort(); 2211 2212 if (this->quickReject(paint.computeFastBounds(tmp, &storage))) { 2213 return; 2214 } 2215 bounds = &r; 2216 } 2217 2218 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false) 2219 2220 while (iter.next()) { 2221 iter.fDevice->drawRect(iter, r, looper.paint()); 2222 } 2223 2224 LOOPER_END 2225} 2226 2227void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 2228 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 2229 SkRect storage; 2230 const SkRect* bounds = nullptr; 2231 if (paint.canComputeFastBounds()) { 2232 if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 2233 return; 2234 } 2235 bounds = &oval; 2236 } 2237 2238 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 2239 2240 while (iter.next()) { 2241 iter.fDevice->drawOval(iter, oval, looper.paint()); 2242 } 2243 2244 LOOPER_END 2245} 2246 2247void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 2248 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 2249 SkRect storage; 2250 const SkRect* bounds = nullptr; 2251 if (paint.canComputeFastBounds()) { 2252 if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) { 2253 return; 2254 } 2255 bounds = &rrect.getBounds(); 2256 } 2257 2258 if (rrect.isRect()) { 2259 // call the non-virtual version 2260 this->SkCanvas::drawRect(rrect.getBounds(), paint); 2261 return; 2262 } else if (rrect.isOval()) { 2263 // call the non-virtual version 2264 this->SkCanvas::drawOval(rrect.getBounds(), paint); 2265 return; 2266 } 2267 2268 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 2269 2270 while (iter.next()) { 2271 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 2272 } 2273 2274 LOOPER_END 2275} 2276 2277void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 2278 const SkPaint& paint) { 2279 SkRect storage; 2280 const SkRect* bounds = nullptr; 2281 if (paint.canComputeFastBounds()) { 2282 if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) { 2283 return; 2284 } 2285 bounds = &outer.getBounds(); 2286 } 2287 2288 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 2289 2290 while (iter.next()) { 2291 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 2292 } 2293 2294 LOOPER_END 2295} 2296 2297void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 2298 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 2299 if (!path.isFinite()) { 2300 return; 2301 } 2302 2303 SkRect storage; 2304 const SkRect* bounds = nullptr; 2305 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 2306 const SkRect& pathBounds = path.getBounds(); 2307 if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) { 2308 return; 2309 } 2310 bounds = &pathBounds; 2311 } 2312 2313 const SkRect& r = path.getBounds(); 2314 if (r.width() <= 0 && r.height() <= 0) { 2315 if (path.isInverseFillType()) { 2316 this->internalDrawPaint(paint); 2317 return; 2318 } 2319 } 2320 2321 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 2322 2323 while (iter.next()) { 2324 iter.fDevice->drawPath(iter, path, looper.paint()); 2325 } 2326 2327 LOOPER_END 2328} 2329 2330bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) { 2331 if (!paint.getImageFilter()) { 2332 return false; 2333 } 2334 2335 const SkMatrix& ctm = this->getTotalMatrix(); 2336 if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) { 2337 return false; 2338 } 2339 2340 // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds. 2341 // Once we can filter and the filter will return a result larger than itself, we should be 2342 // able to remove this constraint. 2343 // skbug.com/4526 2344 // 2345 SkPoint pt; 2346 ctm.mapXY(x, y, &pt); 2347 SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h); 2348 return ir.contains(fMCRec->fRasterClip.getBounds()); 2349} 2350 2351void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 2352 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 2353 SkRect bounds = SkRect::MakeXYWH(x, y, 2354 SkIntToScalar(image->width()), SkIntToScalar(image->height())); 2355 if (nullptr == paint || paint->canComputeFastBounds()) { 2356 SkRect tmp = bounds; 2357 if (paint) { 2358 paint->computeFastBounds(tmp, &tmp); 2359 } 2360 if (this->quickReject(tmp)) { 2361 return; 2362 } 2363 } 2364 2365 SkLazyPaint lazy; 2366 if (nullptr == paint) { 2367 paint = lazy.init(); 2368 } 2369 2370 sk_sp<SkSpecialImage> special; 2371 bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), 2372 *paint); 2373 if (drawAsSprite && paint->getImageFilter()) { 2374 special = this->getDevice()->makeSpecial(image); 2375 if (!special) { 2376 drawAsSprite = false; 2377 } 2378 } 2379 2380 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds) 2381 2382 while (iter.next()) { 2383 const SkPaint& pnt = looper.paint(); 2384 if (special) { 2385 SkPoint pt; 2386 iter.fMatrix->mapXY(x, y, &pt); 2387 iter.fDevice->drawSpecial(iter, special.get(), 2388 SkScalarRoundToInt(pt.fX), 2389 SkScalarRoundToInt(pt.fY), pnt); 2390 } else { 2391 iter.fDevice->drawImage(iter, image, x, y, pnt); 2392 } 2393 } 2394 2395 LOOPER_END 2396} 2397 2398void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 2399 const SkPaint* paint, SrcRectConstraint constraint) { 2400 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 2401 if (nullptr == paint || paint->canComputeFastBounds()) { 2402 SkRect storage = dst; 2403 if (paint) { 2404 paint->computeFastBounds(dst, &storage); 2405 } 2406 if (this->quickReject(storage)) { 2407 return; 2408 } 2409 } 2410 SkLazyPaint lazy; 2411 if (nullptr == paint) { 2412 paint = lazy.init(); 2413 } 2414 2415 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2416 image->isOpaque()) 2417 2418 while (iter.next()) { 2419 iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint); 2420 } 2421 2422 LOOPER_END 2423} 2424 2425void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 2426 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 2427 SkDEBUGCODE(bitmap.validate();) 2428 2429 if (bitmap.drawsNothing()) { 2430 return; 2431 } 2432 2433 SkLazyPaint lazy; 2434 if (nullptr == paint) { 2435 paint = lazy.init(); 2436 } 2437 2438 const SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2439 2440 SkRect storage; 2441 const SkRect* bounds = nullptr; 2442 if (paint->canComputeFastBounds()) { 2443 bitmap.getBounds(&storage); 2444 matrix.mapRect(&storage); 2445 SkRect tmp = storage; 2446 if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) { 2447 return; 2448 } 2449 bounds = &storage; 2450 } 2451 2452 sk_sp<SkSpecialImage> special; 2453 bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(), 2454 *paint); 2455 if (drawAsSprite && paint->getImageFilter()) { 2456 special = this->getDevice()->makeSpecial(bitmap); 2457 if (!special) { 2458 drawAsSprite = false; 2459 } 2460 } 2461 2462 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds) 2463 2464 while (iter.next()) { 2465 const SkPaint& pnt = looper.paint(); 2466 if (special) { 2467 SkPoint pt; 2468 iter.fMatrix->mapXY(x, y, &pt); 2469 iter.fDevice->drawSpecial(iter, special.get(), 2470 SkScalarRoundToInt(pt.fX), 2471 SkScalarRoundToInt(pt.fY), pnt); 2472 } else { 2473 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 2474 } 2475 } 2476 2477 LOOPER_END 2478} 2479 2480// this one is non-virtual, so it can be called safely by other canvas apis 2481void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2482 const SkRect& dst, const SkPaint* paint, 2483 SrcRectConstraint constraint) { 2484 if (bitmap.drawsNothing() || dst.isEmpty()) { 2485 return; 2486 } 2487 2488 if (nullptr == paint || paint->canComputeFastBounds()) { 2489 SkRect storage; 2490 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2491 return; 2492 } 2493 } 2494 2495 SkLazyPaint lazy; 2496 if (nullptr == paint) { 2497 paint = lazy.init(); 2498 } 2499 2500 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2501 bitmap.isOpaque()) 2502 2503 while (iter.next()) { 2504 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint); 2505 } 2506 2507 LOOPER_END 2508} 2509 2510void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2511 const SkPaint* paint, SrcRectConstraint constraint) { 2512 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 2513 SkDEBUGCODE(bitmap.validate();) 2514 this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint); 2515} 2516 2517void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 2518 const SkPaint* paint) { 2519 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()"); 2520 2521 if (nullptr == paint || paint->canComputeFastBounds()) { 2522 SkRect storage; 2523 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2524 return; 2525 } 2526 } 2527 2528 SkLazyPaint lazy; 2529 if (nullptr == paint) { 2530 paint = lazy.init(); 2531 } 2532 2533 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2534 2535 while (iter.next()) { 2536 iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint()); 2537 } 2538 2539 LOOPER_END 2540} 2541 2542void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2543 const SkPaint* paint) { 2544 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2545 SkDEBUGCODE(bitmap.validate();) 2546 2547 if (nullptr == paint || paint->canComputeFastBounds()) { 2548 SkRect storage; 2549 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2550 return; 2551 } 2552 } 2553 2554 SkLazyPaint lazy; 2555 if (nullptr == paint) { 2556 paint = lazy.init(); 2557 } 2558 2559 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2560 2561 while (iter.next()) { 2562 iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint()); 2563 } 2564 2565 LOOPER_END 2566} 2567 2568void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 2569 const SkPaint* paint) { 2570 if (nullptr == paint || paint->canComputeFastBounds()) { 2571 SkRect storage; 2572 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2573 return; 2574 } 2575 } 2576 2577 SkLazyPaint lazy; 2578 if (nullptr == paint) { 2579 paint = lazy.init(); 2580 } 2581 2582 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2583 2584 while (iter.next()) { 2585 iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint()); 2586 } 2587 2588 LOOPER_END 2589} 2590 2591void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, 2592 const SkRect& dst, const SkPaint* paint) { 2593 if (nullptr == paint || paint->canComputeFastBounds()) { 2594 SkRect storage; 2595 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2596 return; 2597 } 2598 } 2599 2600 SkLazyPaint lazy; 2601 if (nullptr == paint) { 2602 paint = lazy.init(); 2603 } 2604 2605 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2606 2607 while (iter.next()) { 2608 iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint()); 2609 } 2610 2611 LOOPER_END 2612} 2613 2614class SkDeviceFilteredPaint { 2615public: 2616 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2617 uint32_t filteredFlags = device->filterTextFlags(paint); 2618 if (filteredFlags != paint.getFlags()) { 2619 SkPaint* newPaint = fLazy.set(paint); 2620 newPaint->setFlags(filteredFlags); 2621 fPaint = newPaint; 2622 } else { 2623 fPaint = &paint; 2624 } 2625 } 2626 2627 const SkPaint& paint() const { return *fPaint; } 2628 2629private: 2630 const SkPaint* fPaint; 2631 SkLazyPaint fLazy; 2632}; 2633 2634void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2635 const SkRect& r, SkScalar textSize) { 2636 if (paint.getStyle() == SkPaint::kFill_Style) { 2637 draw.fDevice->drawRect(draw, r, paint); 2638 } else { 2639 SkPaint p(paint); 2640 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2641 draw.fDevice->drawRect(draw, r, p); 2642 } 2643} 2644 2645void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2646 const char text[], size_t byteLength, 2647 SkScalar x, SkScalar y) { 2648 SkASSERT(byteLength == 0 || text != nullptr); 2649 2650 // nothing to draw 2651 if (text == nullptr || byteLength == 0 || 2652 draw.fRC->isEmpty() || 2653 (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) { 2654 return; 2655 } 2656 2657 SkScalar width = 0; 2658 SkPoint start; 2659 2660 start.set(0, 0); // to avoid warning 2661 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2662 SkPaint::kStrikeThruText_Flag)) { 2663 width = paint.measureText(text, byteLength); 2664 2665 SkScalar offsetX = 0; 2666 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2667 offsetX = SkScalarHalf(width); 2668 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2669 offsetX = width; 2670 } 2671 start.set(x - offsetX, y); 2672 } 2673 2674 if (0 == width) { 2675 return; 2676 } 2677 2678 uint32_t flags = paint.getFlags(); 2679 2680 if (flags & (SkPaint::kUnderlineText_Flag | 2681 SkPaint::kStrikeThruText_Flag)) { 2682 SkScalar textSize = paint.getTextSize(); 2683 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2684 SkRect r; 2685 2686 r.fLeft = start.fX; 2687 r.fRight = start.fX + width; 2688 2689 if (flags & SkPaint::kUnderlineText_Flag) { 2690 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2691 start.fY); 2692 r.fTop = offset; 2693 r.fBottom = offset + height; 2694 DrawRect(draw, paint, r, 1); 2695 } 2696 if (flags & SkPaint::kStrikeThruText_Flag) { 2697 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2698 start.fY); 2699 r.fTop = offset; 2700 r.fBottom = offset + height; 2701 DrawRect(draw, paint, r, 1); 2702 } 2703 } 2704} 2705 2706void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2707 const SkPaint& paint) { 2708 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2709 2710 while (iter.next()) { 2711 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2712 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2713 DrawTextDecorations(iter, dfp.paint(), 2714 static_cast<const char*>(text), byteLength, x, y); 2715 } 2716 2717 LOOPER_END 2718} 2719 2720void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2721 const SkPaint& paint) { 2722 SkPoint textOffset = SkPoint::Make(0, 0); 2723 2724 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2725 2726 while (iter.next()) { 2727 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2728 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2729 dfp.paint()); 2730 } 2731 2732 LOOPER_END 2733} 2734 2735void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2736 SkScalar constY, const SkPaint& paint) { 2737 2738 SkPoint textOffset = SkPoint::Make(0, constY); 2739 2740 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2741 2742 while (iter.next()) { 2743 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2744 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2745 dfp.paint()); 2746 } 2747 2748 LOOPER_END 2749} 2750 2751void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2752 const SkMatrix* matrix, const SkPaint& paint) { 2753 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2754 2755 while (iter.next()) { 2756 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2757 matrix, looper.paint()); 2758 } 2759 2760 LOOPER_END 2761} 2762 2763void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 2764 const SkRect* cullRect, const SkPaint& paint) { 2765 if (cullRect && this->quickReject(*cullRect)) { 2766 return; 2767 } 2768 2769 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2770 2771 while (iter.next()) { 2772 iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint()); 2773 } 2774 2775 LOOPER_END 2776} 2777 2778void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2779 const SkPaint& paint) { 2780 2781 SkRect storage; 2782 const SkRect* bounds = nullptr; 2783 if (paint.canComputeFastBounds()) { 2784 storage = blob->bounds().makeOffset(x, y); 2785 SkRect tmp; 2786 if (this->quickReject(paint.computeFastBounds(storage, &tmp))) { 2787 return; 2788 } 2789 bounds = &storage; 2790 } 2791 2792 // We cannot filter in the looper as we normally do, because the paint is 2793 // incomplete at this point (text-related attributes are embedded within blob run paints). 2794 SkDrawFilter* drawFilter = fMCRec->fFilter; 2795 fMCRec->fFilter = nullptr; 2796 2797 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2798 2799 while (iter.next()) { 2800 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2801 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); 2802 } 2803 2804 LOOPER_END 2805 2806 fMCRec->fFilter = drawFilter; 2807} 2808 2809// These will become non-virtual, so they always call the (virtual) onDraw... method 2810void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2811 const SkPaint& paint) { 2812 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2813 if (byteLength) { 2814 this->onDrawText(text, byteLength, x, y, paint); 2815 } 2816} 2817void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2818 const SkPaint& paint) { 2819 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2820 if (byteLength) { 2821 this->onDrawPosText(text, byteLength, pos, paint); 2822 } 2823} 2824void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2825 SkScalar constY, const SkPaint& paint) { 2826 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2827 if (byteLength) { 2828 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2829 } 2830} 2831void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2832 const SkMatrix* matrix, const SkPaint& paint) { 2833 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2834 if (byteLength) { 2835 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2836 } 2837} 2838void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 2839 const SkRect* cullRect, const SkPaint& paint) { 2840 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()"); 2841 if (byteLength) { 2842 this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint); 2843 } 2844} 2845void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2846 const SkPaint& paint) { 2847 RETURN_ON_NULL(blob); 2848 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2849 this->onDrawTextBlob(blob, x, y, paint); 2850} 2851 2852void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 2853 const SkPoint verts[], const SkPoint texs[], 2854 const SkColor colors[], SkXfermode* xmode, 2855 const uint16_t indices[], int indexCount, 2856 const SkPaint& paint) { 2857 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2858 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2859 2860 while (iter.next()) { 2861 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2862 colors, xmode, indices, indexCount, 2863 looper.paint()); 2864 } 2865 2866 LOOPER_END 2867} 2868 2869void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2870 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2871 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2872 if (nullptr == cubics) { 2873 return; 2874 } 2875 2876 // Since a patch is always within the convex hull of the control points, we discard it when its 2877 // bounding rectangle is completely outside the current clip. 2878 SkRect bounds; 2879 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2880 if (this->quickReject(bounds)) { 2881 return; 2882 } 2883 2884 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2885} 2886 2887void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2888 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2889 2890 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2891 2892 while (iter.next()) { 2893 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2894 } 2895 2896 LOOPER_END 2897} 2898 2899void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) { 2900 RETURN_ON_NULL(dr); 2901 if (x || y) { 2902 SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2903 this->onDrawDrawable(dr, &matrix); 2904 } else { 2905 this->onDrawDrawable(dr, nullptr); 2906 } 2907} 2908 2909void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2910 RETURN_ON_NULL(dr); 2911 if (matrix && matrix->isIdentity()) { 2912 matrix = nullptr; 2913 } 2914 this->onDrawDrawable(dr, matrix); 2915} 2916 2917void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2918 SkRect bounds = dr->getBounds(); 2919 if (matrix) { 2920 matrix->mapRect(&bounds); 2921 } 2922 if (this->quickReject(bounds)) { 2923 return; 2924 } 2925 dr->draw(this, matrix); 2926} 2927 2928void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2929 const SkColor colors[], int count, SkXfermode::Mode mode, 2930 const SkRect* cull, const SkPaint* paint) { 2931 if (cull && this->quickReject(*cull)) { 2932 return; 2933 } 2934 2935 SkPaint pnt; 2936 if (paint) { 2937 pnt = *paint; 2938 } 2939 2940 LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr) 2941 while (iter.next()) { 2942 iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt); 2943 } 2944 LOOPER_END 2945} 2946 2947void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { 2948 SkASSERT(key); 2949 2950 SkPaint paint; 2951 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr) 2952 while (iter.next()) { 2953 iter.fDevice->drawAnnotation(iter, rect, key, value); 2954 } 2955 LOOPER_END 2956} 2957 2958////////////////////////////////////////////////////////////////////////////// 2959// These methods are NOT virtual, and therefore must call back into virtual 2960// methods, rather than actually drawing themselves. 2961////////////////////////////////////////////////////////////////////////////// 2962 2963void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2964 SkXfermode::Mode mode) { 2965 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2966 SkPaint paint; 2967 2968 paint.setARGB(a, r, g, b); 2969 if (SkXfermode::kSrcOver_Mode != mode) { 2970 paint.setXfermodeMode(mode); 2971 } 2972 this->drawPaint(paint); 2973} 2974 2975void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2976 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2977 SkPaint paint; 2978 2979 paint.setColor(c); 2980 if (SkXfermode::kSrcOver_Mode != mode) { 2981 paint.setXfermodeMode(mode); 2982 } 2983 this->drawPaint(paint); 2984} 2985 2986void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2987 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2988 SkPoint pt; 2989 2990 pt.set(x, y); 2991 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2992} 2993 2994void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2995 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2996 SkPoint pt; 2997 SkPaint paint; 2998 2999 pt.set(x, y); 3000 paint.setColor(color); 3001 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 3002} 3003 3004void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 3005 const SkPaint& paint) { 3006 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 3007 SkPoint pts[2]; 3008 3009 pts[0].set(x0, y0); 3010 pts[1].set(x1, y1); 3011 this->drawPoints(kLines_PointMode, 2, pts, paint); 3012} 3013 3014void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 3015 SkScalar right, SkScalar bottom, 3016 const SkPaint& paint) { 3017 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 3018 SkRect r; 3019 3020 r.set(left, top, right, bottom); 3021 this->drawRect(r, paint); 3022} 3023 3024void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 3025 const SkPaint& paint) { 3026 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 3027 if (radius < 0) { 3028 radius = 0; 3029 } 3030 3031 SkRect r; 3032 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 3033 this->drawOval(r, paint); 3034} 3035 3036void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 3037 const SkPaint& paint) { 3038 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 3039 if (rx > 0 && ry > 0) { 3040 SkRRect rrect; 3041 rrect.setRectXY(r, rx, ry); 3042 this->drawRRect(rrect, paint); 3043 } else { 3044 this->drawRect(r, paint); 3045 } 3046} 3047 3048void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 3049 SkScalar sweepAngle, bool useCenter, 3050 const SkPaint& paint) { 3051 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 3052 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 3053 this->drawOval(oval, paint); 3054 } else { 3055 SkPath path; 3056 if (useCenter) { 3057 path.moveTo(oval.centerX(), oval.centerY()); 3058 } 3059 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 3060 if (useCenter) { 3061 path.close(); 3062 } 3063 this->drawPath(path, paint); 3064 } 3065} 3066 3067void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 3068 const SkPath& path, SkScalar hOffset, 3069 SkScalar vOffset, const SkPaint& paint) { 3070 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 3071 SkMatrix matrix; 3072 3073 matrix.setTranslate(hOffset, vOffset); 3074 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 3075} 3076 3077/////////////////////////////////////////////////////////////////////////////// 3078 3079/** 3080 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 3081 * against the playback cost of recursing into the subpicture to get at its actual ops. 3082 * 3083 * For now we pick a conservatively small value, though measurement (and other heuristics like 3084 * the type of ops contained) may justify changing this value. 3085 */ 3086#define kMaxPictureOpsToUnrollInsteadOfRef 1 3087 3088void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 3089 RETURN_ON_NULL(picture); 3090 3091 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 3092 if (matrix && matrix->isIdentity()) { 3093 matrix = nullptr; 3094 } 3095 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { 3096 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 3097 picture->playback(this); 3098 } else { 3099 this->onDrawPicture(picture, matrix, paint); 3100 } 3101} 3102 3103void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 3104 const SkPaint* paint) { 3105 if (!paint || paint->canComputeFastBounds()) { 3106 SkRect bounds = picture->cullRect(); 3107 if (paint) { 3108 paint->computeFastBounds(bounds, &bounds); 3109 } 3110 if (matrix) { 3111 matrix->mapRect(&bounds); 3112 } 3113 if (this->quickReject(bounds)) { 3114 return; 3115 } 3116 } 3117 3118 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 3119 picture->playback(this); 3120} 3121 3122#ifdef SK_EXPERIMENTAL_SHADOWING 3123void SkCanvas::drawShadowedPicture(const SkPicture* picture, 3124 const SkMatrix* matrix, 3125 const SkPaint* paint) { 3126 RETURN_ON_NULL(picture); 3127 3128 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()"); 3129 3130 this->onDrawShadowedPicture(picture, matrix, paint); 3131} 3132 3133void SkCanvas::onDrawShadowedPicture(const SkPicture* picture, 3134 const SkMatrix* matrix, 3135 const SkPaint* paint) { 3136 if (!paint || paint->canComputeFastBounds()) { 3137 SkRect bounds = picture->cullRect(); 3138 if (paint) { 3139 paint->computeFastBounds(bounds, &bounds); 3140 } 3141 if (matrix) { 3142 matrix->mapRect(&bounds); 3143 } 3144 if (this->quickReject(bounds)) { 3145 return; 3146 } 3147 } 3148 3149 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 3150 3151 for (int i = 0; i < fLights->numLights(); ++i) { 3152 // skip over ambient lights; they don't cast shadows 3153 // lights that have shadow maps do not need updating (because lights are immutable) 3154 3155 if (SkLights::Light::kAmbient_LightType == fLights->light(i).type() || 3156 fLights->light(i).getShadowMap() != nullptr) { 3157 continue; 3158 } 3159 3160 // TODO: compute the correct size of the depth map from the light properties 3161 // TODO: maybe add a kDepth_8_SkColorType 3162 // TODO: find actual max depth of picture 3163 SkISize shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize( 3164 fLights->light(i), 255, 3165 picture->cullRect().width(), 3166 picture->cullRect().height()); 3167 3168 SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight, 3169 kBGRA_8888_SkColorType, 3170 kOpaque_SkAlphaType); 3171 3172 // Create a new surface (that matches the backend of canvas) 3173 // for each shadow map 3174 sk_sp<SkSurface> surf(this->makeSurface(info)); 3175 3176 // Wrap another SPFCanvas around the surface 3177 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = 3178 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); 3179 3180 // set the depth map canvas to have the light we're drawing. 3181 SkLights::Builder builder; 3182 builder.add(fLights->light(i)); 3183 sk_sp<SkLights> curLight = builder.finish(); 3184 3185 depthMapCanvas->setLights(std::move(curLight)); 3186 depthMapCanvas->drawPicture(picture); 3187 3188 fLights->light(i).setShadowMap(surf->makeImageSnapshot()); 3189 } 3190 3191 sk_sp<SkImage> povDepthMap; 3192 sk_sp<SkImage> diffuseMap; 3193 3194 // TODO: pass the depth to the shader in vertices, or uniforms 3195 // so we don't have to render depth and color separately 3196 3197 // povDepthMap 3198 { 3199 SkLights::Builder builder; 3200 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f), 3201 SkVector3::Make(0.0f, 0.0f, 1.0f))); 3202 sk_sp<SkLights> povLight = builder.finish(); 3203 3204 SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(), 3205 picture->cullRect().height(), 3206 kBGRA_8888_SkColorType, 3207 kOpaque_SkAlphaType); 3208 3209 // Create a new surface (that matches the backend of canvas) 3210 // to create the povDepthMap 3211 sk_sp<SkSurface> surf(this->makeSurface(info)); 3212 3213 // Wrap another SPFCanvas around the surface 3214 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = 3215 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); 3216 3217 // set the depth map canvas to have the light as the user's POV 3218 depthMapCanvas->setLights(std::move(povLight)); 3219 3220 depthMapCanvas->drawPicture(picture); 3221 3222 povDepthMap = surf->makeImageSnapshot(); 3223 } 3224 3225 // diffuseMap 3226 { 3227 SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(), 3228 picture->cullRect().height(), 3229 kBGRA_8888_SkColorType, 3230 kOpaque_SkAlphaType); 3231 3232 sk_sp<SkSurface> surf(this->makeSurface(info)); 3233 surf->getCanvas()->drawPicture(picture); 3234 3235 diffuseMap = surf->makeImageSnapshot(); 3236 } 3237 3238 SkPaint shadowPaint; 3239 3240 sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode, 3241 SkShader::kClamp_TileMode); 3242 3243 sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode, 3244 SkShader::kClamp_TileMode); 3245 3246 sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader), 3247 std::move(diffuseShader), 3248 std::move(fLights), 3249 diffuseMap->width(), 3250 diffuseMap->height()); 3251 3252 shadowPaint.setShader(shadowShader); 3253 3254 this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint); 3255} 3256#endif 3257 3258/////////////////////////////////////////////////////////////////////////////// 3259/////////////////////////////////////////////////////////////////////////////// 3260 3261SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) { 3262 static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small"); 3263 3264 SkASSERT(canvas); 3265 3266 fImpl = new (fStorage) SkDrawIter(canvas); 3267 fDone = !fImpl->next(); 3268} 3269 3270SkCanvas::LayerIter::~LayerIter() { 3271 fImpl->~SkDrawIter(); 3272} 3273 3274void SkCanvas::LayerIter::next() { 3275 fDone = !fImpl->next(); 3276} 3277 3278SkBaseDevice* SkCanvas::LayerIter::device() const { 3279 return fImpl->getDevice(); 3280} 3281 3282const SkMatrix& SkCanvas::LayerIter::matrix() const { 3283 return fImpl->getMatrix(); 3284} 3285 3286const SkPaint& SkCanvas::LayerIter::paint() const { 3287 const SkPaint* paint = fImpl->getPaint(); 3288 if (nullptr == paint) { 3289 paint = &fDefaultPaint; 3290 } 3291 return *paint; 3292} 3293 3294const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 3295int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 3296int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 3297 3298/////////////////////////////////////////////////////////////////////////////// 3299 3300SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 3301 3302/////////////////////////////////////////////////////////////////////////////// 3303 3304static bool supported_for_raster_canvas(const SkImageInfo& info) { 3305 switch (info.alphaType()) { 3306 case kPremul_SkAlphaType: 3307 case kOpaque_SkAlphaType: 3308 break; 3309 default: 3310 return false; 3311 } 3312 3313 switch (info.colorType()) { 3314 case kAlpha_8_SkColorType: 3315 case kRGB_565_SkColorType: 3316 case kN32_SkColorType: 3317 break; 3318 default: 3319 return false; 3320 } 3321 3322 return true; 3323} 3324 3325SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 3326 if (!supported_for_raster_canvas(info)) { 3327 return nullptr; 3328 } 3329 3330 SkBitmap bitmap; 3331 if (!bitmap.installPixels(info, pixels, rowBytes)) { 3332 return nullptr; 3333 } 3334 return new SkCanvas(bitmap); 3335} 3336 3337/////////////////////////////////////////////////////////////////////////////// 3338 3339SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 3340 const SkPaint* paint, const SkRect& bounds) 3341 : fCanvas(canvas) 3342 , fSaveCount(canvas->getSaveCount()) 3343{ 3344 if (paint) { 3345 SkRect newBounds = bounds; 3346 if (matrix) { 3347 matrix->mapRect(&newBounds); 3348 } 3349 canvas->saveLayer(&newBounds, paint); 3350 } else if (matrix) { 3351 canvas->save(); 3352 } 3353 3354 if (matrix) { 3355 canvas->concat(*matrix); 3356 } 3357} 3358 3359SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 3360 fCanvas->restoreToCount(fSaveCount); 3361} 3362 3363#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API 3364SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 3365 return this->makeSurface(info, props).release(); 3366} 3367#endif 3368