SkCanvas.cpp revision e6f5d5623160a69e1585f5121a3695092327dfe0
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::onDrawOval(const SkRect& oval, const SkPaint& paint) { 2254 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 2255 SkRect storage; 2256 const SkRect* bounds = nullptr; 2257 if (paint.canComputeFastBounds()) { 2258 if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 2259 return; 2260 } 2261 bounds = &oval; 2262 } 2263 2264 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 2265 2266 while (iter.next()) { 2267 iter.fDevice->drawOval(iter, oval, looper.paint()); 2268 } 2269 2270 LOOPER_END 2271} 2272 2273void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle, 2274 SkScalar sweepAngle, bool useCenter, 2275 const SkPaint& paint) { 2276 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2277 const SkRect* bounds = nullptr; 2278 if (paint.canComputeFastBounds()) { 2279 SkRect storage; 2280 // Note we're using the entire oval as the bounds. 2281 if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 2282 return; 2283 } 2284 bounds = &oval; 2285 } 2286 2287 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 2288 2289 while (iter.next()) { 2290 iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint()); 2291 } 2292 2293 LOOPER_END 2294} 2295 2296void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 2297 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 2298 SkRect storage; 2299 const SkRect* bounds = nullptr; 2300 if (paint.canComputeFastBounds()) { 2301 if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) { 2302 return; 2303 } 2304 bounds = &rrect.getBounds(); 2305 } 2306 2307 if (rrect.isRect()) { 2308 // call the non-virtual version 2309 this->SkCanvas::drawRect(rrect.getBounds(), paint); 2310 return; 2311 } else if (rrect.isOval()) { 2312 // call the non-virtual version 2313 this->SkCanvas::drawOval(rrect.getBounds(), paint); 2314 return; 2315 } 2316 2317 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 2318 2319 while (iter.next()) { 2320 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 2321 } 2322 2323 LOOPER_END 2324} 2325 2326void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 2327 const SkPaint& paint) { 2328 SkRect storage; 2329 const SkRect* bounds = nullptr; 2330 if (paint.canComputeFastBounds()) { 2331 if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) { 2332 return; 2333 } 2334 bounds = &outer.getBounds(); 2335 } 2336 2337 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 2338 2339 while (iter.next()) { 2340 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 2341 } 2342 2343 LOOPER_END 2344} 2345 2346void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 2347 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 2348 if (!path.isFinite()) { 2349 return; 2350 } 2351 2352 SkRect storage; 2353 const SkRect* bounds = nullptr; 2354 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 2355 const SkRect& pathBounds = path.getBounds(); 2356 if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) { 2357 return; 2358 } 2359 bounds = &pathBounds; 2360 } 2361 2362 const SkRect& r = path.getBounds(); 2363 if (r.width() <= 0 && r.height() <= 0) { 2364 if (path.isInverseFillType()) { 2365 this->internalDrawPaint(paint); 2366 return; 2367 } 2368 } 2369 2370 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 2371 2372 while (iter.next()) { 2373 iter.fDevice->drawPath(iter, path, looper.paint()); 2374 } 2375 2376 LOOPER_END 2377} 2378 2379bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) { 2380 if (!paint.getImageFilter()) { 2381 return false; 2382 } 2383 2384 const SkMatrix& ctm = this->getTotalMatrix(); 2385 if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) { 2386 return false; 2387 } 2388 2389 // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds. 2390 // Once we can filter and the filter will return a result larger than itself, we should be 2391 // able to remove this constraint. 2392 // skbug.com/4526 2393 // 2394 SkPoint pt; 2395 ctm.mapXY(x, y, &pt); 2396 SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h); 2397 return ir.contains(fMCRec->fRasterClip.getBounds()); 2398} 2399 2400void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 2401 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 2402 SkRect bounds = SkRect::MakeXYWH(x, y, 2403 SkIntToScalar(image->width()), SkIntToScalar(image->height())); 2404 if (nullptr == paint || paint->canComputeFastBounds()) { 2405 SkRect tmp = bounds; 2406 if (paint) { 2407 paint->computeFastBounds(tmp, &tmp); 2408 } 2409 if (this->quickReject(tmp)) { 2410 return; 2411 } 2412 } 2413 2414 SkLazyPaint lazy; 2415 if (nullptr == paint) { 2416 paint = lazy.init(); 2417 } 2418 2419 sk_sp<SkSpecialImage> special; 2420 bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), 2421 *paint); 2422 if (drawAsSprite && paint->getImageFilter()) { 2423 special = this->getDevice()->makeSpecial(image); 2424 if (!special) { 2425 drawAsSprite = false; 2426 } 2427 } 2428 2429 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds) 2430 2431 while (iter.next()) { 2432 const SkPaint& pnt = looper.paint(); 2433 if (special) { 2434 SkPoint pt; 2435 iter.fMatrix->mapXY(x, y, &pt); 2436 iter.fDevice->drawSpecial(iter, special.get(), 2437 SkScalarRoundToInt(pt.fX), 2438 SkScalarRoundToInt(pt.fY), pnt); 2439 } else { 2440 iter.fDevice->drawImage(iter, image, x, y, pnt); 2441 } 2442 } 2443 2444 LOOPER_END 2445} 2446 2447void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 2448 const SkPaint* paint, SrcRectConstraint constraint) { 2449 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 2450 if (nullptr == paint || paint->canComputeFastBounds()) { 2451 SkRect storage = dst; 2452 if (paint) { 2453 paint->computeFastBounds(dst, &storage); 2454 } 2455 if (this->quickReject(storage)) { 2456 return; 2457 } 2458 } 2459 SkLazyPaint lazy; 2460 if (nullptr == paint) { 2461 paint = lazy.init(); 2462 } 2463 2464 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2465 image->isOpaque()) 2466 2467 while (iter.next()) { 2468 iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint); 2469 } 2470 2471 LOOPER_END 2472} 2473 2474void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 2475 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 2476 SkDEBUGCODE(bitmap.validate();) 2477 2478 if (bitmap.drawsNothing()) { 2479 return; 2480 } 2481 2482 SkLazyPaint lazy; 2483 if (nullptr == paint) { 2484 paint = lazy.init(); 2485 } 2486 2487 const SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2488 2489 SkRect storage; 2490 const SkRect* bounds = nullptr; 2491 if (paint->canComputeFastBounds()) { 2492 bitmap.getBounds(&storage); 2493 matrix.mapRect(&storage); 2494 SkRect tmp = storage; 2495 if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) { 2496 return; 2497 } 2498 bounds = &storage; 2499 } 2500 2501 sk_sp<SkSpecialImage> special; 2502 bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(), 2503 *paint); 2504 if (drawAsSprite && paint->getImageFilter()) { 2505 special = this->getDevice()->makeSpecial(bitmap); 2506 if (!special) { 2507 drawAsSprite = false; 2508 } 2509 } 2510 2511 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds) 2512 2513 while (iter.next()) { 2514 const SkPaint& pnt = looper.paint(); 2515 if (special) { 2516 SkPoint pt; 2517 iter.fMatrix->mapXY(x, y, &pt); 2518 iter.fDevice->drawSpecial(iter, special.get(), 2519 SkScalarRoundToInt(pt.fX), 2520 SkScalarRoundToInt(pt.fY), pnt); 2521 } else { 2522 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 2523 } 2524 } 2525 2526 LOOPER_END 2527} 2528 2529// this one is non-virtual, so it can be called safely by other canvas apis 2530void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2531 const SkRect& dst, const SkPaint* paint, 2532 SrcRectConstraint constraint) { 2533 if (bitmap.drawsNothing() || dst.isEmpty()) { 2534 return; 2535 } 2536 2537 if (nullptr == paint || paint->canComputeFastBounds()) { 2538 SkRect storage; 2539 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2540 return; 2541 } 2542 } 2543 2544 SkLazyPaint lazy; 2545 if (nullptr == paint) { 2546 paint = lazy.init(); 2547 } 2548 2549 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2550 bitmap.isOpaque()) 2551 2552 while (iter.next()) { 2553 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint); 2554 } 2555 2556 LOOPER_END 2557} 2558 2559void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2560 const SkPaint* paint, SrcRectConstraint constraint) { 2561 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 2562 SkDEBUGCODE(bitmap.validate();) 2563 this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint); 2564} 2565 2566void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 2567 const SkPaint* paint) { 2568 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()"); 2569 2570 if (nullptr == paint || paint->canComputeFastBounds()) { 2571 SkRect storage; 2572 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2573 return; 2574 } 2575 } 2576 2577 SkLazyPaint lazy; 2578 if (nullptr == paint) { 2579 paint = lazy.init(); 2580 } 2581 2582 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2583 2584 while (iter.next()) { 2585 iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint()); 2586 } 2587 2588 LOOPER_END 2589} 2590 2591void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2592 const SkPaint* paint) { 2593 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2594 SkDEBUGCODE(bitmap.validate();) 2595 2596 if (nullptr == paint || paint->canComputeFastBounds()) { 2597 SkRect storage; 2598 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2599 return; 2600 } 2601 } 2602 2603 SkLazyPaint lazy; 2604 if (nullptr == paint) { 2605 paint = lazy.init(); 2606 } 2607 2608 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2609 2610 while (iter.next()) { 2611 iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint()); 2612 } 2613 2614 LOOPER_END 2615} 2616 2617void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 2618 const SkPaint* paint) { 2619 if (nullptr == paint || paint->canComputeFastBounds()) { 2620 SkRect storage; 2621 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2622 return; 2623 } 2624 } 2625 2626 SkLazyPaint lazy; 2627 if (nullptr == paint) { 2628 paint = lazy.init(); 2629 } 2630 2631 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2632 2633 while (iter.next()) { 2634 iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint()); 2635 } 2636 2637 LOOPER_END 2638} 2639 2640void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, 2641 const SkRect& dst, const SkPaint* paint) { 2642 if (nullptr == paint || paint->canComputeFastBounds()) { 2643 SkRect storage; 2644 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2645 return; 2646 } 2647 } 2648 2649 SkLazyPaint lazy; 2650 if (nullptr == paint) { 2651 paint = lazy.init(); 2652 } 2653 2654 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2655 2656 while (iter.next()) { 2657 iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint()); 2658 } 2659 2660 LOOPER_END 2661} 2662 2663class SkDeviceFilteredPaint { 2664public: 2665 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2666 uint32_t filteredFlags = device->filterTextFlags(paint); 2667 if (filteredFlags != paint.getFlags()) { 2668 SkPaint* newPaint = fLazy.set(paint); 2669 newPaint->setFlags(filteredFlags); 2670 fPaint = newPaint; 2671 } else { 2672 fPaint = &paint; 2673 } 2674 } 2675 2676 const SkPaint& paint() const { return *fPaint; } 2677 2678private: 2679 const SkPaint* fPaint; 2680 SkLazyPaint fLazy; 2681}; 2682 2683void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2684 const SkRect& r, SkScalar textSize) { 2685 if (paint.getStyle() == SkPaint::kFill_Style) { 2686 draw.fDevice->drawRect(draw, r, paint); 2687 } else { 2688 SkPaint p(paint); 2689 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2690 draw.fDevice->drawRect(draw, r, p); 2691 } 2692} 2693 2694void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2695 const char text[], size_t byteLength, 2696 SkScalar x, SkScalar y) { 2697 SkASSERT(byteLength == 0 || text != nullptr); 2698 2699 // nothing to draw 2700 if (text == nullptr || byteLength == 0 || 2701 draw.fRC->isEmpty() || 2702 (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) { 2703 return; 2704 } 2705 2706 SkScalar width = 0; 2707 SkPoint start; 2708 2709 start.set(0, 0); // to avoid warning 2710 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2711 SkPaint::kStrikeThruText_Flag)) { 2712 width = paint.measureText(text, byteLength); 2713 2714 SkScalar offsetX = 0; 2715 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2716 offsetX = SkScalarHalf(width); 2717 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2718 offsetX = width; 2719 } 2720 start.set(x - offsetX, y); 2721 } 2722 2723 if (0 == width) { 2724 return; 2725 } 2726 2727 uint32_t flags = paint.getFlags(); 2728 2729 if (flags & (SkPaint::kUnderlineText_Flag | 2730 SkPaint::kStrikeThruText_Flag)) { 2731 SkScalar textSize = paint.getTextSize(); 2732 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2733 SkRect r; 2734 2735 r.fLeft = start.fX; 2736 r.fRight = start.fX + width; 2737 2738 if (flags & SkPaint::kUnderlineText_Flag) { 2739 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2740 start.fY); 2741 r.fTop = offset; 2742 r.fBottom = offset + height; 2743 DrawRect(draw, paint, r, 1); 2744 } 2745 if (flags & SkPaint::kStrikeThruText_Flag) { 2746 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2747 start.fY); 2748 r.fTop = offset; 2749 r.fBottom = offset + height; 2750 DrawRect(draw, paint, r, 1); 2751 } 2752 } 2753} 2754 2755void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2756 const SkPaint& paint) { 2757 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2758 2759 while (iter.next()) { 2760 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2761 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2762 DrawTextDecorations(iter, dfp.paint(), 2763 static_cast<const char*>(text), byteLength, x, y); 2764 } 2765 2766 LOOPER_END 2767} 2768 2769void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2770 const SkPaint& paint) { 2771 SkPoint textOffset = SkPoint::Make(0, 0); 2772 2773 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2774 2775 while (iter.next()) { 2776 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2777 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2778 dfp.paint()); 2779 } 2780 2781 LOOPER_END 2782} 2783 2784void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2785 SkScalar constY, const SkPaint& paint) { 2786 2787 SkPoint textOffset = SkPoint::Make(0, constY); 2788 2789 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2790 2791 while (iter.next()) { 2792 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2793 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2794 dfp.paint()); 2795 } 2796 2797 LOOPER_END 2798} 2799 2800void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2801 const SkMatrix* matrix, const SkPaint& paint) { 2802 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2803 2804 while (iter.next()) { 2805 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2806 matrix, looper.paint()); 2807 } 2808 2809 LOOPER_END 2810} 2811 2812void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 2813 const SkRect* cullRect, const SkPaint& paint) { 2814 if (cullRect && this->quickReject(*cullRect)) { 2815 return; 2816 } 2817 2818 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2819 2820 while (iter.next()) { 2821 iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint()); 2822 } 2823 2824 LOOPER_END 2825} 2826 2827void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2828 const SkPaint& paint) { 2829 2830 SkRect storage; 2831 const SkRect* bounds = nullptr; 2832 if (paint.canComputeFastBounds()) { 2833 storage = blob->bounds().makeOffset(x, y); 2834 SkRect tmp; 2835 if (this->quickReject(paint.computeFastBounds(storage, &tmp))) { 2836 return; 2837 } 2838 bounds = &storage; 2839 } 2840 2841 // We cannot filter in the looper as we normally do, because the paint is 2842 // incomplete at this point (text-related attributes are embedded within blob run paints). 2843 SkDrawFilter* drawFilter = fMCRec->fFilter; 2844 fMCRec->fFilter = nullptr; 2845 2846 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2847 2848 while (iter.next()) { 2849 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2850 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); 2851 } 2852 2853 LOOPER_END 2854 2855 fMCRec->fFilter = drawFilter; 2856} 2857 2858// These will become non-virtual, so they always call the (virtual) onDraw... method 2859void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2860 const SkPaint& paint) { 2861 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2862 if (byteLength) { 2863 this->onDrawText(text, byteLength, x, y, paint); 2864 } 2865} 2866void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2867 const SkPaint& paint) { 2868 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2869 if (byteLength) { 2870 this->onDrawPosText(text, byteLength, pos, paint); 2871 } 2872} 2873void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2874 SkScalar constY, const SkPaint& paint) { 2875 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2876 if (byteLength) { 2877 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2878 } 2879} 2880void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2881 const SkMatrix* matrix, const SkPaint& paint) { 2882 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2883 if (byteLength) { 2884 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2885 } 2886} 2887void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 2888 const SkRect* cullRect, const SkPaint& paint) { 2889 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()"); 2890 if (byteLength) { 2891 this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint); 2892 } 2893} 2894void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2895 const SkPaint& paint) { 2896 RETURN_ON_NULL(blob); 2897 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2898 this->onDrawTextBlob(blob, x, y, paint); 2899} 2900 2901void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 2902 const SkPoint verts[], const SkPoint texs[], 2903 const SkColor colors[], SkXfermode* xmode, 2904 const uint16_t indices[], int indexCount, 2905 const SkPaint& paint) { 2906 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2907 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2908 2909 while (iter.next()) { 2910 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2911 colors, xmode, indices, indexCount, 2912 looper.paint()); 2913 } 2914 2915 LOOPER_END 2916} 2917 2918void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2919 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2920 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2921 if (nullptr == cubics) { 2922 return; 2923 } 2924 2925 // Since a patch is always within the convex hull of the control points, we discard it when its 2926 // bounding rectangle is completely outside the current clip. 2927 SkRect bounds; 2928 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2929 if (this->quickReject(bounds)) { 2930 return; 2931 } 2932 2933 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2934} 2935 2936void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2937 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2938 2939 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2940 2941 while (iter.next()) { 2942 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2943 } 2944 2945 LOOPER_END 2946} 2947 2948void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) { 2949 RETURN_ON_NULL(dr); 2950 if (x || y) { 2951 SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2952 this->onDrawDrawable(dr, &matrix); 2953 } else { 2954 this->onDrawDrawable(dr, nullptr); 2955 } 2956} 2957 2958void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2959 RETURN_ON_NULL(dr); 2960 if (matrix && matrix->isIdentity()) { 2961 matrix = nullptr; 2962 } 2963 this->onDrawDrawable(dr, matrix); 2964} 2965 2966void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2967 SkRect bounds = dr->getBounds(); 2968 if (matrix) { 2969 matrix->mapRect(&bounds); 2970 } 2971 if (this->quickReject(bounds)) { 2972 return; 2973 } 2974 dr->draw(this, matrix); 2975} 2976 2977void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2978 const SkColor colors[], int count, SkXfermode::Mode mode, 2979 const SkRect* cull, const SkPaint* paint) { 2980 if (cull && this->quickReject(*cull)) { 2981 return; 2982 } 2983 2984 SkPaint pnt; 2985 if (paint) { 2986 pnt = *paint; 2987 } 2988 2989 LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr) 2990 while (iter.next()) { 2991 iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt); 2992 } 2993 LOOPER_END 2994} 2995 2996void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { 2997 SkASSERT(key); 2998 2999 SkPaint paint; 3000 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr) 3001 while (iter.next()) { 3002 iter.fDevice->drawAnnotation(iter, rect, key, value); 3003 } 3004 LOOPER_END 3005} 3006 3007////////////////////////////////////////////////////////////////////////////// 3008// These methods are NOT virtual, and therefore must call back into virtual 3009// methods, rather than actually drawing themselves. 3010////////////////////////////////////////////////////////////////////////////// 3011 3012void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 3013 SkXfermode::Mode mode) { 3014 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 3015 SkPaint paint; 3016 3017 paint.setARGB(a, r, g, b); 3018 if (SkXfermode::kSrcOver_Mode != mode) { 3019 paint.setXfermodeMode(mode); 3020 } 3021 this->drawPaint(paint); 3022} 3023 3024void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 3025 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 3026 SkPaint paint; 3027 3028 paint.setColor(c); 3029 if (SkXfermode::kSrcOver_Mode != mode) { 3030 paint.setXfermodeMode(mode); 3031 } 3032 this->drawPaint(paint); 3033} 3034 3035void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 3036 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 3037 SkPoint pt; 3038 3039 pt.set(x, y); 3040 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 3041} 3042 3043void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 3044 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 3045 SkPoint pt; 3046 SkPaint paint; 3047 3048 pt.set(x, y); 3049 paint.setColor(color); 3050 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 3051} 3052 3053void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 3054 const SkPaint& paint) { 3055 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 3056 SkPoint pts[2]; 3057 3058 pts[0].set(x0, y0); 3059 pts[1].set(x1, y1); 3060 this->drawPoints(kLines_PointMode, 2, pts, paint); 3061} 3062 3063void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 3064 SkScalar right, SkScalar bottom, 3065 const SkPaint& paint) { 3066 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 3067 SkRect r; 3068 3069 r.set(left, top, right, bottom); 3070 this->drawRect(r, paint); 3071} 3072 3073void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 3074 const SkPaint& paint) { 3075 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 3076 if (radius < 0) { 3077 radius = 0; 3078 } 3079 3080 SkRect r; 3081 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 3082 this->drawOval(r, paint); 3083} 3084 3085void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 3086 const SkPaint& paint) { 3087 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 3088 if (rx > 0 && ry > 0) { 3089 SkRRect rrect; 3090 rrect.setRectXY(r, rx, ry); 3091 this->drawRRect(rrect, paint); 3092 } else { 3093 this->drawRect(r, paint); 3094 } 3095} 3096 3097void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 3098 SkScalar sweepAngle, bool useCenter, 3099 const SkPaint& paint) { 3100 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 3101 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 3102 this->drawOval(oval, paint); 3103 } else { 3104 this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint); 3105 } 3106} 3107 3108void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 3109 const SkPath& path, SkScalar hOffset, 3110 SkScalar vOffset, const SkPaint& paint) { 3111 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 3112 SkMatrix matrix; 3113 3114 matrix.setTranslate(hOffset, vOffset); 3115 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 3116} 3117 3118/////////////////////////////////////////////////////////////////////////////// 3119 3120/** 3121 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 3122 * against the playback cost of recursing into the subpicture to get at its actual ops. 3123 * 3124 * For now we pick a conservatively small value, though measurement (and other heuristics like 3125 * the type of ops contained) may justify changing this value. 3126 */ 3127#define kMaxPictureOpsToUnrollInsteadOfRef 1 3128 3129void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 3130 RETURN_ON_NULL(picture); 3131 3132 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 3133 if (matrix && matrix->isIdentity()) { 3134 matrix = nullptr; 3135 } 3136 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { 3137 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 3138 picture->playback(this); 3139 } else { 3140 this->onDrawPicture(picture, matrix, paint); 3141 } 3142} 3143 3144void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 3145 const SkPaint* paint) { 3146 if (!paint || paint->canComputeFastBounds()) { 3147 SkRect bounds = picture->cullRect(); 3148 if (paint) { 3149 paint->computeFastBounds(bounds, &bounds); 3150 } 3151 if (matrix) { 3152 matrix->mapRect(&bounds); 3153 } 3154 if (this->quickReject(bounds)) { 3155 return; 3156 } 3157 } 3158 3159 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 3160 picture->playback(this); 3161} 3162 3163#ifdef SK_EXPERIMENTAL_SHADOWING 3164void SkCanvas::drawShadowedPicture(const SkPicture* picture, 3165 const SkMatrix* matrix, 3166 const SkPaint* paint, 3167 const SkShadowParams& params) { 3168 RETURN_ON_NULL(picture); 3169 3170 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()"); 3171 3172 this->onDrawShadowedPicture(picture, matrix, paint, params); 3173} 3174 3175void SkCanvas::onDrawShadowedPicture(const SkPicture* picture, 3176 const SkMatrix* matrix, 3177 const SkPaint* paint, 3178 const SkShadowParams& params) { 3179 if (!paint || paint->canComputeFastBounds()) { 3180 SkRect bounds = picture->cullRect(); 3181 if (paint) { 3182 paint->computeFastBounds(bounds, &bounds); 3183 } 3184 if (matrix) { 3185 matrix->mapRect(&bounds); 3186 } 3187 if (this->quickReject(bounds)) { 3188 return; 3189 } 3190 } 3191 3192 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 3193 3194 sk_sp<SkImage> povDepthMap; 3195 sk_sp<SkImage> diffuseMap; 3196 3197 // TODO: pass the depth to the shader in vertices, or uniforms 3198 // so we don't have to render depth and color separately 3199 for (int i = 0; i < fLights->numLights(); ++i) { 3200 // skip over ambient lights; they don't cast shadows 3201 // lights that have shadow maps do not need updating (because lights are immutable) 3202 3203 if (SkLights::Light::kAmbient_LightType == fLights->light(i).type() || 3204 fLights->light(i).getShadowMap() != nullptr) { 3205 continue; 3206 } 3207 3208 // TODO: compute the correct size of the depth map from the light properties 3209 // TODO: maybe add a kDepth_8_SkColorType 3210 // TODO: find actual max depth of picture 3211 SkISize shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize( 3212 fLights->light(i), 255, 3213 picture->cullRect().width(), 3214 picture->cullRect().height()); 3215 3216 SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight, 3217 kBGRA_8888_SkColorType, 3218 kOpaque_SkAlphaType); 3219 3220 // Create a new surface (that matches the backend of canvas) 3221 // for each shadow map 3222 sk_sp<SkSurface> surf(this->makeSurface(info)); 3223 3224 // Wrap another SPFCanvas around the surface 3225 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = 3226 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); 3227 depthMapCanvas->setShadowParams(params); 3228 3229 // set the depth map canvas to have the light we're drawing. 3230 SkLights::Builder builder; 3231 builder.add(fLights->light(i)); 3232 sk_sp<SkLights> curLight = builder.finish(); 3233 depthMapCanvas->setLights(std::move(curLight)); 3234 3235 depthMapCanvas->drawPicture(picture); 3236 sk_sp<SkImage> depthMap = surf->makeImageSnapshot(); 3237 3238 if (params.fType == SkShadowParams::kNoBlur_ShadowType) { 3239 fLights->light(i).setShadowMap(std::move(depthMap)); 3240 } else if (params.fType == SkShadowParams::kVariance_ShadowType) { 3241 // we blur the variance map 3242 SkPaint blurPaint; 3243 blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius, 3244 params.fShadowRadius, nullptr)); 3245 3246 SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight, 3247 kBGRA_8888_SkColorType, 3248 kOpaque_SkAlphaType); 3249 3250 sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo)); 3251 3252 blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint); 3253 3254 fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot()); 3255 } 3256 } 3257 3258 // povDepthMap 3259 { 3260 SkLights::Builder builder; 3261 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f), 3262 SkVector3::Make(0.0f, 0.0f, 1.0f))); 3263 sk_sp<SkLights> povLight = builder.finish(); 3264 3265 SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(), 3266 picture->cullRect().height(), 3267 kBGRA_8888_SkColorType, 3268 kOpaque_SkAlphaType); 3269 3270 // Create a new surface (that matches the backend of canvas) 3271 // to create the povDepthMap 3272 sk_sp<SkSurface> surf(this->makeSurface(info)); 3273 3274 // Wrap another SPFCanvas around the surface 3275 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = 3276 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); 3277 3278 // set the depth map canvas to have the light as the user's POV 3279 depthMapCanvas->setLights(std::move(povLight)); 3280 3281 depthMapCanvas->drawPicture(picture); 3282 povDepthMap = surf->makeImageSnapshot(); 3283 } 3284 3285 // diffuseMap 3286 { 3287 SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(), 3288 picture->cullRect().height(), 3289 kBGRA_8888_SkColorType, 3290 kOpaque_SkAlphaType); 3291 3292 sk_sp<SkSurface> surf(this->makeSurface(info)); 3293 surf->getCanvas()->drawPicture(picture); 3294 3295 diffuseMap = surf->makeImageSnapshot(); 3296 } 3297 SkPaint shadowPaint; 3298 3299 sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode, 3300 SkShader::kClamp_TileMode); 3301 sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode, 3302 SkShader::kClamp_TileMode); 3303 sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader), 3304 std::move(diffuseShader), 3305 std::move(fLights), 3306 diffuseMap->width(), 3307 diffuseMap->height(), 3308 params); 3309 3310 shadowPaint.setShader(shadowShader); 3311 3312 this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint); 3313} 3314#endif 3315 3316/////////////////////////////////////////////////////////////////////////////// 3317/////////////////////////////////////////////////////////////////////////////// 3318 3319SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) { 3320 static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small"); 3321 3322 SkASSERT(canvas); 3323 3324 fImpl = new (fStorage) SkDrawIter(canvas); 3325 fDone = !fImpl->next(); 3326} 3327 3328SkCanvas::LayerIter::~LayerIter() { 3329 fImpl->~SkDrawIter(); 3330} 3331 3332void SkCanvas::LayerIter::next() { 3333 fDone = !fImpl->next(); 3334} 3335 3336SkBaseDevice* SkCanvas::LayerIter::device() const { 3337 return fImpl->getDevice(); 3338} 3339 3340const SkMatrix& SkCanvas::LayerIter::matrix() const { 3341 return fImpl->getMatrix(); 3342} 3343 3344const SkPaint& SkCanvas::LayerIter::paint() const { 3345 const SkPaint* paint = fImpl->getPaint(); 3346 if (nullptr == paint) { 3347 paint = &fDefaultPaint; 3348 } 3349 return *paint; 3350} 3351 3352const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 3353int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 3354int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 3355 3356/////////////////////////////////////////////////////////////////////////////// 3357 3358SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 3359 3360/////////////////////////////////////////////////////////////////////////////// 3361 3362static bool supported_for_raster_canvas(const SkImageInfo& info) { 3363 switch (info.alphaType()) { 3364 case kPremul_SkAlphaType: 3365 case kOpaque_SkAlphaType: 3366 break; 3367 default: 3368 return false; 3369 } 3370 3371 switch (info.colorType()) { 3372 case kAlpha_8_SkColorType: 3373 case kRGB_565_SkColorType: 3374 case kN32_SkColorType: 3375 break; 3376 default: 3377 return false; 3378 } 3379 3380 return true; 3381} 3382 3383SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 3384 if (!supported_for_raster_canvas(info)) { 3385 return nullptr; 3386 } 3387 3388 SkBitmap bitmap; 3389 if (!bitmap.installPixels(info, pixels, rowBytes)) { 3390 return nullptr; 3391 } 3392 return new SkCanvas(bitmap); 3393} 3394 3395/////////////////////////////////////////////////////////////////////////////// 3396 3397SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 3398 const SkPaint* paint, const SkRect& bounds) 3399 : fCanvas(canvas) 3400 , fSaveCount(canvas->getSaveCount()) 3401{ 3402 if (paint) { 3403 SkRect newBounds = bounds; 3404 if (matrix) { 3405 matrix->mapRect(&newBounds); 3406 } 3407 canvas->saveLayer(&newBounds, paint); 3408 } else if (matrix) { 3409 canvas->save(); 3410 } 3411 3412 if (matrix) { 3413 canvas->concat(*matrix); 3414 } 3415} 3416 3417SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 3418 fCanvas->restoreToCount(fSaveCount); 3419} 3420 3421#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API 3422SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 3423 return this->makeSurface(info, props).release(); 3424} 3425#endif 3426