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