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