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