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