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