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