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