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