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