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