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