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