SkCanvas.cpp revision 802acec1876bb647aaab1bbcfd97748bba54da8f
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 const bool hasImageFilter = paint && paint->getImageFilter(); 1181 1182 SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 1183 if ((prev.bytesPerPixel() < 4) || hasImageFilter) { 1184 // force to L32 1185 return SkImageInfo::MakeN32(w, h, alphaType); 1186 } else { 1187 // keep the same characteristics as the prev 1188 return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.profileType()); 1189 } 1190} 1191 1192void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) { 1193 const SkRect* bounds = rec.fBounds; 1194 const SkPaint* paint = rec.fPaint; 1195 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags; 1196 1197#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 1198 saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag; 1199#endif 1200 1201 SkLazyPaint lazyP; 1202 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL; 1203 SkMatrix stashedMatrix = fMCRec->fMatrix; 1204 SkMatrix remainder; 1205 SkSize scale; 1206 /* 1207 * ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc. 1208 * but they do handle scaling. To accommodate this, we do the following: 1209 * 1210 * 1. Stash off the current CTM 1211 * 2. Decompose the CTM into SCALE and REMAINDER 1212 * 3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that 1213 * contains the REMAINDER 1214 * 4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM) 1215 * 5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output 1216 * of the original imagefilter, and draw that (via drawSprite) 1217 * 6. Unwack the CTM to its original state (i.e. stashedMatrix) 1218 * 1219 * Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer 1220 * a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter. 1221 */ 1222 if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() && 1223 stashedMatrix.decomposeScale(&scale, &remainder)) 1224 { 1225 // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix 1226 this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height())); 1227 SkPaint* p = lazyP.set(*paint); 1228 p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder, 1229 SkFilterQuality::kLow_SkFilterQuality, 1230 sk_ref_sp(imageFilter))); 1231 imageFilter = p->getImageFilter(); 1232 paint = p; 1233 } 1234 1235 // do this before we create the layer. We don't call the public save() since 1236 // that would invoke a possibly overridden virtual 1237 this->internalSave(); 1238 1239 fDeviceCMDirty = true; 1240 1241 SkIRect ir; 1242 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) { 1243 return; 1244 } 1245 1246 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 1247 // the clipRectBounds() call above? 1248 if (kNoLayer_SaveLayerStrategy == strategy) { 1249 return; 1250 } 1251 1252 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag); 1253 SkPixelGeometry geo = fProps.pixelGeometry(); 1254 if (paint) { 1255 // TODO: perhaps add a query to filters so we might preserve opaqueness... 1256 if (paint->getImageFilter() || paint->getColorFilter()) { 1257 isOpaque = false; 1258 geo = kUnknown_SkPixelGeometry; 1259 } 1260 } 1261 1262 SkBaseDevice* device = this->getTopDevice(); 1263 if (nullptr == device) { 1264 SkDebugf("Unable to find device for layer."); 1265 return; 1266 } 1267 1268 SkImageInfo info = make_layer_info(device->imageInfo(), ir.width(), ir.height(), isOpaque, 1269 paint); 1270 1271 bool forceSpriteOnRestore = false; 1272 { 1273 const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() || 1274 (saveLayerFlags & kPreserveLCDText_SaveLayerFlag); 1275 const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; 1276 const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo, 1277 preserveLCDText, false); 1278 SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint); 1279 if (nullptr == newDev) { 1280 // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint) 1281 const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry); 1282 newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps); 1283 if (nullptr == newDev) { 1284 SkErrorInternals::SetError(kInternalError_SkError, 1285 "Unable to create device for layer."); 1286 return; 1287 } 1288 forceSpriteOnRestore = true; 1289 } 1290 device = newDev; 1291 } 1292 device->setOrigin(ir.fLeft, ir.fTop); 1293 1294 if (rec.fBackdrop) { 1295 draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, device, fMCRec->fMatrix); 1296 } 1297 1298 DeviceCM* layer = new DeviceCM(device, paint, this, fConservativeRasterClip, 1299 forceSpriteOnRestore, stashedMatrix); 1300 device->unref(); 1301 1302 layer->fNext = fMCRec->fTopLayer; 1303 fMCRec->fLayer = layer; 1304 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 1305} 1306 1307int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 1308 if (0xFF == alpha) { 1309 return this->saveLayer(bounds, nullptr); 1310 } else { 1311 SkPaint tmpPaint; 1312 tmpPaint.setAlpha(alpha); 1313 return this->saveLayer(bounds, &tmpPaint); 1314 } 1315} 1316 1317void SkCanvas::internalRestore() { 1318 SkASSERT(fMCStack.count() != 0); 1319 1320 fDeviceCMDirty = true; 1321 fCachedLocalClipBoundsDirty = true; 1322 1323 fClipStack->restore(); 1324 1325 // reserve our layer (if any) 1326 DeviceCM* layer = fMCRec->fLayer; // may be null 1327 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 1328 fMCRec->fLayer = nullptr; 1329 1330 // now do the normal restore() 1331 fMCRec->~MCRec(); // balanced in save() 1332 fMCStack.pop_back(); 1333 fMCRec = (MCRec*)fMCStack.back(); 1334 1335 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1336 since if we're being recorded, we don't want to record this (the 1337 recorder will have already recorded the restore). 1338 */ 1339 if (layer) { 1340 if (layer->fNext) { 1341 const SkIPoint& origin = layer->fDevice->getOrigin(); 1342 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1343 layer->fPaint, layer->fDeviceIsBitmapDevice); 1344 // restore what we smashed in internalSaveLayer 1345 fMCRec->fMatrix = layer->fStashedMatrix; 1346 // reset this, since internalDrawDevice will have set it to true 1347 fDeviceCMDirty = true; 1348 delete layer; 1349 } else { 1350 // we're at the root 1351 SkASSERT(layer == (void*)fDeviceCMStorage); 1352 layer->~DeviceCM(); 1353 // no need to update fMCRec, 'cause we're killing the canvas 1354 } 1355 } 1356} 1357 1358sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 1359 if (nullptr == props) { 1360 props = &fProps; 1361 } 1362 return this->onNewSurface(info, *props); 1363} 1364 1365sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1366 SkBaseDevice* dev = this->getDevice(); 1367 return dev ? dev->makeSurface(info, props) : nullptr; 1368} 1369 1370SkImageInfo SkCanvas::imageInfo() const { 1371 SkBaseDevice* dev = this->getDevice(); 1372 if (dev) { 1373 return dev->imageInfo(); 1374 } else { 1375 return SkImageInfo::MakeUnknown(0, 0); 1376 } 1377} 1378 1379bool SkCanvas::getProps(SkSurfaceProps* props) const { 1380 SkBaseDevice* dev = this->getDevice(); 1381 if (dev) { 1382 if (props) { 1383 *props = fProps; 1384 } 1385 return true; 1386 } else { 1387 return false; 1388 } 1389} 1390 1391#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS 1392const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1393 SkPixmap pmap; 1394 if (this->peekPixels(&pmap)) { 1395 if (info) { 1396 *info = pmap.info(); 1397 } 1398 if (rowBytes) { 1399 *rowBytes = pmap.rowBytes(); 1400 } 1401 return pmap.addr(); 1402 } 1403 return nullptr; 1404} 1405#endif 1406 1407bool SkCanvas::peekPixels(SkPixmap* pmap) { 1408 return this->onPeekPixels(pmap); 1409} 1410 1411bool SkCanvas::onPeekPixels(SkPixmap* pmap) { 1412 SkBaseDevice* dev = this->getDevice(); 1413 return dev && dev->peekPixels(pmap); 1414} 1415 1416void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { 1417 SkPixmap pmap; 1418 if (!this->onAccessTopLayerPixels(&pmap)) { 1419 return nullptr; 1420 } 1421 if (info) { 1422 *info = pmap.info(); 1423 } 1424 if (rowBytes) { 1425 *rowBytes = pmap.rowBytes(); 1426 } 1427 if (origin) { 1428 *origin = this->getTopDevice(false)->getOrigin(); 1429 } 1430 return pmap.writable_addr(); 1431} 1432 1433bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) { 1434 SkBaseDevice* dev = this->getTopDevice(); 1435 return dev && dev->accessPixels(pmap); 1436} 1437 1438///////////////////////////////////////////////////////////////////////////// 1439 1440void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 1441 const SkPaint* paint, bool deviceIsBitmapDevice) { 1442 SkPaint tmp; 1443 if (nullptr == paint) { 1444 paint = &tmp; 1445 } 1446 1447 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1448 while (iter.next()) { 1449 SkBaseDevice* dstDev = iter.fDevice; 1450 paint = &looper.paint(); 1451 SkImageFilter* filter = paint->getImageFilter(); 1452 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1453 if (filter) { 1454 const SkBitmap& srcBM = srcDev->accessBitmap(false); 1455 dstDev->drawSpriteWithFilter(iter, srcBM, pos.x(), pos.y(), *paint); 1456 } else if (deviceIsBitmapDevice) { 1457 const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap; 1458 dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint); 1459 } else { 1460 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1461 } 1462 } 1463 LOOPER_END 1464} 1465 1466///////////////////////////////////////////////////////////////////////////// 1467 1468void SkCanvas::translate(SkScalar dx, SkScalar dy) { 1469 SkMatrix m; 1470 m.setTranslate(dx, dy); 1471 this->concat(m); 1472} 1473 1474void SkCanvas::scale(SkScalar sx, SkScalar sy) { 1475 SkMatrix m; 1476 m.setScale(sx, sy); 1477 this->concat(m); 1478} 1479 1480void SkCanvas::rotate(SkScalar degrees) { 1481 SkMatrix m; 1482 m.setRotate(degrees); 1483 this->concat(m); 1484} 1485 1486void SkCanvas::skew(SkScalar sx, SkScalar sy) { 1487 SkMatrix m; 1488 m.setSkew(sx, sy); 1489 this->concat(m); 1490} 1491 1492void SkCanvas::concat(const SkMatrix& matrix) { 1493 if (matrix.isIdentity()) { 1494 return; 1495 } 1496 1497 this->checkForDeferredSave(); 1498 fDeviceCMDirty = true; 1499 fCachedLocalClipBoundsDirty = true; 1500 fMCRec->fMatrix.preConcat(matrix); 1501 1502 this->didConcat(matrix); 1503} 1504 1505void SkCanvas::internalSetMatrix(const SkMatrix& matrix) { 1506 fDeviceCMDirty = true; 1507 fCachedLocalClipBoundsDirty = true; 1508 fMCRec->fMatrix = matrix; 1509} 1510 1511void SkCanvas::setMatrix(const SkMatrix& matrix) { 1512 this->checkForDeferredSave(); 1513 this->internalSetMatrix(matrix); 1514 this->didSetMatrix(matrix); 1515} 1516 1517void SkCanvas::resetMatrix() { 1518 this->setMatrix(SkMatrix::I()); 1519} 1520 1521////////////////////////////////////////////////////////////////////////////// 1522 1523void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1524 this->checkForDeferredSave(); 1525 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1526 this->onClipRect(rect, op, edgeStyle); 1527} 1528 1529void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1530#ifdef SK_ENABLE_CLIP_QUICKREJECT 1531 if (SkRegion::kIntersect_Op == op) { 1532 if (fMCRec->fRasterClip.isEmpty()) { 1533 return false; 1534 } 1535 1536 if (this->quickReject(rect)) { 1537 fDeviceCMDirty = true; 1538 fCachedLocalClipBoundsDirty = true; 1539 1540 fClipStack->clipEmpty(); 1541 return fMCRec->fRasterClip.setEmpty(); 1542 } 1543 } 1544#endif 1545 1546 if (!fAllowSoftClip) { 1547 edgeStyle = kHard_ClipEdgeStyle; 1548 } 1549 1550 const bool rectStaysRect = fMCRec->fMatrix.rectStaysRect(); 1551 SkRect devR; 1552 if (rectStaysRect) { 1553 fMCRec->fMatrix.mapRect(&devR, rect); 1554 } 1555 1556 // Check if we can quick-accept the clip call (and do nothing) 1557 // 1558 // TODO: investigate if a (conservative) version of this could be done in ::clipRect, 1559 // so that subclasses (like PictureRecording) didn't see unnecessary clips, which in turn 1560 // might allow lazy save/restores to eliminate entire save/restore blocks. 1561 // 1562 if (SkRegion::kIntersect_Op == op && 1563 kHard_ClipEdgeStyle == edgeStyle 1564 && rectStaysRect) 1565 { 1566 if (devR.round().contains(fMCRec->fRasterClip.getBounds())) { 1567#if 0 1568 SkDebugf("------- ignored clipRect [%g %g %g %g]\n", 1569 rect.left(), rect.top(), rect.right(), rect.bottom()); 1570#endif 1571 return; 1572 } 1573 } 1574 1575 AutoValidateClip avc(this); 1576 1577 fDeviceCMDirty = true; 1578 fCachedLocalClipBoundsDirty = true; 1579 1580 if (rectStaysRect) { 1581 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle; 1582 fClipStack->clipDevRect(devR, op, isAA); 1583 fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA); 1584 } else { 1585 // since we're rotated or some such thing, we convert the rect to a path 1586 // and clip against that, since it can handle any matrix. However, to 1587 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1588 // we explicitly call "our" version of clipPath. 1589 SkPath path; 1590 1591 path.addRect(rect); 1592 this->SkCanvas::onClipPath(path, op, edgeStyle); 1593 } 1594} 1595 1596void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1597 this->checkForDeferredSave(); 1598 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1599 if (rrect.isRect()) { 1600 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1601 } else { 1602 this->onClipRRect(rrect, op, edgeStyle); 1603 } 1604} 1605 1606void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1607 SkRRect transformedRRect; 1608 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1609 AutoValidateClip avc(this); 1610 1611 fDeviceCMDirty = true; 1612 fCachedLocalClipBoundsDirty = true; 1613 if (!fAllowSoftClip) { 1614 edgeStyle = kHard_ClipEdgeStyle; 1615 } 1616 1617 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1618 1619 fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op, 1620 kSoft_ClipEdgeStyle == edgeStyle); 1621 return; 1622 } 1623 1624 SkPath path; 1625 path.addRRect(rrect); 1626 // call the non-virtual version 1627 this->SkCanvas::onClipPath(path, op, edgeStyle); 1628} 1629 1630void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1631 this->checkForDeferredSave(); 1632 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1633 1634 if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) { 1635 SkRect r; 1636 if (path.isRect(&r)) { 1637 this->onClipRect(r, op, edgeStyle); 1638 return; 1639 } 1640 SkRRect rrect; 1641 if (path.isOval(&r)) { 1642 rrect.setOval(r); 1643 this->onClipRRect(rrect, op, edgeStyle); 1644 return; 1645 } 1646 if (path.isRRect(&rrect)) { 1647 this->onClipRRect(rrect, op, edgeStyle); 1648 return; 1649 } 1650 } 1651 1652 this->onClipPath(path, op, edgeStyle); 1653} 1654 1655void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1656#ifdef SK_ENABLE_CLIP_QUICKREJECT 1657 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1658 if (fMCRec->fRasterClip.isEmpty()) { 1659 return false; 1660 } 1661 1662 if (this->quickReject(path.getBounds())) { 1663 fDeviceCMDirty = true; 1664 fCachedLocalClipBoundsDirty = true; 1665 1666 fClipStack->clipEmpty(); 1667 return fMCRec->fRasterClip.setEmpty(); 1668 } 1669 } 1670#endif 1671 1672 AutoValidateClip avc(this); 1673 1674 fDeviceCMDirty = true; 1675 fCachedLocalClipBoundsDirty = true; 1676 if (!fAllowSoftClip) { 1677 edgeStyle = kHard_ClipEdgeStyle; 1678 } 1679 1680 SkPath devPath; 1681 path.transform(fMCRec->fMatrix, &devPath); 1682 1683 // Check if the transfomation, or the original path itself 1684 // made us empty. Note this can also happen if we contained NaN 1685 // values. computing the bounds detects this, and will set our 1686 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1687 if (devPath.getBounds().isEmpty()) { 1688 // resetting the path will remove any NaN or other wanky values 1689 // that might upset our scan converter. 1690 devPath.reset(); 1691 } 1692 1693 // if we called path.swap() we could avoid a deep copy of this path 1694 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1695 1696 if (fAllowSimplifyClip) { 1697 bool clipIsAA = getClipStack()->asPath(&devPath); 1698 if (clipIsAA) { 1699 edgeStyle = kSoft_ClipEdgeStyle; 1700 } 1701 1702 op = SkRegion::kReplace_Op; 1703 } 1704 1705 fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle); 1706} 1707 1708void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1709 this->checkForDeferredSave(); 1710 this->onClipRegion(rgn, op); 1711} 1712 1713void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1714 AutoValidateClip avc(this); 1715 1716 fDeviceCMDirty = true; 1717 fCachedLocalClipBoundsDirty = true; 1718 1719 // todo: signal fClipStack that we have a region, and therefore (I guess) 1720 // we have to ignore it, and use the region directly? 1721 fClipStack->clipDevRect(rgn.getBounds(), op); 1722 1723 fMCRec->fRasterClip.op(rgn, op); 1724} 1725 1726#ifdef SK_DEBUG 1727void SkCanvas::validateClip() const { 1728 // construct clipRgn from the clipstack 1729 const SkBaseDevice* device = this->getDevice(); 1730 if (!device) { 1731 SkASSERT(this->isClipEmpty()); 1732 return; 1733 } 1734 1735 SkIRect ir; 1736 ir.set(0, 0, device->width(), device->height()); 1737 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1738 1739 SkClipStack::B2TIter iter(*fClipStack); 1740 const SkClipStack::Element* element; 1741 while ((element = iter.next()) != nullptr) { 1742 switch (element->getType()) { 1743 case SkClipStack::Element::kRect_Type: 1744 element->getRect().round(&ir); 1745 tmpClip.op(ir, element->getOp()); 1746 break; 1747 case SkClipStack::Element::kEmpty_Type: 1748 tmpClip.setEmpty(); 1749 break; 1750 default: { 1751 SkPath path; 1752 element->asPath(&path); 1753 tmpClip.op(path, this->getTopLayerBounds(), element->getOp(), element->isAA()); 1754 break; 1755 } 1756 } 1757 } 1758} 1759#endif 1760 1761void SkCanvas::replayClips(ClipVisitor* visitor) const { 1762 SkClipStack::B2TIter iter(*fClipStack); 1763 const SkClipStack::Element* element; 1764 1765 while ((element = iter.next()) != nullptr) { 1766 element->replay(visitor); 1767 } 1768} 1769 1770/////////////////////////////////////////////////////////////////////////////// 1771 1772bool SkCanvas::isClipEmpty() const { 1773 return fMCRec->fRasterClip.isEmpty(); 1774} 1775 1776bool SkCanvas::isClipRect() const { 1777 return fMCRec->fRasterClip.isRect(); 1778} 1779 1780bool SkCanvas::quickReject(const SkRect& rect) const { 1781 if (!rect.isFinite()) 1782 return true; 1783 1784 if (fMCRec->fRasterClip.isEmpty()) { 1785 return true; 1786 } 1787 1788 if (fMCRec->fMatrix.hasPerspective()) { 1789 SkRect dst; 1790 fMCRec->fMatrix.mapRect(&dst, rect); 1791 return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds()); 1792 } else { 1793 const SkRect& clipR = this->getLocalClipBounds(); 1794 1795 // for speed, do the most likely reject compares first 1796 // TODO: should we use | instead, or compare all 4 at once? 1797 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1798 return true; 1799 } 1800 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1801 return true; 1802 } 1803 return false; 1804 } 1805} 1806 1807bool SkCanvas::quickReject(const SkPath& path) const { 1808 return path.isEmpty() || this->quickReject(path.getBounds()); 1809} 1810 1811bool SkCanvas::getClipBounds(SkRect* bounds) const { 1812 SkIRect ibounds; 1813 if (!this->getClipDeviceBounds(&ibounds)) { 1814 return false; 1815 } 1816 1817 SkMatrix inverse; 1818 // if we can't invert the CTM, we can't return local clip bounds 1819 if (!fMCRec->fMatrix.invert(&inverse)) { 1820 if (bounds) { 1821 bounds->setEmpty(); 1822 } 1823 return false; 1824 } 1825 1826 if (bounds) { 1827 SkRect r; 1828 // adjust it outwards in case we are antialiasing 1829 const int inset = 1; 1830 1831 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1832 ibounds.fRight + inset, ibounds.fBottom + inset); 1833 inverse.mapRect(bounds, r); 1834 } 1835 return true; 1836} 1837 1838bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1839 const SkRasterClip& clip = fMCRec->fRasterClip; 1840 if (clip.isEmpty()) { 1841 if (bounds) { 1842 bounds->setEmpty(); 1843 } 1844 return false; 1845 } 1846 1847 if (bounds) { 1848 *bounds = clip.getBounds(); 1849 } 1850 return true; 1851} 1852 1853const SkMatrix& SkCanvas::getTotalMatrix() const { 1854 return fMCRec->fMatrix; 1855} 1856 1857const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1858 return fMCRec->fRasterClip.forceGetBW(); 1859} 1860 1861GrDrawContext* SkCanvas::internal_private_accessTopLayerDrawContext() { 1862 SkBaseDevice* dev = this->getTopDevice(); 1863 return dev ? dev->accessDrawContext() : nullptr; 1864} 1865 1866GrContext* SkCanvas::getGrContext() { 1867 SkBaseDevice* device = this->getTopDevice(); 1868 return device ? device->context() : nullptr; 1869} 1870 1871void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1872 const SkPaint& paint) { 1873 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()"); 1874 if (outer.isEmpty()) { 1875 return; 1876 } 1877 if (inner.isEmpty()) { 1878 this->drawRRect(outer, paint); 1879 return; 1880 } 1881 1882 // We don't have this method (yet), but technically this is what we should 1883 // be able to assert... 1884 // SkASSERT(outer.contains(inner)); 1885 // 1886 // For now at least check for containment of bounds 1887 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1888 1889 this->onDrawDRRect(outer, inner, paint); 1890} 1891 1892// These need to stop being virtual -- clients need to override the onDraw... versions 1893 1894void SkCanvas::drawPaint(const SkPaint& paint) { 1895 this->onDrawPaint(paint); 1896} 1897 1898void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1899 this->onDrawRect(r, paint); 1900} 1901 1902void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) { 1903 this->onDrawOval(r, paint); 1904} 1905 1906void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1907 this->onDrawRRect(rrect, paint); 1908} 1909 1910void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { 1911 this->onDrawPoints(mode, count, pts, paint); 1912} 1913 1914void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], 1915 const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, 1916 const uint16_t indices[], int indexCount, const SkPaint& paint) { 1917 this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 1918 indices, indexCount, paint); 1919} 1920 1921void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1922 this->onDrawPath(path, paint); 1923} 1924 1925void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1926 RETURN_ON_NULL(image); 1927 this->onDrawImage(image, x, y, paint); 1928} 1929 1930void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, 1931 const SkPaint* paint, SrcRectConstraint constraint) { 1932 RETURN_ON_NULL(image); 1933 if (dst.isEmpty() || src.isEmpty()) { 1934 return; 1935 } 1936 this->onDrawImageRect(image, &src, dst, paint, constraint); 1937} 1938 1939void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst, 1940 const SkPaint* paint, SrcRectConstraint constraint) { 1941 RETURN_ON_NULL(image); 1942 this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint); 1943} 1944 1945void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint, 1946 SrcRectConstraint constraint) { 1947 RETURN_ON_NULL(image); 1948 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint, 1949 constraint); 1950} 1951 1952void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 1953 const SkPaint* paint) { 1954 RETURN_ON_NULL(image); 1955 if (dst.isEmpty()) { 1956 return; 1957 } 1958 if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) { 1959 this->drawImageRect(image, dst, paint); 1960 } 1961 this->onDrawImageNine(image, center, dst, paint); 1962} 1963 1964void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1965 if (bitmap.drawsNothing()) { 1966 return; 1967 } 1968 this->onDrawBitmap(bitmap, dx, dy, paint); 1969} 1970 1971void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst, 1972 const SkPaint* paint, SrcRectConstraint constraint) { 1973 if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) { 1974 return; 1975 } 1976 this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint); 1977} 1978 1979void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst, 1980 const SkPaint* paint, SrcRectConstraint constraint) { 1981 this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint); 1982} 1983 1984void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, 1985 SrcRectConstraint constraint) { 1986 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint, 1987 constraint); 1988} 1989 1990void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 1991 const SkPaint* paint) { 1992 if (bitmap.drawsNothing() || dst.isEmpty()) { 1993 return; 1994 } 1995 if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) { 1996 this->drawBitmapRect(bitmap, dst, paint); 1997 } 1998 this->onDrawBitmapNine(bitmap, center, dst, paint); 1999} 2000 2001void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2002 const SkColor colors[], int count, SkXfermode::Mode mode, 2003 const SkRect* cull, const SkPaint* paint) { 2004 RETURN_ON_NULL(atlas); 2005 if (count <= 0) { 2006 return; 2007 } 2008 SkASSERT(atlas); 2009 SkASSERT(xform); 2010 SkASSERT(tex); 2011 this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); 2012} 2013 2014void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) { 2015 if (key) { 2016 this->onDrawAnnotation(rect, key, value); 2017 } 2018} 2019 2020void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 2021 const SkPaint* paint, SrcRectConstraint constraint) { 2022 if (src) { 2023 this->drawImageRect(image, *src, dst, paint, constraint); 2024 } else { 2025 this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), 2026 dst, paint, constraint); 2027 } 2028} 2029void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2030 const SkPaint* paint, SrcRectConstraint constraint) { 2031 if (src) { 2032 this->drawBitmapRect(bitmap, *src, dst, paint, constraint); 2033 } else { 2034 this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), 2035 dst, paint, constraint); 2036 } 2037} 2038 2039void SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) { 2040 SkIRect layer_bounds = this->getTopLayerBounds(); 2041 if (matrix) { 2042 *matrix = this->getTotalMatrix(); 2043 matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top()); 2044 } 2045 if (clip_bounds) { 2046 this->getClipDeviceBounds(clip_bounds); 2047 clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top()); 2048 } 2049} 2050 2051////////////////////////////////////////////////////////////////////////////// 2052// These are the virtual drawing methods 2053////////////////////////////////////////////////////////////////////////////// 2054 2055void SkCanvas::onDiscard() { 2056 if (fSurfaceBase) { 2057 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 2058 } 2059} 2060 2061void SkCanvas::onDrawPaint(const SkPaint& paint) { 2062 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 2063 this->internalDrawPaint(paint); 2064} 2065 2066void SkCanvas::internalDrawPaint(const SkPaint& paint) { 2067 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false) 2068 2069 while (iter.next()) { 2070 iter.fDevice->drawPaint(iter, looper.paint()); 2071 } 2072 2073 LOOPER_END 2074} 2075 2076void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 2077 const SkPaint& paint) { 2078 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 2079 if ((long)count <= 0) { 2080 return; 2081 } 2082 2083 SkRect r, storage; 2084 const SkRect* bounds = nullptr; 2085 if (paint.canComputeFastBounds()) { 2086 // special-case 2 points (common for drawing a single line) 2087 if (2 == count) { 2088 r.set(pts[0], pts[1]); 2089 } else { 2090 r.set(pts, SkToInt(count)); 2091 } 2092 if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) { 2093 return; 2094 } 2095 bounds = &r; 2096 } 2097 2098 SkASSERT(pts != nullptr); 2099 2100 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 2101 2102 while (iter.next()) { 2103 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 2104 } 2105 2106 LOOPER_END 2107} 2108 2109void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { 2110 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 2111 SkRect storage; 2112 const SkRect* bounds = nullptr; 2113 if (paint.canComputeFastBounds()) { 2114 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream. 2115 // To prevent accidental rejecting at this stage, we have to sort it before we check. 2116 SkRect tmp(r); 2117 tmp.sort(); 2118 2119 if (this->quickReject(paint.computeFastBounds(tmp, &storage))) { 2120 return; 2121 } 2122 bounds = &r; 2123 } 2124 2125 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false) 2126 2127 while (iter.next()) { 2128 iter.fDevice->drawRect(iter, r, looper.paint()); 2129 } 2130 2131 LOOPER_END 2132} 2133 2134void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 2135 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 2136 SkRect storage; 2137 const SkRect* bounds = nullptr; 2138 if (paint.canComputeFastBounds()) { 2139 if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 2140 return; 2141 } 2142 bounds = &oval; 2143 } 2144 2145 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 2146 2147 while (iter.next()) { 2148 iter.fDevice->drawOval(iter, oval, looper.paint()); 2149 } 2150 2151 LOOPER_END 2152} 2153 2154void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 2155 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 2156 SkRect storage; 2157 const SkRect* bounds = nullptr; 2158 if (paint.canComputeFastBounds()) { 2159 if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) { 2160 return; 2161 } 2162 bounds = &rrect.getBounds(); 2163 } 2164 2165 if (rrect.isRect()) { 2166 // call the non-virtual version 2167 this->SkCanvas::drawRect(rrect.getBounds(), paint); 2168 return; 2169 } else if (rrect.isOval()) { 2170 // call the non-virtual version 2171 this->SkCanvas::drawOval(rrect.getBounds(), paint); 2172 return; 2173 } 2174 2175 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 2176 2177 while (iter.next()) { 2178 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 2179 } 2180 2181 LOOPER_END 2182} 2183 2184void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 2185 const SkPaint& paint) { 2186 SkRect storage; 2187 const SkRect* bounds = nullptr; 2188 if (paint.canComputeFastBounds()) { 2189 if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) { 2190 return; 2191 } 2192 bounds = &outer.getBounds(); 2193 } 2194 2195 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 2196 2197 while (iter.next()) { 2198 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 2199 } 2200 2201 LOOPER_END 2202} 2203 2204void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 2205 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 2206 if (!path.isFinite()) { 2207 return; 2208 } 2209 2210 SkRect storage; 2211 const SkRect* bounds = nullptr; 2212 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 2213 const SkRect& pathBounds = path.getBounds(); 2214 if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) { 2215 return; 2216 } 2217 bounds = &pathBounds; 2218 } 2219 2220 const SkRect& r = path.getBounds(); 2221 if (r.width() <= 0 && r.height() <= 0) { 2222 if (path.isInverseFillType()) { 2223 this->internalDrawPaint(paint); 2224 return; 2225 } 2226 } 2227 2228 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 2229 2230 while (iter.next()) { 2231 iter.fDevice->drawPath(iter, path, looper.paint()); 2232 } 2233 2234 LOOPER_END 2235} 2236 2237bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) { 2238 if (!paint.getImageFilter()) { 2239 return false; 2240 } 2241 2242 const SkMatrix& ctm = this->getTotalMatrix(); 2243 if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) { 2244 return false; 2245 } 2246 2247 // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds. 2248 // Once we can filter and the filter will return a result larger than itself, we should be 2249 // able to remove this constraint. 2250 // skbug.com/4526 2251 // 2252 SkPoint pt; 2253 ctm.mapXY(x, y, &pt); 2254 SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h); 2255 return ir.contains(fMCRec->fRasterClip.getBounds()); 2256} 2257 2258void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 2259 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 2260 SkRect bounds = SkRect::MakeXYWH(x, y, 2261 SkIntToScalar(image->width()), SkIntToScalar(image->height())); 2262 if (nullptr == paint || paint->canComputeFastBounds()) { 2263 SkRect tmp = bounds; 2264 if (paint) { 2265 paint->computeFastBounds(tmp, &tmp); 2266 } 2267 if (this->quickReject(tmp)) { 2268 return; 2269 } 2270 } 2271 2272 SkLazyPaint lazy; 2273 if (nullptr == paint) { 2274 paint = lazy.init(); 2275 } 2276 2277 bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), 2278 *paint); 2279 if (drawAsSprite && paint->getImageFilter()) { 2280 SkBitmap bitmap; 2281 if (!as_IB(image)->asBitmapForImageFilters(&bitmap)) { 2282 drawAsSprite = false; 2283 } else{ 2284 // Until imagefilters are updated, they cannot handle any src type but N32... 2285 if (bitmap.info().colorType() != kN32_SkColorType || bitmap.info().isSRGB()) { 2286 drawAsSprite = false; 2287 } 2288 } 2289 } 2290 2291 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds) 2292 2293 while (iter.next()) { 2294 const SkPaint& pnt = looper.paint(); 2295 if (drawAsSprite && pnt.getImageFilter()) { 2296 SkBitmap bitmap; 2297 if (as_IB(image)->asBitmapForImageFilters(&bitmap)) { 2298 SkPoint pt; 2299 iter.fMatrix->mapXY(x, y, &pt); 2300 iter.fDevice->drawSpriteWithFilter(iter, bitmap, 2301 SkScalarRoundToInt(pt.fX), 2302 SkScalarRoundToInt(pt.fY), pnt); 2303 } 2304 } else { 2305 iter.fDevice->drawImage(iter, image, x, y, pnt); 2306 } 2307 } 2308 2309 LOOPER_END 2310} 2311 2312void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 2313 const SkPaint* paint, SrcRectConstraint constraint) { 2314 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 2315 if (nullptr == paint || paint->canComputeFastBounds()) { 2316 SkRect storage = dst; 2317 if (paint) { 2318 paint->computeFastBounds(dst, &storage); 2319 } 2320 if (this->quickReject(storage)) { 2321 return; 2322 } 2323 } 2324 SkLazyPaint lazy; 2325 if (nullptr == paint) { 2326 paint = lazy.init(); 2327 } 2328 2329 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2330 image->isOpaque()) 2331 2332 while (iter.next()) { 2333 iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint); 2334 } 2335 2336 LOOPER_END 2337} 2338 2339void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 2340 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 2341 SkDEBUGCODE(bitmap.validate();) 2342 2343 if (bitmap.drawsNothing()) { 2344 return; 2345 } 2346 2347 SkLazyPaint lazy; 2348 if (nullptr == paint) { 2349 paint = lazy.init(); 2350 } 2351 2352 const SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2353 2354 SkRect storage; 2355 const SkRect* bounds = nullptr; 2356 if (paint->canComputeFastBounds()) { 2357 bitmap.getBounds(&storage); 2358 matrix.mapRect(&storage); 2359 SkRect tmp = storage; 2360 if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) { 2361 return; 2362 } 2363 bounds = &storage; 2364 } 2365 2366 bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(), 2367 *paint); 2368 if (drawAsSprite && paint->getImageFilter()) { 2369 // Until imagefilters are updated, they cannot handle any src type but N32... 2370 if (bitmap.info().colorType() != kN32_SkColorType || bitmap.info().isSRGB()) { 2371 drawAsSprite = false; 2372 } 2373 } 2374 2375 LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds) 2376 2377 while (iter.next()) { 2378 const SkPaint& pnt = looper.paint(); 2379 if (drawAsSprite && pnt.getImageFilter()) { 2380 SkPoint pt; 2381 iter.fMatrix->mapXY(x, y, &pt); 2382 iter.fDevice->drawSpriteWithFilter(iter, bitmap, 2383 SkScalarRoundToInt(pt.fX), 2384 SkScalarRoundToInt(pt.fY), pnt); 2385 } else { 2386 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 2387 } 2388 } 2389 2390 LOOPER_END 2391} 2392 2393// this one is non-virtual, so it can be called safely by other canvas apis 2394void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2395 const SkRect& dst, const SkPaint* paint, 2396 SrcRectConstraint constraint) { 2397 if (bitmap.drawsNothing() || dst.isEmpty()) { 2398 return; 2399 } 2400 2401 if (nullptr == paint || paint->canComputeFastBounds()) { 2402 SkRect storage; 2403 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2404 return; 2405 } 2406 } 2407 2408 SkLazyPaint lazy; 2409 if (nullptr == paint) { 2410 paint = lazy.init(); 2411 } 2412 2413 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst, 2414 bitmap.isOpaque()) 2415 2416 while (iter.next()) { 2417 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint); 2418 } 2419 2420 LOOPER_END 2421} 2422 2423void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2424 const SkPaint* paint, SrcRectConstraint constraint) { 2425 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 2426 SkDEBUGCODE(bitmap.validate();) 2427 this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint); 2428} 2429 2430void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 2431 const SkPaint* paint) { 2432 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()"); 2433 2434 if (nullptr == paint || paint->canComputeFastBounds()) { 2435 SkRect storage; 2436 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2437 return; 2438 } 2439 } 2440 2441 SkLazyPaint lazy; 2442 if (nullptr == paint) { 2443 paint = lazy.init(); 2444 } 2445 2446 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2447 2448 while (iter.next()) { 2449 iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint()); 2450 } 2451 2452 LOOPER_END 2453} 2454 2455void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2456 const SkPaint* paint) { 2457 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2458 SkDEBUGCODE(bitmap.validate();) 2459 2460 if (nullptr == paint || paint->canComputeFastBounds()) { 2461 SkRect storage; 2462 if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) { 2463 return; 2464 } 2465 } 2466 2467 SkLazyPaint lazy; 2468 if (nullptr == paint) { 2469 paint = lazy.init(); 2470 } 2471 2472 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst) 2473 2474 while (iter.next()) { 2475 iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint()); 2476 } 2477 2478 LOOPER_END 2479} 2480 2481class SkDeviceFilteredPaint { 2482public: 2483 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2484 uint32_t filteredFlags = device->filterTextFlags(paint); 2485 if (filteredFlags != paint.getFlags()) { 2486 SkPaint* newPaint = fLazy.set(paint); 2487 newPaint->setFlags(filteredFlags); 2488 fPaint = newPaint; 2489 } else { 2490 fPaint = &paint; 2491 } 2492 } 2493 2494 const SkPaint& paint() const { return *fPaint; } 2495 2496private: 2497 const SkPaint* fPaint; 2498 SkLazyPaint fLazy; 2499}; 2500 2501void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2502 const SkRect& r, SkScalar textSize) { 2503 if (paint.getStyle() == SkPaint::kFill_Style) { 2504 draw.fDevice->drawRect(draw, r, paint); 2505 } else { 2506 SkPaint p(paint); 2507 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2508 draw.fDevice->drawRect(draw, r, p); 2509 } 2510} 2511 2512void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2513 const char text[], size_t byteLength, 2514 SkScalar x, SkScalar y) { 2515 SkASSERT(byteLength == 0 || text != nullptr); 2516 2517 // nothing to draw 2518 if (text == nullptr || byteLength == 0 || 2519 draw.fRC->isEmpty() || 2520 (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) { 2521 return; 2522 } 2523 2524 SkScalar width = 0; 2525 SkPoint start; 2526 2527 start.set(0, 0); // to avoid warning 2528 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2529 SkPaint::kStrikeThruText_Flag)) { 2530 width = paint.measureText(text, byteLength); 2531 2532 SkScalar offsetX = 0; 2533 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2534 offsetX = SkScalarHalf(width); 2535 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2536 offsetX = width; 2537 } 2538 start.set(x - offsetX, y); 2539 } 2540 2541 if (0 == width) { 2542 return; 2543 } 2544 2545 uint32_t flags = paint.getFlags(); 2546 2547 if (flags & (SkPaint::kUnderlineText_Flag | 2548 SkPaint::kStrikeThruText_Flag)) { 2549 SkScalar textSize = paint.getTextSize(); 2550 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2551 SkRect r; 2552 2553 r.fLeft = start.fX; 2554 r.fRight = start.fX + width; 2555 2556 if (flags & SkPaint::kUnderlineText_Flag) { 2557 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2558 start.fY); 2559 r.fTop = offset; 2560 r.fBottom = offset + height; 2561 DrawRect(draw, paint, r, 1); 2562 } 2563 if (flags & SkPaint::kStrikeThruText_Flag) { 2564 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2565 start.fY); 2566 r.fTop = offset; 2567 r.fBottom = offset + height; 2568 DrawRect(draw, paint, r, 1); 2569 } 2570 } 2571} 2572 2573void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2574 const SkPaint& paint) { 2575 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2576 2577 while (iter.next()) { 2578 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2579 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2580 DrawTextDecorations(iter, dfp.paint(), 2581 static_cast<const char*>(text), byteLength, x, y); 2582 } 2583 2584 LOOPER_END 2585} 2586 2587void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2588 const SkPaint& paint) { 2589 SkPoint textOffset = SkPoint::Make(0, 0); 2590 2591 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2592 2593 while (iter.next()) { 2594 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2595 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2596 dfp.paint()); 2597 } 2598 2599 LOOPER_END 2600} 2601 2602void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2603 SkScalar constY, const SkPaint& paint) { 2604 2605 SkPoint textOffset = SkPoint::Make(0, constY); 2606 2607 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2608 2609 while (iter.next()) { 2610 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2611 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2612 dfp.paint()); 2613 } 2614 2615 LOOPER_END 2616} 2617 2618void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2619 const SkMatrix* matrix, const SkPaint& paint) { 2620 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr) 2621 2622 while (iter.next()) { 2623 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2624 matrix, looper.paint()); 2625 } 2626 2627 LOOPER_END 2628} 2629 2630void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2631 const SkPaint& paint) { 2632 2633 SkRect storage; 2634 const SkRect* bounds = nullptr; 2635 if (paint.canComputeFastBounds()) { 2636 storage = blob->bounds().makeOffset(x, y); 2637 SkRect tmp; 2638 if (this->quickReject(paint.computeFastBounds(storage, &tmp))) { 2639 return; 2640 } 2641 bounds = &storage; 2642 } 2643 2644 // We cannot filter in the looper as we normally do, because the paint is 2645 // incomplete at this point (text-related attributes are embedded within blob run paints). 2646 SkDrawFilter* drawFilter = fMCRec->fFilter; 2647 fMCRec->fFilter = nullptr; 2648 2649 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2650 2651 while (iter.next()) { 2652 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2653 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); 2654 } 2655 2656 LOOPER_END 2657 2658 fMCRec->fFilter = drawFilter; 2659} 2660 2661// These will become non-virtual, so they always call the (virtual) onDraw... method 2662void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2663 const SkPaint& paint) { 2664 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2665 this->onDrawText(text, byteLength, x, y, paint); 2666} 2667void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2668 const SkPaint& paint) { 2669 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2670 this->onDrawPosText(text, byteLength, pos, paint); 2671} 2672void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2673 SkScalar constY, const SkPaint& paint) { 2674 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2675 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2676} 2677void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2678 const SkMatrix* matrix, const SkPaint& paint) { 2679 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2680 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2681} 2682void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2683 const SkPaint& paint) { 2684 RETURN_ON_NULL(blob); 2685 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2686 this->onDrawTextBlob(blob, x, y, paint); 2687} 2688 2689void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 2690 const SkPoint verts[], const SkPoint texs[], 2691 const SkColor colors[], SkXfermode* xmode, 2692 const uint16_t indices[], int indexCount, 2693 const SkPaint& paint) { 2694 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2695 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2696 2697 while (iter.next()) { 2698 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2699 colors, xmode, indices, indexCount, 2700 looper.paint()); 2701 } 2702 2703 LOOPER_END 2704} 2705 2706void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2707 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2708 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2709 if (nullptr == cubics) { 2710 return; 2711 } 2712 2713 // Since a patch is always within the convex hull of the control points, we discard it when its 2714 // bounding rectangle is completely outside the current clip. 2715 SkRect bounds; 2716 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2717 if (this->quickReject(bounds)) { 2718 return; 2719 } 2720 2721 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2722} 2723 2724void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2725 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2726 2727 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr) 2728 2729 while (iter.next()) { 2730 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2731 } 2732 2733 LOOPER_END 2734} 2735 2736void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) { 2737 RETURN_ON_NULL(dr); 2738 if (x || y) { 2739 SkMatrix matrix = SkMatrix::MakeTrans(x, y); 2740 this->onDrawDrawable(dr, &matrix); 2741 } else { 2742 this->onDrawDrawable(dr, nullptr); 2743 } 2744} 2745 2746void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2747 RETURN_ON_NULL(dr); 2748 if (matrix && matrix->isIdentity()) { 2749 matrix = nullptr; 2750 } 2751 this->onDrawDrawable(dr, matrix); 2752} 2753 2754void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) { 2755 SkRect bounds = dr->getBounds(); 2756 if (matrix) { 2757 matrix->mapRect(&bounds); 2758 } 2759 if (this->quickReject(bounds)) { 2760 return; 2761 } 2762 dr->draw(this, matrix); 2763} 2764 2765void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2766 const SkColor colors[], int count, SkXfermode::Mode mode, 2767 const SkRect* cull, const SkPaint* paint) { 2768 if (cull && this->quickReject(*cull)) { 2769 return; 2770 } 2771 2772 SkPaint pnt; 2773 if (paint) { 2774 pnt = *paint; 2775 } 2776 2777 LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr) 2778 while (iter.next()) { 2779 iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt); 2780 } 2781 LOOPER_END 2782} 2783 2784void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { 2785 SkASSERT(key); 2786 2787 SkPaint paint; 2788 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr) 2789 while (iter.next()) { 2790 iter.fDevice->drawAnnotation(iter, rect, key, value); 2791 } 2792 LOOPER_END 2793} 2794 2795////////////////////////////////////////////////////////////////////////////// 2796// These methods are NOT virtual, and therefore must call back into virtual 2797// methods, rather than actually drawing themselves. 2798////////////////////////////////////////////////////////////////////////////// 2799 2800void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2801 SkXfermode::Mode mode) { 2802 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2803 SkPaint paint; 2804 2805 paint.setARGB(a, r, g, b); 2806 if (SkXfermode::kSrcOver_Mode != mode) { 2807 paint.setXfermodeMode(mode); 2808 } 2809 this->drawPaint(paint); 2810} 2811 2812void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2813 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2814 SkPaint paint; 2815 2816 paint.setColor(c); 2817 if (SkXfermode::kSrcOver_Mode != mode) { 2818 paint.setXfermodeMode(mode); 2819 } 2820 this->drawPaint(paint); 2821} 2822 2823void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2824 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2825 SkPoint pt; 2826 2827 pt.set(x, y); 2828 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2829} 2830 2831void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2832 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2833 SkPoint pt; 2834 SkPaint paint; 2835 2836 pt.set(x, y); 2837 paint.setColor(color); 2838 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2839} 2840 2841void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2842 const SkPaint& paint) { 2843 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 2844 SkPoint pts[2]; 2845 2846 pts[0].set(x0, y0); 2847 pts[1].set(x1, y1); 2848 this->drawPoints(kLines_PointMode, 2, pts, paint); 2849} 2850 2851void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2852 SkScalar right, SkScalar bottom, 2853 const SkPaint& paint) { 2854 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 2855 SkRect r; 2856 2857 r.set(left, top, right, bottom); 2858 this->drawRect(r, paint); 2859} 2860 2861void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2862 const SkPaint& paint) { 2863 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 2864 if (radius < 0) { 2865 radius = 0; 2866 } 2867 2868 SkRect r; 2869 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2870 this->drawOval(r, paint); 2871} 2872 2873void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2874 const SkPaint& paint) { 2875 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 2876 if (rx > 0 && ry > 0) { 2877 if (paint.canComputeFastBounds()) { 2878 SkRect storage; 2879 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2880 return; 2881 } 2882 } 2883 SkRRect rrect; 2884 rrect.setRectXY(r, rx, ry); 2885 this->drawRRect(rrect, paint); 2886 } else { 2887 this->drawRect(r, paint); 2888 } 2889} 2890 2891void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2892 SkScalar sweepAngle, bool useCenter, 2893 const SkPaint& paint) { 2894 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2895 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2896 this->drawOval(oval, paint); 2897 } else { 2898 SkPath path; 2899 if (useCenter) { 2900 path.moveTo(oval.centerX(), oval.centerY()); 2901 } 2902 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2903 if (useCenter) { 2904 path.close(); 2905 } 2906 this->drawPath(path, paint); 2907 } 2908} 2909 2910void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2911 const SkPath& path, SkScalar hOffset, 2912 SkScalar vOffset, const SkPaint& paint) { 2913 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 2914 SkMatrix matrix; 2915 2916 matrix.setTranslate(hOffset, vOffset); 2917 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2918} 2919 2920/////////////////////////////////////////////////////////////////////////////// 2921 2922/** 2923 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 2924 * against the playback cost of recursing into the subpicture to get at its actual ops. 2925 * 2926 * For now we pick a conservatively small value, though measurement (and other heuristics like 2927 * the type of ops contained) may justify changing this value. 2928 */ 2929#define kMaxPictureOpsToUnrollInsteadOfRef 1 2930 2931void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2932 RETURN_ON_NULL(picture); 2933 2934 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 2935 if (matrix && matrix->isIdentity()) { 2936 matrix = nullptr; 2937 } 2938 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { 2939 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2940 picture->playback(this); 2941 } else { 2942 this->onDrawPicture(picture, matrix, paint); 2943 } 2944} 2945 2946void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2947 const SkPaint* paint) { 2948 if (!paint || paint->canComputeFastBounds()) { 2949 SkRect bounds = picture->cullRect(); 2950 if (paint) { 2951 paint->computeFastBounds(bounds, &bounds); 2952 } 2953 if (matrix) { 2954 matrix->mapRect(&bounds); 2955 } 2956 if (this->quickReject(bounds)) { 2957 return; 2958 } 2959 } 2960 2961 SkBaseDevice* device = this->getTopDevice(); 2962 if (device) { 2963 // Canvas has to first give the device the opportunity to render 2964 // the picture itself. 2965 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) { 2966 return; // the device has rendered the entire picture 2967 } 2968 } 2969 2970 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2971 picture->playback(this); 2972} 2973 2974/////////////////////////////////////////////////////////////////////////////// 2975/////////////////////////////////////////////////////////////////////////////// 2976 2977SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2978 static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small"); 2979 2980 SkASSERT(canvas); 2981 2982 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2983 fDone = !fImpl->next(); 2984} 2985 2986SkCanvas::LayerIter::~LayerIter() { 2987 fImpl->~SkDrawIter(); 2988} 2989 2990void SkCanvas::LayerIter::next() { 2991 fDone = !fImpl->next(); 2992} 2993 2994SkBaseDevice* SkCanvas::LayerIter::device() const { 2995 return fImpl->getDevice(); 2996} 2997 2998const SkMatrix& SkCanvas::LayerIter::matrix() const { 2999 return fImpl->getMatrix(); 3000} 3001 3002const SkPaint& SkCanvas::LayerIter::paint() const { 3003 const SkPaint* paint = fImpl->getPaint(); 3004 if (nullptr == paint) { 3005 paint = &fDefaultPaint; 3006 } 3007 return *paint; 3008} 3009 3010const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 3011int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 3012int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 3013 3014/////////////////////////////////////////////////////////////////////////////// 3015 3016SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 3017 3018/////////////////////////////////////////////////////////////////////////////// 3019 3020static bool supported_for_raster_canvas(const SkImageInfo& info) { 3021 switch (info.alphaType()) { 3022 case kPremul_SkAlphaType: 3023 case kOpaque_SkAlphaType: 3024 break; 3025 default: 3026 return false; 3027 } 3028 3029 switch (info.colorType()) { 3030 case kAlpha_8_SkColorType: 3031 case kRGB_565_SkColorType: 3032 case kN32_SkColorType: 3033 break; 3034 default: 3035 return false; 3036 } 3037 3038 return true; 3039} 3040 3041SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 3042 if (!supported_for_raster_canvas(info)) { 3043 return nullptr; 3044 } 3045 3046 SkBitmap bitmap; 3047 if (!bitmap.installPixels(info, pixels, rowBytes)) { 3048 return nullptr; 3049 } 3050 return new SkCanvas(bitmap); 3051} 3052 3053/////////////////////////////////////////////////////////////////////////////// 3054 3055SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 3056 const SkPaint* paint, const SkRect& bounds) 3057 : fCanvas(canvas) 3058 , fSaveCount(canvas->getSaveCount()) 3059{ 3060 if (paint) { 3061 SkRect newBounds = bounds; 3062 if (matrix) { 3063 matrix->mapRect(&newBounds); 3064 } 3065 canvas->saveLayer(&newBounds, paint); 3066 } else if (matrix) { 3067 canvas->save(); 3068 } 3069 3070 if (matrix) { 3071 canvas->concat(*matrix); 3072 } 3073} 3074 3075SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 3076 fCanvas->restoreToCount(fSaveCount); 3077} 3078 3079#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API 3080SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 3081 return this->makeSurface(info, props).release(); 3082} 3083#endif 3084