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