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