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