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