SkCanvas.cpp revision 887cdf112809727c51890ba8b98b3ddce22249f0
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 1576void SkCanvas::replayClips(ClipVisitor* visitor) const { 1577#if 0 1578 SkClipStack::B2TIter iter(*fClipStack); 1579 const SkClipStack::Element* element; 1580 1581 while ((element = iter.next()) != nullptr) { 1582 element->replay(visitor); 1583 } 1584#endif 1585} 1586 1587bool SkCanvas::androidFramework_isClipAA() const { 1588 bool containsAA = false; 1589 1590 FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA()); 1591 1592 return containsAA; 1593} 1594 1595class RgnAccumulator { 1596 SkRegion* fRgn; 1597public: 1598 RgnAccumulator(SkRegion* total) : fRgn(total) {} 1599 void accumulate(SkBaseDevice* device, SkRegion* rgn) { 1600 SkIPoint origin = device->getOrigin(); 1601 if (origin.x() | origin.y()) { 1602 rgn->translate(origin.x(), origin.y()); 1603 } 1604 fRgn->op(*rgn, SkRegion::kUnion_Op); 1605 } 1606}; 1607 1608void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) { 1609 RgnAccumulator accum(rgn); 1610 SkRegion tmp; 1611 1612 rgn->setEmpty(); 1613 FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp)); 1614} 1615 1616/////////////////////////////////////////////////////////////////////////////// 1617 1618bool SkCanvas::isClipEmpty() const { 1619 return fMCRec->fRasterClip.isEmpty(); 1620 1621 // TODO: should we only use the conservative answer in a recording canvas? 1622#if 0 1623 SkBaseDevice* dev = this->getTopDevice(); 1624 // if no device we return true 1625 return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType; 1626#endif 1627} 1628 1629bool SkCanvas::isClipRect() const { 1630 SkBaseDevice* dev = this->getTopDevice(); 1631 // if no device we return false 1632 return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType; 1633} 1634 1635static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) { 1636#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 1637 __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec); 1638 __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec); 1639 __m128 mask = _mm_cmplt_ps(lLtT, RrBb); 1640 return 0xF != _mm_movemask_ps(mask); 1641#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON) 1642 float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0]; 1643 float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1]; 1644 uint32x4_t mask = vcltq_f32(lLtT, RrBb); 1645 return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask); 1646#else 1647 SkRect devRectAsRect; 1648 SkRect devClipAsRect; 1649 devRect.store(&devRectAsRect.fLeft); 1650 devClip.store(&devClipAsRect.fLeft); 1651 return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect); 1652#endif 1653} 1654 1655// It's important for this function to not be inlined. Otherwise the compiler will share code 1656// between the fast path and the slow path, resulting in two slow paths. 1657static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip, 1658 const SkMatrix& matrix) { 1659 SkRect deviceRect; 1660 matrix.mapRect(&deviceRect, src); 1661 return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip); 1662} 1663 1664bool SkCanvas::quickReject(const SkRect& src) const { 1665#ifdef SK_DEBUG 1666 // Verify that fDeviceClipBounds are set properly. 1667 SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); 1668 if (fMCRec->fRasterClip.isEmpty()) { 1669 SkASSERT(fDeviceClipBounds.isEmpty()); 1670 } else { 1671 SkASSERT(tmp == fDeviceClipBounds); 1672 } 1673 1674 // Verify that fIsScaleTranslate is set properly. 1675 SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate()); 1676#endif 1677 1678 if (!fIsScaleTranslate) { 1679 return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix); 1680 } 1681 1682 // We inline the implementation of mapScaleTranslate() for the fast path. 1683 float sx = fMCRec->fMatrix.getScaleX(); 1684 float sy = fMCRec->fMatrix.getScaleY(); 1685 float tx = fMCRec->fMatrix.getTranslateX(); 1686 float ty = fMCRec->fMatrix.getTranslateY(); 1687 Sk4f scale(sx, sy, sx, sy); 1688 Sk4f trans(tx, ty, tx, ty); 1689 1690 // Apply matrix. 1691 Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans; 1692 1693 // Make sure left < right, top < bottom. 1694 Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]); 1695 Sk4f min = Sk4f::Min(ltrb, rblt); 1696 Sk4f max = Sk4f::Max(ltrb, rblt); 1697 // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on 1698 // ARM this sequence generates the fastest (a single instruction). 1699 Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]); 1700 1701 // Check if the device rect is NaN or outside the clip. 1702 return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft)); 1703} 1704 1705bool SkCanvas::quickReject(const SkPath& path) const { 1706 return path.isEmpty() || this->quickReject(path.getBounds()); 1707} 1708 1709SkRect SkCanvas::onGetLocalClipBounds() const { 1710 SkIRect ibounds = this->onGetDeviceClipBounds(); 1711 if (ibounds.isEmpty()) { 1712 return SkRect::MakeEmpty(); 1713 } 1714 1715 SkMatrix inverse; 1716 // if we can't invert the CTM, we can't return local clip bounds 1717 if (!fMCRec->fMatrix.invert(&inverse)) { 1718 return SkRect::MakeEmpty(); 1719 } 1720 1721 SkRect bounds; 1722 SkRect r; 1723 // adjust it outwards in case we are antialiasing 1724 const int inset = 1; 1725 1726 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1727 ibounds.fRight + inset, ibounds.fBottom + inset); 1728 inverse.mapRect(&bounds, r); 1729 return bounds; 1730} 1731 1732SkIRect SkCanvas::onGetDeviceClipBounds() const { 1733 return fMCRec->fRasterClip.getBounds(); 1734} 1735 1736const SkMatrix& SkCanvas::getTotalMatrix() const { 1737 return fMCRec->fMatrix; 1738} 1739 1740GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() { 1741 SkBaseDevice* dev = this->getTopDevice(); 1742 return dev ? dev->accessRenderTargetContext() : nullptr; 1743} 1744 1745GrContext* SkCanvas::getGrContext() { 1746 SkBaseDevice* device = this->getTopDevice(); 1747 return device ? device->context() : nullptr; 1748} 1749 1750void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1751 const SkPaint& paint) { 1752 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()"); 1753 if (outer.isEmpty()) { 1754 return; 1755 } 1756 if (inner.isEmpty()) { 1757 this->drawRRect(outer, paint); 1758 return; 1759 } 1760 1761 // We don't have this method (yet), but technically this is what we should 1762 // be able to assert... 1763 // SkASSERT(outer.contains(inner)); 1764 // 1765 // For now at least check for containment of bounds 1766 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1767 1768 this->onDrawDRRect(outer, inner, paint); 1769} 1770 1771// These need to stop being virtual -- clients need to override the onDraw... versions 1772 1773void SkCanvas::drawPaint(const SkPaint& paint) { 1774 this->onDrawPaint(paint); 1775} 1776 1777void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1778 this->onDrawRect(r, paint); 1779} 1780 1781void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { 1782 if (region.isEmpty()) { 1783 return; 1784 } 1785 1786 if (region.isRect()) { 1787 return this->drawIRect(region.getBounds(), paint); 1788 } 1789 1790 this->onDrawRegion(region, paint); 1791} 1792 1793void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) { 1794 this->onDrawOval(r, paint); 1795} 1796 1797void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1798 this->onDrawRRect(rrect, paint); 1799} 1800 1801void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { 1802 this->onDrawPoints(mode, count, pts, paint); 1803} 1804 1805#ifdef SK_SUPPORT_LEGACY_CANVAS_VERTICES 1806void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint positions[], 1807 const SkPoint texs[], const SkColor colors[], SkBlendMode bmode, 1808 const uint16_t indices[], int indexCount, const SkPaint& paint) { 1809 auto vertices = SkVertices::MakeCopy(vmode, vertexCount, positions, texs, colors, 1810 indexCount, indices); 1811 if (vertices) { 1812 this->onDrawVerticesObject(vertices.get(), bmode, paint); 1813 } 1814} 1815#endif 1816 1817void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, 1818 const SkPaint& paint) { 1819 RETURN_ON_NULL(vertices); 1820 this->onDrawVerticesObject(vertices.get(), mode, paint); 1821} 1822 1823void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { 1824 RETURN_ON_NULL(vertices); 1825 this->onDrawVerticesObject(vertices, mode, paint); 1826} 1827 1828void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1829 this->onDrawPath(path, paint); 1830} 1831 1832void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1833 RETURN_ON_NULL(image); 1834 this->onDrawImage(image, x, y, paint); 1835} 1836 1837void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, 1838 const SkPaint* paint, SrcRectConstraint constraint) { 1839 RETURN_ON_NULL(image); 1840 if (dst.isEmpty() || src.isEmpty()) { 1841 return; 1842 } 1843 this->onDrawImageRect(image, &src, dst, paint, constraint); 1844} 1845 1846void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst, 1847 const SkPaint* paint, SrcRectConstraint constraint) { 1848 RETURN_ON_NULL(image); 1849 this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint); 1850} 1851 1852void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint, 1853 SrcRectConstraint constraint) { 1854 RETURN_ON_NULL(image); 1855 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint, 1856 constraint); 1857} 1858 1859void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 1860 const SkPaint* paint) { 1861 RETURN_ON_NULL(image); 1862 if (dst.isEmpty()) { 1863 return; 1864 } 1865 if (SkLatticeIter::Valid(image->width(), image->height(), center)) { 1866 this->onDrawImageNine(image, center, dst, paint); 1867 } else { 1868 this->drawImageRect(image, dst, paint); 1869 } 1870} 1871 1872void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 1873 const SkPaint* paint) { 1874 RETURN_ON_NULL(image); 1875 if (dst.isEmpty()) { 1876 return; 1877 } 1878 1879 SkIRect bounds; 1880 Lattice latticePlusBounds = lattice; 1881 if (!latticePlusBounds.fBounds) { 1882 bounds = SkIRect::MakeWH(image->width(), image->height()); 1883 latticePlusBounds.fBounds = &bounds; 1884 } 1885 1886 if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) { 1887 this->onDrawImageLattice(image, latticePlusBounds, dst, paint); 1888 } else { 1889 this->drawImageRect(image, dst, paint); 1890 } 1891} 1892 1893void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1894 if (bitmap.drawsNothing()) { 1895 return; 1896 } 1897 this->onDrawBitmap(bitmap, dx, dy, paint); 1898} 1899 1900void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst, 1901 const SkPaint* paint, SrcRectConstraint constraint) { 1902 if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) { 1903 return; 1904 } 1905 this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint); 1906} 1907 1908void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst, 1909 const SkPaint* paint, SrcRectConstraint constraint) { 1910 this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint); 1911} 1912 1913void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, 1914 SrcRectConstraint constraint) { 1915 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint, 1916 constraint); 1917} 1918 1919void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 1920 const SkPaint* paint) { 1921 if (bitmap.drawsNothing() || dst.isEmpty()) { 1922 return; 1923 } 1924 if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) { 1925 this->onDrawBitmapNine(bitmap, center, dst, paint); 1926 } else { 1927 this->drawBitmapRect(bitmap, dst, paint); 1928 } 1929} 1930 1931void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst, 1932 const SkPaint* paint) { 1933 if (bitmap.drawsNothing() || dst.isEmpty()) { 1934 return; 1935 } 1936 1937 SkIRect bounds; 1938 Lattice latticePlusBounds = lattice; 1939 if (!latticePlusBounds.fBounds) { 1940 bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height()); 1941 latticePlusBounds.fBounds = &bounds; 1942 } 1943 1944 if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) { 1945 this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint); 1946 } else { 1947 this->drawBitmapRect(bitmap, dst, paint); 1948 } 1949} 1950 1951void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 1952 const SkColor colors[], int count, SkBlendMode mode, 1953 const SkRect* cull, const SkPaint* paint) { 1954 RETURN_ON_NULL(atlas); 1955 if (count <= 0) { 1956 return; 1957 } 1958 SkASSERT(atlas); 1959 SkASSERT(tex); 1960 this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); 1961} 1962 1963void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) { 1964 if (key) { 1965 this->onDrawAnnotation(rect, key, value); 1966 } 1967} 1968 1969void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1970 const SkPaint* paint, SrcRectConstraint constraint) { 1971 if (src) { 1972 this->drawImageRect(image, *src, dst, paint, constraint); 1973 } else { 1974 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), 1975 dst, paint, constraint); 1976 } 1977} 1978void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 1979 const SkPaint* paint, SrcRectConstraint constraint) { 1980 if (src) { 1981 this->drawBitmapRect(bitmap, *src, dst, paint, constraint); 1982 } else { 1983 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), 1984 dst, paint, constraint); 1985 } 1986} 1987 1988void SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) { 1989 SkIRect layer_bounds = this->getTopLayerBounds(); 1990 if (matrix) { 1991 *matrix = this->getTotalMatrix(); 1992 matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top()); 1993 } 1994 if (clip_bounds) { 1995 *clip_bounds = this->getDeviceClipBounds(); 1996 clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top()); 1997 } 1998} 1999 2000////////////////////////////////////////////////////////////////////////////// 2001// These are the virtual drawing methods 2002////////////////////////////////////////////////////////////////////////////// 2003 2004void SkCanvas::onDiscard() { 2005 if (fSurfaceBase) { 2006 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 2007 } 2008} 2009 2010void SkCanvas::onDrawPaint(const SkPaint& paint) { 2011 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 2012 this->internalDrawPaint(paint); 2013} 2014 2015void SkCanvas::internalDrawPaint(const SkPaint& paint) { 2016 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false) 2017 2018 while (iter.next()) { 2019 iter.fDevice->drawPaint(looper.paint()); 2020 } 2021 2022 LOOPER_END 2023} 2024 2025void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 2026 const SkPaint& paint) { 2027 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 2028 if ((long)count <= 0) { 2029 return; 2030 } 2031 2032 SkRect r; 2033 const SkRect* bounds = nullptr; 2034 if (paint.canComputeFastBounds()) { 2035 // special-case 2 points (common for drawing a single line) 2036 if (2 == count) { 2037 r.set(pts[0], pts[1]); 2038 } else { 2039 r.set(pts, SkToInt(count)); 2040 } 2041 SkRect storage; 2042 if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) { 2043 return; 2044 } 2045 bounds = &r; 2046 } 2047 2048 SkASSERT(pts != nullptr); 2049 2050 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 2051 2052 while (iter.next()) { 2053 iter.fDevice->drawPoints(mode, count, pts, looper.paint()); 2054 } 2055 2056 LOOPER_END 2057} 2058 2059static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) { 2060 return ((intptr_t)paint.getImageFilter() | 2061#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 2062 (intptr_t)canvas->getDrawFilter() | 2063#endif 2064 (intptr_t)paint.getLooper() ) != 0; 2065} 2066 2067void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { 2068 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 2069 if (paint.canComputeFastBounds()) { 2070 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream. 2071 // To prevent accidental rejecting at this stage, we have to sort it before we check. 2072 SkRect tmp(r); 2073 tmp.sort(); 2074 2075 SkRect storage; 2076 if (this->quickReject(paint.computeFastBounds(tmp, &storage))) { 2077 return; 2078 } 2079 } 2080 2081 if (needs_autodrawlooper(this, paint)) { 2082 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false) 2083 2084 while (iter.next()) { 2085 iter.fDevice->drawRect(r, looper.paint()); 2086 } 2087 2088 LOOPER_END 2089 } else { 2090 this->predrawNotify(&r, &paint, false); 2091 SkDrawIter iter(this); 2092 while (iter.next()) { 2093 iter.fDevice->drawRect(r, paint); 2094 } 2095 } 2096} 2097 2098void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { 2099 SkRect regionRect = SkRect::Make(region.getBounds()); 2100 if (paint.canComputeFastBounds()) { 2101 SkRect storage; 2102 if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) { 2103 return; 2104 } 2105 } 2106 2107 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, ®ionRect) 2108 2109 while (iter.next()) { 2110 iter.fDevice->drawRegion(region, looper.paint()); 2111 } 2112 2113 LOOPER_END 2114} 2115 2116void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 2117 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 2118 if (paint.canComputeFastBounds()) { 2119 SkRect storage; 2120 if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 2121 return; 2122 } 2123 } 2124 2125 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval) 2126 2127 while (iter.next()) { 2128 iter.fDevice->drawOval(oval, looper.paint()); 2129 } 2130 2131 LOOPER_END 2132} 2133 2134void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle, 2135 SkScalar sweepAngle, bool useCenter, 2136 const SkPaint& paint) { 2137 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2138 if (paint.canComputeFastBounds()) { 2139 SkRect storage; 2140 // Note we're using the entire oval as the bounds. 2141 if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 2142 return; 2143 } 2144 } 2145 2146 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval) 2147 2148 while (iter.next()) { 2149 iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint()); 2150 } 2151 2152 LOOPER_END 2153} 2154 2155void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 2156 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 2157 if (paint.canComputeFastBounds()) { 2158 SkRect storage; 2159 if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) { 2160 return; 2161 } 2162 } 2163 2164 if (rrect.isRect()) { 2165 // call the non-virtual version 2166 this->SkCanvas::drawRect(rrect.getBounds(), paint); 2167 return; 2168 } else if (rrect.isOval()) { 2169 // call the non-virtual version 2170 this->SkCanvas::drawOval(rrect.getBounds(), paint); 2171 return; 2172 } 2173 2174 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds()) 2175 2176 while (iter.next()) { 2177 iter.fDevice->drawRRect(rrect, looper.paint()); 2178 } 2179 2180 LOOPER_END 2181} 2182 2183void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 2184 if (paint.canComputeFastBounds()) { 2185 SkRect storage; 2186 if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) { 2187 return; 2188 } 2189 } 2190 2191 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds()) 2192 2193 while (iter.next()) { 2194 iter.fDevice->drawDRRect(outer, inner, looper.paint()); 2195 } 2196 2197 LOOPER_END 2198} 2199 2200void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 2201 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 2202 if (!path.isFinite()) { 2203 return; 2204 } 2205 2206 const SkRect& pathBounds = path.getBounds(); 2207 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 2208 SkRect storage; 2209 if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) { 2210 return; 2211 } 2212 } 2213 2214 if (pathBounds.width() <= 0 && pathBounds.height() <= 0) { 2215 if (path.isInverseFillType()) { 2216 this->internalDrawPaint(paint); 2217 return; 2218 } 2219 } 2220 2221 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds) 2222 2223 while (iter.next()) { 2224 iter.fDevice->drawPath(path, looper.paint()); 2225 } 2226 2227 LOOPER_END 2228} 2229 2230bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) { 2231 if (!paint.getImageFilter()) { 2232 return false; 2233 } 2234 2235 const SkMatrix& ctm = this->getTotalMatrix(); 2236 if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) { 2237 return false; 2238 } 2239 2240 // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds. 2241 // Once we can filter and the filter will return a result larger than itself, we should be 2242 // able to remove this constraint. 2243 // skbug.com/4526 2244 // 2245 SkPoint pt; 2246 ctm.mapXY(x, y, &pt); 2247 SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h); 2248 return ir.contains(fMCRec->fRasterClip.getBounds()); 2249} 2250 2251void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 2252 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 2253 SkRect bounds = SkRect::MakeXYWH(x, y, 2254 SkIntToScalar(image->width()), SkIntToScalar(image->height())); 2255 if (nullptr == paint || paint->canComputeFastBounds()) { 2256 SkRect tmp = bounds; 2257 if (paint) { 2258 paint->computeFastBounds(tmp, &tmp); 2259 } 2260 if (this->quickReject(tmp)) { 2261 return; 2262 } 2263 } 2264 2265 SkLazyPaint lazy; 2266 if (nullptr == paint) { 2267 paint = lazy.init(); 2268 } 2269 2270 sk_sp<SkSpecialImage> special; 2271 bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), 2272 *paint); 2273 if (drawAsSprite && paint->getImageFilter()) { 2274 special = this->getDevice()->makeSpecial(image); 2275 if (!special) { 2276 drawAsSprite = false; 2277 } 2278 } 2279 2280 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds) 2281 2282 while (iter.next()) { 2283 const SkPaint& pnt = looper.paint(); 2284 if (special) { 2285 SkPoint pt; 2286 iter.fDevice->ctm().mapXY(x, y, &pt); 2287 iter.fDevice->drawSpecial(special.get(), 2288 SkScalarRoundToInt(pt.fX), 2289 SkScalarRoundToInt(pt.fY), pnt); 2290 } else { 2291 iter.fDevice->drawImage(image, x, y, pnt); 2292 } 2293 } 2294 2295 LOOPER_END 2296} 2297 2298void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 2299 const SkPaint* paint, SrcRectConstraint constraint) { 2300 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 2301 if (nullptr == paint || paint->canComputeFastBounds()) { 2302 SkRect storage = dst; 2303 if (paint) { 2304 paint->computeFastBounds(dst, &storage); 2305 } 2306 if (this->quickReject(storage)) { 2307 return; 2308 } 2309 } 2310 SkLazyPaint lazy; 2311 if (nullptr == paint) { 2312 paint = lazy.init(); 2313 } 2314 2315 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2316 image->isOpaque()) 2317 2318 while (iter.next()) { 2319 iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint); 2320 } 2321 2322 LOOPER_END 2323} 2324 2325void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 2326 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 2327 SkDEBUGCODE(bitmap.validate();) 2328 2329 if (bitmap.drawsNothing()) { 2330 return; 2331 } 2332 2333 SkLazyPaint lazy; 2334 if (nullptr == paint) { 2335 paint = lazy.init(); 2336 } 2337 2338 SkRect bounds; 2339 bitmap.getBounds(&bounds); 2340 bounds.offset(x, y); 2341 bool canFastBounds = paint->canComputeFastBounds(); 2342 if (canFastBounds) { 2343 SkRect storage; 2344 if (this->quickReject(paint->computeFastBounds(bounds, &storage))) { 2345 return; 2346 } 2347 } 2348 2349 sk_sp<SkSpecialImage> special; 2350 bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), 2351 bitmap.height(), *paint); 2352 if (drawAsSprite && paint->getImageFilter()) { 2353 special = this->getDevice()->makeSpecial(bitmap); 2354 if (!special) { 2355 drawAsSprite = false; 2356 } 2357 } 2358 2359 const SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2360 2361 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds) 2362 2363 while (iter.next()) { 2364 const SkPaint& pnt = looper.paint(); 2365 if (special) { 2366 SkPoint pt; 2367 iter.fDevice->ctm().mapXY(x, y, &pt); 2368 iter.fDevice->drawSpecial(special.get(), 2369 SkScalarRoundToInt(pt.fX), 2370 SkScalarRoundToInt(pt.fY), pnt); 2371 } else { 2372 iter.fDevice->drawBitmap(bitmap, matrix, looper.paint()); 2373 } 2374 } 2375 2376 LOOPER_END 2377} 2378 2379// this one is non-virtual, so it can be called safely by other canvas apis 2380void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2381 const SkRect& dst, const SkPaint* paint, 2382 SrcRectConstraint constraint) { 2383 if (bitmap.drawsNothing() || dst.isEmpty()) { 2384 return; 2385 } 2386 2387 if (nullptr == paint || paint->canComputeFastBounds()) { 2388 SkRect storage; 2389 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2390 return; 2391 } 2392 } 2393 2394 SkLazyPaint lazy; 2395 if (nullptr == paint) { 2396 paint = lazy.init(); 2397 } 2398 2399 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2400 bitmap.isOpaque()) 2401 2402 while (iter.next()) { 2403 iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint); 2404 } 2405 2406 LOOPER_END 2407} 2408 2409void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2410 const SkPaint* paint, SrcRectConstraint constraint) { 2411 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 2412 SkDEBUGCODE(bitmap.validate();) 2413 this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint); 2414} 2415 2416void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 2417 const SkPaint* paint) { 2418 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()"); 2419 2420 if (nullptr == paint || paint->canComputeFastBounds()) { 2421 SkRect storage; 2422 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2423 return; 2424 } 2425 } 2426 2427 SkLazyPaint lazy; 2428 if (nullptr == paint) { 2429 paint = lazy.init(); 2430 } 2431 2432 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2433 2434 while (iter.next()) { 2435 iter.fDevice->drawImageNine(image, center, dst, looper.paint()); 2436 } 2437 2438 LOOPER_END 2439} 2440 2441void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2442 const SkPaint* paint) { 2443 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2444 SkDEBUGCODE(bitmap.validate();) 2445 2446 if (nullptr == paint || paint->canComputeFastBounds()) { 2447 SkRect storage; 2448 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2449 return; 2450 } 2451 } 2452 2453 SkLazyPaint lazy; 2454 if (nullptr == paint) { 2455 paint = lazy.init(); 2456 } 2457 2458 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2459 2460 while (iter.next()) { 2461 iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint()); 2462 } 2463 2464 LOOPER_END 2465} 2466 2467void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 2468 const SkPaint* paint) { 2469 if (nullptr == paint || paint->canComputeFastBounds()) { 2470 SkRect storage; 2471 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2472 return; 2473 } 2474 } 2475 2476 SkLazyPaint lazy; 2477 if (nullptr == paint) { 2478 paint = lazy.init(); 2479 } 2480 2481 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2482 2483 while (iter.next()) { 2484 iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint()); 2485 } 2486 2487 LOOPER_END 2488} 2489 2490void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, 2491 const SkRect& dst, const SkPaint* paint) { 2492 if (nullptr == paint || paint->canComputeFastBounds()) { 2493 SkRect storage; 2494 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2495 return; 2496 } 2497 } 2498 2499 SkLazyPaint lazy; 2500 if (nullptr == paint) { 2501 paint = lazy.init(); 2502 } 2503 2504 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2505 2506 while (iter.next()) { 2507 iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint()); 2508 } 2509 2510 LOOPER_END 2511} 2512 2513class SkDeviceFilteredPaint { 2514public: 2515 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2516 uint32_t filteredFlags = device->filterTextFlags(paint); 2517 if (filteredFlags != paint.getFlags()) { 2518 SkPaint* newPaint = fLazy.set(paint); 2519 newPaint->setFlags(filteredFlags); 2520 fPaint = newPaint; 2521 } else { 2522 fPaint = &paint; 2523 } 2524 } 2525 2526 const SkPaint& paint() const { return *fPaint; } 2527 2528private: 2529 const SkPaint* fPaint; 2530 SkLazyPaint fLazy; 2531}; 2532 2533void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2534 const SkPaint& paint) { 2535 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2536 2537 while (iter.next()) { 2538 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2539 iter.fDevice->drawText(text, byteLength, x, y, dfp.paint()); 2540 } 2541 2542 LOOPER_END 2543} 2544 2545void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2546 const SkPaint& paint) { 2547 SkPoint textOffset = SkPoint::Make(0, 0); 2548 2549 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2550 2551 while (iter.next()) { 2552 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2553 iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset, 2554 dfp.paint()); 2555 } 2556 2557 LOOPER_END 2558} 2559 2560void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2561 SkScalar constY, const SkPaint& paint) { 2562 2563 SkPoint textOffset = SkPoint::Make(0, constY); 2564 2565 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2566 2567 while (iter.next()) { 2568 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2569 iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset, 2570 dfp.paint()); 2571 } 2572 2573 LOOPER_END 2574} 2575 2576void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2577 const SkMatrix* matrix, const SkPaint& paint) { 2578 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2579 2580 while (iter.next()) { 2581 iter.fDevice->drawTextOnPath(text, byteLength, path, 2582 matrix, looper.paint()); 2583 } 2584 2585 LOOPER_END 2586} 2587 2588void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 2589 const SkRect* cullRect, const SkPaint& paint) { 2590 if (cullRect && this->quickReject(*cullRect)) { 2591 return; 2592 } 2593 2594 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2595 2596 while (iter.next()) { 2597 iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint()); 2598 } 2599 2600 LOOPER_END 2601} 2602 2603void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2604 const SkPaint& paint) { 2605 2606 SkRect storage; 2607 const SkRect* bounds = nullptr; 2608 if (paint.canComputeFastBounds()) { 2609 storage = blob->bounds().makeOffset(x, y); 2610 SkRect tmp; 2611 if (this->quickReject(paint.computeFastBounds(storage, &tmp))) { 2612 return; 2613 } 2614 bounds = &storage; 2615 } 2616 2617 // We cannot filter in the looper as we normally do, because the paint is 2618 // incomplete at this point (text-related attributes are embedded within blob run paints). 2619 SkDrawFilter* drawFilter = fMCRec->fFilter; 2620 fMCRec->fFilter = nullptr; 2621 2622 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2623 2624 while (iter.next()) { 2625 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2626 iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter); 2627 } 2628 2629 LOOPER_END 2630 2631 fMCRec->fFilter = drawFilter; 2632} 2633 2634// These will become non-virtual, so they always call the (virtual) onDraw... method 2635void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2636 const SkPaint& paint) { 2637 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2638 if (byteLength) { 2639 this->onDrawText(text, byteLength, x, y, paint); 2640 } 2641} 2642void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2643 const SkPaint& paint) { 2644 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2645 if (byteLength) { 2646 this->onDrawPosText(text, byteLength, pos, paint); 2647 } 2648} 2649void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2650 SkScalar constY, const SkPaint& paint) { 2651 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2652 if (byteLength) { 2653 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2654 } 2655} 2656void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2657 const SkMatrix* matrix, const SkPaint& paint) { 2658 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2659 if (byteLength) { 2660 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2661 } 2662} 2663void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 2664 const SkRect* cullRect, const SkPaint& paint) { 2665 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()"); 2666 if (byteLength) { 2667 this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint); 2668 } 2669} 2670void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2671 const SkPaint& paint) { 2672 RETURN_ON_NULL(blob); 2673 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2674 this->onDrawTextBlob(blob, x, y, paint); 2675} 2676 2677void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode, 2678 const SkPaint& paint) { 2679 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2680 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2681 2682 while (iter.next()) { 2683 // In the common case of one iteration we could std::move vertices here. 2684 iter.fDevice->drawVertices(vertices, bmode, looper.paint()); 2685 } 2686 2687 LOOPER_END 2688} 2689 2690void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2691 const SkPoint texCoords[4], SkBlendMode bmode, 2692 const SkPaint& paint) { 2693 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2694 if (nullptr == cubics) { 2695 return; 2696 } 2697 2698 this->onDrawPatch(cubics, colors, texCoords, bmode, paint); 2699} 2700 2701void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2702 const SkPoint texCoords[4], SkBlendMode bmode, 2703 const SkPaint& paint) { 2704 // Since a patch is always within the convex hull of the control points, we discard it when its 2705 // bounding rectangle is completely outside the current clip. 2706 SkRect bounds; 2707 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2708 if (this->quickReject(bounds)) { 2709 return; 2710 } 2711 2712 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2713 2714 while (iter.next()) { 2715 iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint); 2716 } 2717 2718 LOOPER_END 2719} 2720 2721void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) { 2722 RETURN_ON_NULL(dr); 2723 if (x || y) { 2724 SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2725 this->onDrawDrawable(dr, &matrix); 2726 } else { 2727 this->onDrawDrawable(dr, nullptr); 2728 } 2729} 2730 2731void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2732 RETURN_ON_NULL(dr); 2733 if (matrix && matrix->isIdentity()) { 2734 matrix = nullptr; 2735 } 2736 this->onDrawDrawable(dr, matrix); 2737} 2738 2739void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2740 // drawable bounds are no longer reliable (e.g. android displaylist) 2741 // so don't use them for quick-reject 2742 dr->draw(this, matrix); 2743} 2744 2745void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2746 const SkColor colors[], int count, SkBlendMode bmode, 2747 const SkRect* cull, const SkPaint* paint) { 2748 if (cull && this->quickReject(*cull)) { 2749 return; 2750 } 2751 2752 SkPaint pnt; 2753 if (paint) { 2754 pnt = *paint; 2755 } 2756 2757 LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr) 2758 while (iter.next()) { 2759 iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt); 2760 } 2761 LOOPER_END 2762} 2763 2764void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { 2765 SkASSERT(key); 2766 2767 SkPaint paint; 2768 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr) 2769 while (iter.next()) { 2770 iter.fDevice->drawAnnotation(rect, key, value); 2771 } 2772 LOOPER_END 2773} 2774 2775////////////////////////////////////////////////////////////////////////////// 2776// These methods are NOT virtual, and therefore must call back into virtual 2777// methods, rather than actually drawing themselves. 2778////////////////////////////////////////////////////////////////////////////// 2779 2780#ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS 2781void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode) { 2782 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2783 SkPaint paint; 2784 2785 paint.setARGB(a, r, g, b); 2786 paint.setBlendMode(mode); 2787 this->drawPaint(paint); 2788} 2789#endif 2790 2791void SkCanvas::drawColor(SkColor c, SkBlendMode mode) { 2792 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2793 SkPaint paint; 2794 2795 paint.setColor(c); 2796 paint.setBlendMode(mode); 2797 this->drawPaint(paint); 2798} 2799 2800void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2801 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2802 const SkPoint pt = { x, y }; 2803 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2804} 2805 2806#ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS 2807void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2808 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2809 SkPoint pt; 2810 SkPaint paint; 2811 2812 pt.set(x, y); 2813 paint.setColor(color); 2814 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2815} 2816#endif 2817 2818void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) { 2819 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 2820 SkPoint pts[2]; 2821 2822 pts[0].set(x0, y0); 2823 pts[1].set(x1, y1); 2824 this->drawPoints(kLines_PointMode, 2, pts, paint); 2825} 2826 2827#ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS 2828void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2829 SkScalar right, SkScalar bottom, 2830 const SkPaint& paint) { 2831 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 2832 SkRect r; 2833 2834 r.set(left, top, right, bottom); 2835 this->drawRect(r, paint); 2836} 2837#endif 2838 2839void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) { 2840 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 2841 if (radius < 0) { 2842 radius = 0; 2843 } 2844 2845 SkRect r; 2846 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2847 this->drawOval(r, paint); 2848} 2849 2850void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2851 const SkPaint& paint) { 2852 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 2853 if (rx > 0 && ry > 0) { 2854 SkRRect rrect; 2855 rrect.setRectXY(r, rx, ry); 2856 this->drawRRect(rrect, paint); 2857 } else { 2858 this->drawRect(r, paint); 2859 } 2860} 2861 2862void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2863 SkScalar sweepAngle, bool useCenter, 2864 const SkPaint& paint) { 2865 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2866 if (oval.isEmpty() || !sweepAngle) { 2867 return; 2868 } 2869 this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint); 2870} 2871 2872void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2873 const SkPath& path, SkScalar hOffset, 2874 SkScalar vOffset, const SkPaint& paint) { 2875 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 2876 SkMatrix matrix; 2877 2878 matrix.setTranslate(hOffset, vOffset); 2879 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2880} 2881 2882/////////////////////////////////////////////////////////////////////////////// 2883 2884/** 2885 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 2886 * against the playback cost of recursing into the subpicture to get at its actual ops. 2887 * 2888 * For now we pick a conservatively small value, though measurement (and other heuristics like 2889 * the type of ops contained) may justify changing this value. 2890 */ 2891#define kMaxPictureOpsToUnrollInsteadOfRef 1 2892 2893void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2894 RETURN_ON_NULL(picture); 2895 2896 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 2897 if (matrix && matrix->isIdentity()) { 2898 matrix = nullptr; 2899 } 2900 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { 2901 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2902 picture->playback(this); 2903 } else { 2904 this->onDrawPicture(picture, matrix, paint); 2905 } 2906} 2907 2908void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2909 const SkPaint* paint) { 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 picture->playback(this); 2925} 2926 2927#ifdef SK_EXPERIMENTAL_SHADOWING 2928void SkCanvas::drawShadowedPicture(const SkPicture* picture, 2929 const SkMatrix* matrix, 2930 const SkPaint* paint, 2931 const SkShadowParams& params) { 2932 RETURN_ON_NULL(picture); 2933 2934 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()"); 2935 2936 this->onDrawShadowedPicture(picture, matrix, paint, params); 2937} 2938 2939void SkCanvas::onDrawShadowedPicture(const SkPicture* picture, 2940 const SkMatrix* matrix, 2941 const SkPaint* paint, 2942 const SkShadowParams& params) { 2943 if (!paint || paint->canComputeFastBounds()) { 2944 SkRect bounds = picture->cullRect(); 2945 if (paint) { 2946 paint->computeFastBounds(bounds, &bounds); 2947 } 2948 if (matrix) { 2949 matrix->mapRect(&bounds); 2950 } 2951 if (this->quickReject(bounds)) { 2952 return; 2953 } 2954 } 2955 2956 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2957 2958 sk_sp<SkImage> povDepthMap; 2959 sk_sp<SkImage> diffuseMap; 2960 2961 // povDepthMap 2962 { 2963 SkLights::Builder builder; 2964 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f), 2965 SkVector3::Make(0.0f, 0.0f, 1.0f))); 2966 sk_sp<SkLights> povLight = builder.finish(); 2967 2968 SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(), 2969 picture->cullRect().height(), 2970 kBGRA_8888_SkColorType, 2971 kOpaque_SkAlphaType); 2972 2973 // Create a new surface (that matches the backend of canvas) 2974 // to create the povDepthMap 2975 sk_sp<SkSurface> surf(this->makeSurface(info)); 2976 2977 // Wrap another SPFCanvas around the surface 2978 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = 2979 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); 2980 2981 // set the depth map canvas to have the light as the user's POV 2982 depthMapCanvas->setLights(std::move(povLight)); 2983 2984 depthMapCanvas->drawPicture(picture); 2985 povDepthMap = surf->makeImageSnapshot(); 2986 } 2987 2988 // diffuseMap 2989 { 2990 SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(), 2991 picture->cullRect().height(), 2992 kBGRA_8888_SkColorType, 2993 kOpaque_SkAlphaType); 2994 2995 sk_sp<SkSurface> surf(this->makeSurface(info)); 2996 surf->getCanvas()->drawPicture(picture); 2997 2998 diffuseMap = surf->makeImageSnapshot(); 2999 } 3000 3001 sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode, 3002 SkShader::kClamp_TileMode); 3003 sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode, 3004 SkShader::kClamp_TileMode); 3005 3006 // TODO: pass the depth to the shader in vertices, or uniforms 3007 // so we don't have to render depth and color separately 3008 for (int i = 0; i < fLights->numLights(); ++i) { 3009 // skip over ambient lights; they don't cast shadows 3010 // lights that have shadow maps do not need updating (because lights are immutable) 3011 sk_sp<SkImage> depthMap; 3012 SkISize shMapSize; 3013 3014 if (fLights->light(i).getShadowMap() != nullptr) { 3015 continue; 3016 } 3017 3018 if (fLights->light(i).isRadial()) { 3019 shMapSize.fHeight = 1; 3020 shMapSize.fWidth = (int) picture->cullRect().width(); 3021 3022 SkImageInfo info = SkImageInfo::Make(diffuseMap->width(), 1, 3023 kBGRA_8888_SkColorType, 3024 kOpaque_SkAlphaType); 3025 3026 // Create new surface (that matches the backend of canvas) 3027 // for each shadow map 3028 sk_sp<SkSurface> surf(this->makeSurface(info)); 3029 3030 // Wrap another SPFCanvas around the surface 3031 SkCanvas* depthMapCanvas = surf->getCanvas(); 3032 3033 SkLights::Builder builder; 3034 builder.add(fLights->light(i)); 3035 sk_sp<SkLights> curLight = builder.finish(); 3036 3037 sk_sp<SkShader> shadowMapShader; 3038 shadowMapShader = SkRadialShadowMapShader::Make( 3039 povDepthShader, curLight, 3040 (int) picture->cullRect().width(), 3041 (int) picture->cullRect().height()); 3042 3043 SkPaint shadowMapPaint; 3044 shadowMapPaint.setShader(std::move(shadowMapShader)); 3045 3046 depthMapCanvas->setLights(curLight); 3047 3048 depthMapCanvas->drawRect(SkRect::MakeIWH(diffuseMap->width(), 3049 diffuseMap->height()), 3050 shadowMapPaint); 3051 3052 depthMap = surf->makeImageSnapshot(); 3053 3054 } else { 3055 // TODO: compute the correct size of the depth map from the light properties 3056 // TODO: maybe add a kDepth_8_SkColorType 3057 // TODO: find actual max depth of picture 3058 shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize( 3059 fLights->light(i), 255, 3060 (int) picture->cullRect().width(), 3061 (int) picture->cullRect().height()); 3062 3063 SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight, 3064 kBGRA_8888_SkColorType, 3065 kOpaque_SkAlphaType); 3066 3067 // Create a new surface (that matches the backend of canvas) 3068 // for each shadow map 3069 sk_sp<SkSurface> surf(this->makeSurface(info)); 3070 3071 // Wrap another SPFCanvas around the surface 3072 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = 3073 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); 3074 depthMapCanvas->setShadowParams(params); 3075 3076 // set the depth map canvas to have the light we're drawing. 3077 SkLights::Builder builder; 3078 builder.add(fLights->light(i)); 3079 sk_sp<SkLights> curLight = builder.finish(); 3080 depthMapCanvas->setLights(std::move(curLight)); 3081 3082 depthMapCanvas->drawPicture(picture); 3083 depthMap = surf->makeImageSnapshot(); 3084 } 3085 3086 if (params.fType == SkShadowParams::kNoBlur_ShadowType) { 3087 fLights->light(i).setShadowMap(std::move(depthMap)); 3088 } else if (params.fType == SkShadowParams::kVariance_ShadowType) { 3089 // we blur the variance map 3090 SkPaint blurPaint; 3091 blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius, 3092 params.fShadowRadius, nullptr)); 3093 3094 SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight, 3095 kBGRA_8888_SkColorType, 3096 kOpaque_SkAlphaType); 3097 3098 sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo)); 3099 3100 blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint); 3101 3102 fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot()); 3103 } 3104 } 3105 3106 SkPaint shadowPaint; 3107 sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader), 3108 std::move(diffuseShader), 3109 fLights, 3110 diffuseMap->width(), 3111 diffuseMap->height(), 3112 params); 3113 3114 shadowPaint.setShader(shadowShader); 3115 3116 this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint); 3117} 3118#endif 3119 3120/////////////////////////////////////////////////////////////////////////////// 3121/////////////////////////////////////////////////////////////////////////////// 3122 3123SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) { 3124 static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small"); 3125 3126 SkASSERT(canvas); 3127 3128 fImpl = new (fStorage) SkDrawIter(canvas); 3129 fDone = !fImpl->next(); 3130} 3131 3132SkCanvas::LayerIter::~LayerIter() { 3133 fImpl->~SkDrawIter(); 3134} 3135 3136void SkCanvas::LayerIter::next() { 3137 fDone = !fImpl->next(); 3138} 3139 3140SkBaseDevice* SkCanvas::LayerIter::device() const { 3141 return fImpl->fDevice; 3142} 3143 3144const SkMatrix& SkCanvas::LayerIter::matrix() const { 3145 return fImpl->fDevice->ctm(); 3146} 3147 3148const SkPaint& SkCanvas::LayerIter::paint() const { 3149 const SkPaint* paint = fImpl->getPaint(); 3150 if (nullptr == paint) { 3151 paint = &fDefaultPaint; 3152 } 3153 return *paint; 3154} 3155 3156void SkCanvas::LayerIter::clip(SkRegion* rgn) const { 3157 return fImpl->fDevice->onAsRgnClip(rgn); 3158} 3159 3160int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 3161int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 3162 3163/////////////////////////////////////////////////////////////////////////////// 3164 3165SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 3166 3167/////////////////////////////////////////////////////////////////////////////// 3168 3169static bool supported_for_raster_canvas(const SkImageInfo& info) { 3170 switch (info.alphaType()) { 3171 case kPremul_SkAlphaType: 3172 case kOpaque_SkAlphaType: 3173 break; 3174 default: 3175 return false; 3176 } 3177 3178 switch (info.colorType()) { 3179 case kAlpha_8_SkColorType: 3180 case kRGB_565_SkColorType: 3181 case kN32_SkColorType: 3182 case kRGBA_F16_SkColorType: 3183 break; 3184 default: 3185 return false; 3186 } 3187 3188 return true; 3189} 3190 3191std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels, 3192 size_t rowBytes) { 3193 if (!supported_for_raster_canvas(info)) { 3194 return nullptr; 3195 } 3196 3197 SkBitmap bitmap; 3198 if (!bitmap.installPixels(info, pixels, rowBytes)) { 3199 return nullptr; 3200 } 3201 return skstd::make_unique<SkCanvas>(bitmap); 3202} 3203 3204/////////////////////////////////////////////////////////////////////////////// 3205 3206SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 3207 const SkPaint* paint, const SkRect& bounds) 3208 : fCanvas(canvas) 3209 , fSaveCount(canvas->getSaveCount()) 3210{ 3211 if (paint) { 3212 SkRect newBounds = bounds; 3213 if (matrix) { 3214 matrix->mapRect(&newBounds); 3215 } 3216 canvas->saveLayer(&newBounds, paint); 3217 } else if (matrix) { 3218 canvas->save(); 3219 } 3220 3221 if (matrix) { 3222 canvas->concat(*matrix); 3223 } 3224} 3225 3226SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 3227 fCanvas->restoreToCount(fSaveCount); 3228} 3229 3230/////////////////////////////////////////////////////////////////////////////// 3231 3232SkNoDrawCanvas::SkNoDrawCanvas(int width, int height) 3233 : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {} 3234 3235SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds) 3236 : INHERITED(bounds, kConservativeRasterClip_InitFlag) {} 3237 3238SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { 3239 (void)this->INHERITED::getSaveLayerStrategy(rec); 3240 return kNoLayer_SaveLayerStrategy; 3241} 3242 3243/////////////////////////////////////////////////////////////////////////////// 3244 3245static_assert((int)SkRegion::kDifference_Op == (int)kDifference_SkClipOp, ""); 3246static_assert((int)SkRegion::kIntersect_Op == (int)kIntersect_SkClipOp, ""); 3247static_assert((int)SkRegion::kUnion_Op == (int)kUnion_SkClipOp, ""); 3248static_assert((int)SkRegion::kXOR_Op == (int)kXOR_SkClipOp, ""); 3249static_assert((int)SkRegion::kReverseDifference_Op == (int)kReverseDifference_SkClipOp, ""); 3250static_assert((int)SkRegion::kReplace_Op == (int)kReplace_SkClipOp, ""); 3251 3252/////////////////////////////////////////////////////////////////////////////////////////////////// 3253 3254SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const { 3255 if (fAllocator && fMCRec->fTopLayer->fDevice) { 3256 const SkBaseDevice* dev = fMCRec->fTopLayer->fDevice; 3257 SkRasterHandleAllocator::Handle handle = dev->getRasterHandle(); 3258 SkIPoint origin = dev->getOrigin(); 3259 SkMatrix ctm = this->getTotalMatrix(); 3260 ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y())); 3261 3262 SkIRect clip = fMCRec->fRasterClip.getBounds(); 3263 clip.offset(-origin.x(), -origin.y()); 3264 if (!clip.intersect(0, 0, dev->width(), dev->height())) { 3265 clip.setEmpty(); 3266 } 3267 3268 fAllocator->updateHandle(handle, ctm, clip); 3269 return handle; 3270 } 3271 return nullptr; 3272} 3273 3274static bool install(SkBitmap* bm, const SkImageInfo& info, 3275 const SkRasterHandleAllocator::Rec& rec) { 3276 return bm->installPixels(info, rec.fPixels, rec.fRowBytes, nullptr, 3277 rec.fReleaseProc, rec.fReleaseCtx); 3278} 3279 3280SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info, 3281 SkBitmap* bm) { 3282 SkRasterHandleAllocator::Rec rec; 3283 if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) { 3284 return nullptr; 3285 } 3286 return rec.fHandle; 3287} 3288 3289std::unique_ptr<SkCanvas> 3290SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc, 3291 const SkImageInfo& info, const Rec* rec) { 3292 if (!alloc || !supported_for_raster_canvas(info)) { 3293 return nullptr; 3294 } 3295 3296 SkBitmap bm; 3297 Handle hndl; 3298 3299 if (rec) { 3300 hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr; 3301 } else { 3302 hndl = alloc->allocBitmap(info, &bm); 3303 } 3304 return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr; 3305} 3306