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