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