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