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