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