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