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