1 /* 2 * Copyright 2006 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 #ifndef SkCanvas_DEFINED 9 #define SkCanvas_DEFINED 10 11 #include "include/core/SkArc.h" 12 #include "include/core/SkBlendMode.h" 13 #include "include/core/SkClipOp.h" 14 #include "include/core/SkColor.h" 15 #include "include/core/SkFontTypes.h" 16 #include "include/core/SkImageFilter.h" 17 #include "include/core/SkImageInfo.h" 18 #include "include/core/SkM44.h" 19 #include "include/core/SkMatrix.h" 20 #include "include/core/SkPaint.h" 21 #include "include/core/SkPoint.h" 22 #include "include/core/SkRasterHandleAllocator.h" 23 #include "include/core/SkRect.h" 24 #include "include/core/SkRefCnt.h" 25 #include "include/core/SkSamplingOptions.h" 26 #include "include/core/SkScalar.h" 27 #include "include/core/SkSize.h" 28 #include "include/core/SkSpan.h" 29 #include "include/core/SkString.h" 30 #include "include/core/SkSurfaceProps.h" 31 #include "include/core/SkTypes.h" 32 #include "include/private/base/SkCPUTypes.h" 33 #include "include/private/base/SkDeque.h" 34 #include "include/private/base/SkTArray.h" 35 36 #include <cstdint> 37 #include <cstring> 38 #include <memory> 39 #include <optional> 40 41 #ifndef SK_SUPPORT_LEGACY_GETTOTALMATRIX 42 #define SK_SUPPORT_LEGACY_GETTOTALMATRIX 43 #endif 44 45 namespace sktext { 46 class GlyphRunBuilder; 47 class GlyphRunList; 48 } 49 50 class AutoLayerForImageFilter; 51 class GrRecordingContext; 52 53 class SkBitmap; 54 class SkBlender; 55 class SkColorSpace; 56 class SkData; 57 class SkDevice; 58 class SkDrawable; 59 class SkFont; 60 class SkImage; 61 class SkMesh; 62 class SkPaintFilterCanvas; 63 class SkPath; 64 class SkPicture; 65 class SkPixmap; 66 class SkRRect; 67 class SkRegion; 68 class SkShader; 69 class SkSpecialImage; 70 class SkSurface; 71 class SkSurface_Base; 72 class SkTextBlob; 73 class SkVertices; 74 struct SkDrawShadowRec; 75 struct SkRSXform; 76 77 template<typename E> 78 class SkEnumBitMask; 79 80 namespace skgpu::graphite { class Recorder; } 81 namespace sktext::gpu { class Slug; } 82 namespace SkRecords { class Draw; } 83 84 /** \class SkCanvas 85 SkCanvas provides an interface for drawing, and how the drawing is clipped and transformed. 86 SkCanvas contains a stack of SkMatrix and clip values. 87 88 SkCanvas and SkPaint together provide the state to draw into SkSurface or SkDevice. 89 Each SkCanvas draw call transforms the geometry of the object by the concatenation of all 90 SkMatrix values in the stack. The transformed geometry is clipped by the intersection 91 of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing 92 state such as color, SkTypeface, text size, stroke width, SkShader and so on. 93 94 To draw to a pixel-based destination, create raster surface or GPU surface. 95 Request SkCanvas from SkSurface to obtain the interface to draw. 96 SkCanvas generated by raster surface draws to memory visible to the CPU. 97 SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU. 98 99 To draw to a document, obtain SkCanvas from SVG canvas, document PDF, or SkPictureRecorder. 100 SkDocument based SkCanvas and other SkCanvas subclasses reference SkDevice describing the 101 destination. 102 103 SkCanvas can be constructed to draw to SkBitmap without first creating raster surface. 104 This approach may be deprecated in the future. 105 */ 106 class SK_API SkCanvas { 107 public: 108 109 /** Allocates raster SkCanvas that will draw directly into pixels. 110 111 SkCanvas is returned if all parameters are valid. 112 Valid parameters include: 113 info dimensions are zero or positive; 114 info contains SkColorType and SkAlphaType supported by raster surface; 115 pixels is not nullptr; 116 rowBytes is zero or large enough to contain info width pixels of SkColorType. 117 118 Pass zero for rowBytes to compute rowBytes from info width and size of pixel. 119 If rowBytes is greater than zero, it must be equal to or greater than 120 info width times bytes required for SkColorType. 121 122 Pixel buffer size should be info height times computed rowBytes. 123 Pixels are not initialized. 124 To access pixels after drawing, call flush() or peekPixels(). 125 126 @param info width, height, SkColorType, SkAlphaType, SkColorSpace, of raster surface; 127 width, or height, or both, may be zero 128 @param pixels pointer to destination pixels buffer 129 @param rowBytes interval from one SkSurface row to the next, or zero 130 @param props LCD striping orientation and setting for device independent fonts; 131 may be nullptr 132 @return SkCanvas if all parameters are valid; otherwise, nullptr 133 */ 134 static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels, 135 size_t rowBytes, 136 const SkSurfaceProps* props = nullptr); 137 138 /** Allocates raster SkCanvas specified by inline image specification. Subsequent SkCanvas 139 calls draw into pixels. 140 SkColorType is set to kN32_SkColorType. 141 SkAlphaType is set to kPremul_SkAlphaType. 142 To access pixels after drawing, call flush() or peekPixels(). 143 144 SkCanvas is returned if all parameters are valid. 145 Valid parameters include: 146 width and height are zero or positive; 147 pixels is not nullptr; 148 rowBytes is zero or large enough to contain width pixels of kN32_SkColorType. 149 150 Pass zero for rowBytes to compute rowBytes from width and size of pixel. 151 If rowBytes is greater than zero, it must be equal to or greater than 152 width times bytes required for SkColorType. 153 154 Pixel buffer size should be height times rowBytes. 155 156 @param width pixel column count on raster surface created; must be zero or greater 157 @param height pixel row count on raster surface created; must be zero or greater 158 @param pixels pointer to destination pixels buffer; buffer size should be height 159 times rowBytes 160 @param rowBytes interval from one SkSurface row to the next, or zero 161 @return SkCanvas if all parameters are valid; otherwise, nullptr 162 */ MakeRasterDirectN32(int width,int height,SkPMColor * pixels,size_t rowBytes)163 static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels, 164 size_t rowBytes) { 165 return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes); 166 } 167 168 /** Creates an empty SkCanvas with no backing device or pixels, with 169 a width and height of zero. 170 171 @return empty SkCanvas 172 173 example: https://fiddle.skia.org/c/@Canvas_empty_constructor 174 */ 175 SkCanvas(); 176 177 /** Creates SkCanvas of the specified dimensions without a SkSurface. 178 Used by subclasses with custom implementations for draw member functions. 179 180 If props equals nullptr, SkSurfaceProps are created with 181 SkSurfaceProps::InitType settings, which choose the pixel striping 182 direction and order. Since a platform may dynamically change its direction when 183 the device is rotated, and since a platform may have multiple monitors with 184 different characteristics, it is best not to rely on this legacy behavior. 185 186 @param width zero or greater 187 @param height zero or greater 188 @param props LCD striping orientation and setting for device independent fonts; 189 may be nullptr 190 @return SkCanvas placeholder with dimensions 191 192 example: https://fiddle.skia.org/c/@Canvas_int_int_const_SkSurfaceProps_star 193 */ 194 SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr); 195 196 /** Private. For internal use only. 197 */ 198 explicit SkCanvas(sk_sp<SkDevice> device); 199 200 /** Constructs a canvas that draws into bitmap. 201 Sets kUnknown_SkPixelGeometry in constructed SkSurface. 202 203 SkBitmap is copied so that subsequently editing bitmap will not affect 204 constructed SkCanvas. 205 206 May be deprecated in the future. 207 208 @param bitmap width, height, SkColorType, SkAlphaType, and pixel 209 storage of raster surface 210 @return SkCanvas that can be used to draw into bitmap 211 212 example: https://fiddle.skia.org/c/@Canvas_copy_const_SkBitmap 213 */ 214 explicit SkCanvas(const SkBitmap& bitmap); 215 216 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 217 /** Private. 218 */ 219 enum class ColorBehavior { 220 kLegacy, //!< placeholder 221 }; 222 223 /** Private. For use by Android framework only. 224 225 @param bitmap specifies a bitmap for the canvas to draw into 226 @param behavior specializes this constructor; value is unused 227 @return SkCanvas that can be used to draw into bitmap 228 */ 229 SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior); 230 #endif 231 232 /** Constructs a canvas that draws into bitmap. 233 Use props to match the device characteristics, like LCD striping. 234 235 bitmap is copied so that subsequently editing bitmap will not affect 236 constructed SkCanvas. 237 238 @param bitmap width, height, SkColorType, SkAlphaType, 239 and pixel storage of raster surface 240 @param props order and orientation of RGB striping; and whether to use 241 device independent fonts 242 @return SkCanvas that can be used to draw into bitmap 243 244 example: https://fiddle.skia.org/c/@Canvas_const_SkBitmap_const_SkSurfaceProps 245 */ 246 SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props); 247 248 /** Draws saved layers, if any. 249 Frees up resources used by SkCanvas. 250 251 example: https://fiddle.skia.org/c/@Canvas_destructor 252 */ 253 virtual ~SkCanvas(); 254 255 /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or 256 GPU surface, returned SkColorType is set to kUnknown_SkColorType. 257 258 @return dimensions and SkColorType of SkCanvas 259 260 example: https://fiddle.skia.org/c/@Canvas_imageInfo 261 */ 262 SkImageInfo imageInfo() const; 263 264 /** Copies SkSurfaceProps, if SkCanvas is associated with raster surface or 265 GPU surface, and returns true. Otherwise, returns false and leave props unchanged. 266 267 @param props storage for writable SkSurfaceProps 268 @return true if SkSurfaceProps was copied 269 270 DEPRECATED: Replace usage with getBaseProps() or getTopProps() 271 272 example: https://fiddle.skia.org/c/@Canvas_getProps 273 */ 274 bool getProps(SkSurfaceProps* props) const; 275 276 /** Returns the SkSurfaceProps associated with the canvas (i.e., at the base of the layer 277 stack). 278 279 @return base SkSurfaceProps 280 */ 281 SkSurfaceProps getBaseProps() const; 282 283 /** Returns the SkSurfaceProps associated with the canvas that are currently active (i.e., at 284 the top of the layer stack). This can differ from getBaseProps depending on the flags 285 passed to saveLayer (see SaveLayerFlagsSet). 286 287 @return SkSurfaceProps active in the current/top layer 288 */ 289 SkSurfaceProps getTopProps() const; 290 291 /** Gets the size of the base or root layer in global canvas coordinates. The 292 origin of the base layer is always (0,0). The area available for drawing may be 293 smaller (due to clipping or saveLayer). 294 295 @return integral width and height of base layer 296 297 example: https://fiddle.skia.org/c/@Canvas_getBaseLayerSize 298 */ 299 virtual SkISize getBaseLayerSize() const; 300 301 /** Creates SkSurface matching info and props, and associates it with SkCanvas. 302 Returns nullptr if no match found. 303 304 If props is nullptr, matches SkSurfaceProps in SkCanvas. If props is nullptr and SkCanvas 305 does not have SkSurfaceProps, creates SkSurface with default SkSurfaceProps. 306 307 @param info width, height, SkColorType, SkAlphaType, and SkColorSpace 308 @param props SkSurfaceProps to match; may be nullptr to match SkCanvas 309 @return SkSurface matching info and props, or nullptr if no match is available 310 311 example: https://fiddle.skia.org/c/@Canvas_makeSurface 312 */ 313 sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr); 314 315 /** Returns Ganesh context of the GPU surface associated with SkCanvas. 316 317 @return GPU context, if available; nullptr otherwise 318 319 example: https://fiddle.skia.org/c/@Canvas_recordingContext 320 */ 321 virtual GrRecordingContext* recordingContext() const; 322 323 324 /** Returns Recorder for the GPU surface associated with SkCanvas. 325 326 @return Recorder, if available; nullptr otherwise 327 */ 328 virtual skgpu::graphite::Recorder* recorder() const; 329 330 /** Sometimes a canvas is owned by a surface. If it is, getSurface() will return a bare 331 * pointer to that surface, else this will return nullptr. 332 */ 333 SkSurface* getSurface() const; 334 335 /** Returns the pixel base address, SkImageInfo, rowBytes, and origin if the pixels 336 can be read directly. The returned address is only valid 337 while SkCanvas is in scope and unchanged. Any SkCanvas call or SkSurface call 338 may invalidate the returned address and other returned values. 339 340 If pixels are inaccessible, info, rowBytes, and origin are unchanged. 341 342 @param info storage for writable pixels' SkImageInfo; may be nullptr 343 @param rowBytes storage for writable pixels' row bytes; may be nullptr 344 @param origin storage for SkCanvas top layer origin, its top-left corner; 345 may be nullptr 346 @return address of pixels, or nullptr if inaccessible 347 348 example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_a 349 example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_b 350 */ 351 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr); 352 353 /** Returns custom context that tracks the SkMatrix and clip. 354 355 Use SkRasterHandleAllocator to blend Skia drawing with custom drawing, typically performed 356 by the host platform user interface. The custom context returned is generated by 357 SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for 358 the drawing destination. 359 360 @return context of custom allocation 361 362 example: https://fiddle.skia.org/c/@Canvas_accessTopRasterHandle 363 */ 364 SkRasterHandleAllocator::Handle accessTopRasterHandle() const; 365 366 /** Returns true if SkCanvas has direct access to its pixels. 367 368 Pixels are readable when SkDevice is raster. Pixels are not readable when SkCanvas 369 is returned from GPU surface, returned by SkDocument::beginPage, returned by 370 SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility class 371 like DebugCanvas. 372 373 pixmap is valid only while SkCanvas is in scope and unchanged. Any 374 SkCanvas or SkSurface call may invalidate the pixmap values. 375 376 @param pixmap storage for pixel state if pixels are readable; otherwise, ignored 377 @return true if SkCanvas has direct access to pixels 378 379 example: https://fiddle.skia.org/c/@Canvas_peekPixels 380 */ 381 bool peekPixels(SkPixmap* pixmap); 382 383 /** Copies SkRect of pixels from SkCanvas into dstPixels. SkMatrix and clip are 384 ignored. 385 386 Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 387 Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()). 388 Copies each readable pixel intersecting both rectangles, without scaling, 389 converting to dstInfo.colorType() and dstInfo.alphaType() if required. 390 391 Pixels are readable when SkDevice is raster, or backed by a GPU. 392 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 393 returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility 394 class like DebugCanvas. 395 396 The destination pixel storage must be allocated by the caller. 397 398 Pixel values are converted only if SkColorType and SkAlphaType 399 do not match. Only pixels within both source and destination rectangles 400 are copied. dstPixels contents outside SkRect intersection are unchanged. 401 402 Pass negative values for srcX or srcY to offset pixels across or down destination. 403 404 Does not copy, and returns false if: 405 - Source and destination rectangles do not intersect. 406 - SkCanvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). 407 - SkCanvas pixels are not readable; for instance, SkCanvas is document-based. 408 - dstRowBytes is too small to contain one row of pixels. 409 410 @param dstInfo width, height, SkColorType, and SkAlphaType of dstPixels 411 @param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger 412 @param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger 413 @param srcX offset into readable pixels on x-axis; may be negative 414 @param srcY offset into readable pixels on y-axis; may be negative 415 @return true if pixels were copied 416 */ 417 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 418 int srcX, int srcY); 419 420 /** Copies SkRect of pixels from SkCanvas into pixmap. SkMatrix and clip are 421 ignored. 422 423 Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 424 Destination SkRect corners are (0, 0) and (pixmap.width(), pixmap.height()). 425 Copies each readable pixel intersecting both rectangles, without scaling, 426 converting to pixmap.colorType() and pixmap.alphaType() if required. 427 428 Pixels are readable when SkDevice is raster, or backed by a GPU. 429 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 430 returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility 431 class like DebugCanvas. 432 433 Caller must allocate pixel storage in pixmap if needed. 434 435 Pixel values are converted only if SkColorType and SkAlphaType 436 do not match. Only pixels within both source and destination SkRect 437 are copied. pixmap pixels contents outside SkRect intersection are unchanged. 438 439 Pass negative values for srcX or srcY to offset pixels across or down pixmap. 440 441 Does not copy, and returns false if: 442 - Source and destination rectangles do not intersect. 443 - SkCanvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). 444 - SkCanvas pixels are not readable; for instance, SkCanvas is document-based. 445 - SkPixmap pixels could not be allocated. 446 - pixmap.rowBytes() is too small to contain one row of pixels. 447 448 @param pixmap storage for pixels copied from SkCanvas 449 @param srcX offset into readable pixels on x-axis; may be negative 450 @param srcY offset into readable pixels on y-axis; may be negative 451 @return true if pixels were copied 452 453 example: https://fiddle.skia.org/c/@Canvas_readPixels_2 454 */ 455 bool readPixels(const SkPixmap& pixmap, int srcX, int srcY); 456 457 /** Copies SkRect of pixels from SkCanvas into bitmap. SkMatrix and clip are 458 ignored. 459 460 Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 461 Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()). 462 Copies each readable pixel intersecting both rectangles, without scaling, 463 converting to bitmap.colorType() and bitmap.alphaType() if required. 464 465 Pixels are readable when SkDevice is raster, or backed by a GPU. 466 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 467 returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility 468 class like DebugCanvas. 469 470 Caller must allocate pixel storage in bitmap if needed. 471 472 SkBitmap values are converted only if SkColorType and SkAlphaType 473 do not match. Only pixels within both source and destination rectangles 474 are copied. SkBitmap pixels outside SkRect intersection are unchanged. 475 476 Pass negative values for srcX or srcY to offset pixels across or down bitmap. 477 478 Does not copy, and returns false if: 479 - Source and destination rectangles do not intersect. 480 - SkCanvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). 481 - SkCanvas pixels are not readable; for instance, SkCanvas is document-based. 482 - bitmap pixels could not be allocated. 483 - bitmap.rowBytes() is too small to contain one row of pixels. 484 485 @param bitmap storage for pixels copied from SkCanvas 486 @param srcX offset into readable pixels on x-axis; may be negative 487 @param srcY offset into readable pixels on y-axis; may be negative 488 @return true if pixels were copied 489 490 example: https://fiddle.skia.org/c/@Canvas_readPixels_3 491 */ 492 bool readPixels(const SkBitmap& bitmap, int srcX, int srcY); 493 494 /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored. 495 Source SkRect corners are (0, 0) and (info.width(), info.height()). 496 Destination SkRect corners are (x, y) and 497 (imageInfo().width(), imageInfo().height()). 498 499 Copies each readable pixel intersecting both rectangles, without scaling, 500 converting to imageInfo().colorType() and imageInfo().alphaType() if required. 501 502 Pixels are writable when SkDevice is raster, or backed by a GPU. 503 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage, 504 returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility 505 class like DebugCanvas. 506 507 Pixel values are converted only if SkColorType and SkAlphaType 508 do not match. Only pixels within both source and destination rectangles 509 are copied. SkCanvas pixels outside SkRect intersection are unchanged. 510 511 Pass negative values for x or y to offset pixels to the left or 512 above SkCanvas pixels. 513 514 Does not copy, and returns false if: 515 - Source and destination rectangles do not intersect. 516 - pixels could not be converted to SkCanvas imageInfo().colorType() or 517 imageInfo().alphaType(). 518 - SkCanvas pixels are not writable; for instance, SkCanvas is document-based. 519 - rowBytes is too small to contain one row of pixels. 520 521 @param info width, height, SkColorType, and SkAlphaType of pixels 522 @param pixels pixels to copy, of size info.height() times rowBytes, or larger 523 @param rowBytes size of one row of pixels; info.width() times pixel size, or larger 524 @param x offset into SkCanvas writable pixels on x-axis; may be negative 525 @param y offset into SkCanvas writable pixels on y-axis; may be negative 526 @return true if pixels were written to SkCanvas 527 528 example: https://fiddle.skia.org/c/@Canvas_writePixels 529 */ 530 bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y); 531 532 /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored. 533 Source SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()). 534 535 Destination SkRect corners are (x, y) and 536 (imageInfo().width(), imageInfo().height()). 537 538 Copies each readable pixel intersecting both rectangles, without scaling, 539 converting to imageInfo().colorType() and imageInfo().alphaType() if required. 540 541 Pixels are writable when SkDevice is raster, or backed by a GPU. 542 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage, 543 returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility 544 class like DebugCanvas. 545 546 Pixel values are converted only if SkColorType and SkAlphaType 547 do not match. Only pixels within both source and destination rectangles 548 are copied. SkCanvas pixels outside SkRect intersection are unchanged. 549 550 Pass negative values for x or y to offset pixels to the left or 551 above SkCanvas pixels. 552 553 Does not copy, and returns false if: 554 - Source and destination rectangles do not intersect. 555 - bitmap does not have allocated pixels. 556 - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or 557 imageInfo().alphaType(). 558 - SkCanvas pixels are not writable; for instance, SkCanvas is document based. 559 - bitmap pixels are inaccessible; for instance, bitmap wraps a texture. 560 561 @param bitmap contains pixels copied to SkCanvas 562 @param x offset into SkCanvas writable pixels on x-axis; may be negative 563 @param y offset into SkCanvas writable pixels on y-axis; may be negative 564 @return true if pixels were written to SkCanvas 565 566 example: https://fiddle.skia.org/c/@Canvas_writePixels_2 567 example: https://fiddle.skia.org/c/@State_Stack_a 568 example: https://fiddle.skia.org/c/@State_Stack_b 569 */ 570 bool writePixels(const SkBitmap& bitmap, int x, int y); 571 572 /** Saves SkMatrix and clip. 573 Calling restore() discards changes to SkMatrix and clip, 574 restoring the SkMatrix and clip to their state when save() was called. 575 576 SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix(), 577 and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), clipPath(), clipRegion(). 578 579 Saved SkCanvas state is put on a stack; multiple calls to save() should be balance 580 by an equal number of calls to restore(). 581 582 Call restoreToCount() with result to restore this and subsequent saves. 583 584 @return depth of saved stack 585 586 example: https://fiddle.skia.org/c/@Canvas_save 587 */ 588 int save(); 589 590 /** Saves SkMatrix and clip, and allocates a SkSurface for subsequent drawing. 591 Calling restore() discards changes to SkMatrix and clip, and draws the SkSurface. 592 593 SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), 594 setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), 595 clipPath(), clipRegion(). 596 597 SkRect bounds suggests but does not define the SkSurface size. To clip drawing to 598 a specific rectangle, use clipRect(). 599 600 Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and 601 SkBlendMode when restore() is called. 602 603 Call restoreToCount() with returned value to restore this and subsequent saves. 604 605 @param bounds hint to limit the size of the layer; may be nullptr 606 @param paint graphics state for layer; may be nullptr 607 @return depth of saved stack 608 609 example: https://fiddle.skia.org/c/@Canvas_saveLayer 610 example: https://fiddle.skia.org/c/@Canvas_saveLayer_4 611 */ 612 int saveLayer(const SkRect* bounds, const SkPaint* paint); 613 614 /** Saves SkMatrix and clip, and allocates a SkSurface for subsequent drawing. 615 Calling restore() discards changes to SkMatrix and clip, and draws the SkSurface. 616 617 SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), 618 setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), 619 clipPath(), clipRegion(). 620 621 SkRect bounds suggests but does not define the layer size. To clip drawing to 622 a specific rectangle, use clipRect(). 623 624 Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and 625 SkBlendMode when restore() is called. 626 627 Call restoreToCount() with returned value to restore this and subsequent saves. 628 629 @param bounds hint to limit the size of layer; may be nullptr 630 @param paint graphics state for layer; may be nullptr 631 @return depth of saved stack 632 */ saveLayer(const SkRect & bounds,const SkPaint * paint)633 int saveLayer(const SkRect& bounds, const SkPaint* paint) { 634 return this->saveLayer(&bounds, paint); 635 } 636 637 /** Saves SkMatrix and clip, and allocates SkSurface for subsequent drawing. 638 639 Calling restore() discards changes to SkMatrix and clip, 640 and blends layer with alpha opacity onto prior layer. 641 642 SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), 643 setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), 644 clipPath(), clipRegion(). 645 646 SkRect bounds suggests but does not define layer size. To clip drawing to 647 a specific rectangle, use clipRect(). 648 649 alpha of zero is fully transparent, 1.0f is fully opaque. 650 651 Call restoreToCount() with returned value to restore this and subsequent saves. 652 653 @param bounds hint to limit the size of layer; may be nullptr 654 @param alpha opacity of layer 655 @return depth of saved stack 656 657 example: https://fiddle.skia.org/c/@Canvas_saveLayerAlpha 658 */ 659 int saveLayerAlphaf(const SkRect* bounds, float alpha); 660 // Helper that accepts an int between 0 and 255, and divides it by 255.0 saveLayerAlpha(const SkRect * bounds,U8CPU alpha)661 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 662 return this->saveLayerAlphaf(bounds, alpha * (1.0f / 255)); 663 } 664 665 /** \enum SkCanvas::SaveLayerFlagsSet 666 SaveLayerFlags provides options that may be used in any combination in SaveLayerRec, 667 defining how layer allocated by saveLayer() operates. It may be set to zero, 668 kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags. 669 */ 670 enum SaveLayerFlagsSet { 671 kPreserveLCDText_SaveLayerFlag = 1 << 1, 672 kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents 673 // instead of matching previous layer's colortype, use F16 674 kF16ColorType = 1 << 4, 675 }; 676 677 using SaveLayerFlags = uint32_t; 678 using FilterSpan = SkSpan<sk_sp<SkImageFilter>>; 679 static constexpr int kMaxFiltersPerLayer = 16; 680 681 /** \struct SkCanvas::SaveLayerRec 682 SaveLayerRec contains the state used to create the layer. 683 */ 684 struct SaveLayerRec { 685 /** Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags. 686 687 @return empty SaveLayerRec 688 */ SaveLayerRecSaveLayerRec689 SaveLayerRec() {} 690 691 /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr. 692 693 @param bounds layer dimensions; may be nullptr 694 @param paint applied to layer when overlaying prior layer; may be nullptr 695 @param saveLayerFlags SaveLayerRec options to modify layer 696 @return SaveLayerRec with empty fBackdrop 697 */ 698 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0) 699 : SaveLayerRec(bounds, paint, nullptr, nullptr, 1.f, saveLayerFlags, /*filters=*/{}) {} 700 701 /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags. 702 703 @param bounds layer dimensions; may be nullptr 704 @param paint applied to layer when overlaying prior layer; 705 may be nullptr 706 @param backdrop If not null, this causes the current layer to be filtered by 707 backdrop, and then drawn into the new layer 708 (respecting the current clip). 709 If null, the new layer is initialized with transparent-black. 710 @param saveLayerFlags SaveLayerRec options to modify layer 711 @return SaveLayerRec fully specified 712 */ SaveLayerRecSaveLayerRec713 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, 714 SaveLayerFlags saveLayerFlags) 715 : SaveLayerRec(bounds, paint, backdrop, nullptr, 1.f, saveLayerFlags, /*filters=*/{}) {} 716 717 /** Sets fBounds, fColorSpace, and fSaveLayerFlags. 718 719 @param bounds layer dimensions; may be nullptr 720 @param paint applied to layer when overlaying prior layer; 721 may be nullptr 722 @param backdrop If not null, this causes the current layer to be filtered by 723 backdrop, and then drawn into the new layer 724 (respecting the current clip). 725 If null, the new layer is initialized with transparent-black. 726 @param colorSpace If not null, when the layer is restored, a color space 727 conversion will be applied from this color space to the 728 parent's color space. The restore paint and backdrop filters will 729 be applied in this color space. 730 If null, the new layer will inherit the color space from its 731 parent. 732 @param saveLayerFlags SaveLayerRec options to modify layer 733 @return SaveLayerRec fully specified 734 */ SaveLayerRecSaveLayerRec735 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, 736 const SkColorSpace* colorSpace, SaveLayerFlags saveLayerFlags) 737 : SaveLayerRec(bounds, paint, backdrop, colorSpace, 1.f, saveLayerFlags, /*filters=*/{}) {} 738 739 /** hints at layer size limit */ 740 const SkRect* fBounds = nullptr; 741 742 /** modifies overlay */ 743 const SkPaint* fPaint = nullptr; 744 745 FilterSpan fFilters = {}; 746 747 /** 748 * If not null, this triggers the same initialization behavior as setting 749 * kInitWithPrevious_SaveLayerFlag on fSaveLayerFlags: the current layer is copied into 750 * the new layer, rather than initializing the new layer with transparent-black. 751 * This is then filtered by fBackdrop (respecting the current clip). 752 */ 753 const SkImageFilter* fBackdrop = nullptr; 754 755 /** 756 * If not null, this triggers a color space conversion when the layer is restored. It 757 * will be as if the layer's contents are drawn in this color space. Filters from 758 * fBackdrop and fPaint will be applied in this color space. 759 */ 760 const SkColorSpace* fColorSpace = nullptr; 761 762 /** preserves LCD text, creates with prior layer contents */ 763 SaveLayerFlags fSaveLayerFlags = 0; 764 765 private: 766 friend class SkCanvas; 767 friend class SkCanvasPriv; 768 SaveLayerRecSaveLayerRec769 SaveLayerRec(const SkRect* bounds, 770 const SkPaint* paint, 771 const SkImageFilter* backdrop, 772 const SkColorSpace* colorSpace, 773 SkScalar backdropScale, 774 SaveLayerFlags saveLayerFlags, 775 FilterSpan filters) 776 : fBounds(bounds) 777 , fPaint(paint) 778 , fFilters(filters) 779 , fBackdrop(backdrop) 780 , fColorSpace(colorSpace) 781 , fSaveLayerFlags(saveLayerFlags) 782 , fExperimentalBackdropScale(backdropScale) { 783 // We only allow the paint's image filter or the side-car list of filters -- not both. 784 SkASSERT(fFilters.empty() || !paint || !paint->getImageFilter()); 785 // To keep things reasonable (during deserialization), we limit filter list size. 786 SkASSERT(fFilters.size() <= kMaxFiltersPerLayer); 787 } 788 789 // Relative scale factor that the image content used to initialize the layer when the 790 // kInitFromPrevious flag or a backdrop filter is used. 791 SkScalar fExperimentalBackdropScale = 1.f; 792 }; 793 794 /** Saves SkMatrix and clip, and allocates SkSurface for subsequent drawing. 795 796 Calling restore() discards changes to SkMatrix and clip, 797 and blends SkSurface with alpha opacity onto the prior layer. 798 799 SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), 800 setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), 801 clipPath(), clipRegion(). 802 803 SaveLayerRec contains the state used to create the layer. 804 805 Call restoreToCount() with returned value to restore this and subsequent saves. 806 807 @param layerRec layer state 808 @return depth of save state stack before this call was made. 809 810 example: https://fiddle.skia.org/c/@Canvas_saveLayer_3 811 */ 812 int saveLayer(const SaveLayerRec& layerRec); 813 814 /** Removes changes to SkMatrix and clip since SkCanvas state was 815 last saved. The state is removed from the stack. 816 817 Does nothing if the stack is empty. 818 819 example: https://fiddle.skia.org/c/@AutoCanvasRestore_restore 820 821 example: https://fiddle.skia.org/c/@Canvas_restore 822 */ 823 void restore(); 824 825 /** Returns the number of saved states, each containing: SkMatrix and clip. 826 Equals the number of save() calls less the number of restore() calls plus one. 827 The save count of a new canvas is one. 828 829 @return depth of save state stack 830 831 example: https://fiddle.skia.org/c/@Canvas_getSaveCount 832 */ 833 int getSaveCount() const; 834 835 /** Restores state to SkMatrix and clip values when save(), saveLayer(), 836 saveLayerPreserveLCDTextRequests(), or saveLayerAlpha() returned saveCount. 837 838 Does nothing if saveCount is greater than state stack count. 839 Restores state to initial values if saveCount is less than or equal to one. 840 841 @param saveCount depth of state stack to restore 842 843 example: https://fiddle.skia.org/c/@Canvas_restoreToCount 844 */ 845 void restoreToCount(int saveCount); 846 847 /** Translates SkMatrix by dx along the x-axis and dy along the y-axis. 848 849 Mathematically, replaces SkMatrix with a translation matrix 850 premultiplied with SkMatrix. 851 852 This has the effect of moving the drawing by (dx, dy) before transforming 853 the result with SkMatrix. 854 855 @param dx distance to translate on x-axis 856 @param dy distance to translate on y-axis 857 858 example: https://fiddle.skia.org/c/@Canvas_translate 859 */ 860 void translate(SkScalar dx, SkScalar dy); 861 862 /** Scales SkMatrix by sx on the x-axis and sy on the y-axis. 863 864 Mathematically, replaces SkMatrix with a scale matrix 865 premultiplied with SkMatrix. 866 867 This has the effect of scaling the drawing by (sx, sy) before transforming 868 the result with SkMatrix. 869 870 @param sx amount to scale on x-axis 871 @param sy amount to scale on y-axis 872 873 example: https://fiddle.skia.org/c/@Canvas_scale 874 */ 875 void scale(SkScalar sx, SkScalar sy); 876 877 /** Rotates SkMatrix by degrees. Positive degrees rotates clockwise. 878 879 Mathematically, replaces SkMatrix with a rotation matrix 880 premultiplied with SkMatrix. 881 882 This has the effect of rotating the drawing by degrees before transforming 883 the result with SkMatrix. 884 885 @param degrees amount to rotate, in degrees 886 887 example: https://fiddle.skia.org/c/@Canvas_rotate 888 */ 889 void rotate(SkScalar degrees); 890 891 /** Rotates SkMatrix by degrees about a point at (px, py). Positive degrees rotates 892 clockwise. 893 894 Mathematically, constructs a rotation matrix; premultiplies the rotation matrix by 895 a translation matrix; then replaces SkMatrix with the resulting matrix 896 premultiplied with SkMatrix. 897 898 This has the effect of rotating the drawing about a given point before 899 transforming the result with SkMatrix. 900 901 @param degrees amount to rotate, in degrees 902 @param px x-axis value of the point to rotate about 903 @param py y-axis value of the point to rotate about 904 905 example: https://fiddle.skia.org/c/@Canvas_rotate_2 906 */ 907 void rotate(SkScalar degrees, SkScalar px, SkScalar py); 908 909 /** Skews SkMatrix by sx on the x-axis and sy on the y-axis. A positive value of sx 910 skews the drawing right as y-axis values increase; a positive value of sy skews 911 the drawing down as x-axis values increase. 912 913 Mathematically, replaces SkMatrix with a skew matrix premultiplied with SkMatrix. 914 915 This has the effect of skewing the drawing by (sx, sy) before transforming 916 the result with SkMatrix. 917 918 @param sx amount to skew on x-axis 919 @param sy amount to skew on y-axis 920 921 example: https://fiddle.skia.org/c/@Canvas_skew 922 */ 923 void skew(SkScalar sx, SkScalar sy); 924 925 /** Replaces SkMatrix with matrix premultiplied with existing SkMatrix. 926 927 This has the effect of transforming the drawn geometry by matrix, before 928 transforming the result with existing SkMatrix. 929 930 @param matrix matrix to premultiply with existing SkMatrix 931 932 example: https://fiddle.skia.org/c/@Canvas_concat 933 */ 934 void concat(const SkMatrix& matrix); 935 void concat(const SkM44&); 936 937 /** Replaces SkMatrix with matrix. 938 Unlike concat(), any prior matrix state is overwritten. 939 940 @param matrix matrix to copy, replacing existing SkMatrix 941 942 example: https://fiddle.skia.org/c/@Canvas_setMatrix 943 */ 944 void setMatrix(const SkM44& matrix); 945 946 // DEPRECATED -- use SkM44 version 947 void setMatrix(const SkMatrix& matrix); 948 949 /** Sets SkMatrix to the identity matrix. 950 Any prior matrix state is overwritten. 951 952 example: https://fiddle.skia.org/c/@Canvas_resetMatrix 953 */ 954 void resetMatrix(); 955 956 /** Replaces clip with the intersection or difference of clip and rect, 957 with an aliased or anti-aliased clip edge. rect is transformed by SkMatrix 958 before it is combined with clip. 959 960 @param rect SkRect to combine with clip 961 @param op SkClipOp to apply to clip 962 @param doAntiAlias true if clip is to be anti-aliased 963 964 example: https://fiddle.skia.org/c/@Canvas_clipRect 965 */ 966 void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias); 967 968 /** Replaces clip with the intersection or difference of clip and rect. 969 Resulting clip is aliased; pixels are fully contained by the clip. 970 rect is transformed by SkMatrix before it is combined with clip. 971 972 @param rect SkRect to combine with clip 973 @param op SkClipOp to apply to clip 974 */ clipRect(const SkRect & rect,SkClipOp op)975 void clipRect(const SkRect& rect, SkClipOp op) { 976 this->clipRect(rect, op, false); 977 } 978 979 /** Replaces clip with the intersection of clip and rect. 980 Resulting clip is aliased; pixels are fully contained by the clip. 981 rect is transformed by SkMatrix 982 before it is combined with clip. 983 984 @param rect SkRect to combine with clip 985 @param doAntiAlias true if clip is to be anti-aliased 986 */ 987 void clipRect(const SkRect& rect, bool doAntiAlias = false) { 988 this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias); 989 } 990 991 void clipIRect(const SkIRect& irect, SkClipOp op = SkClipOp::kIntersect) { 992 this->clipRect(SkRect::Make(irect), op, false); 993 } 994 995 /** Sets the maximum clip rectangle, which can be set by clipRect(), clipRRect() and 996 clipPath() and intersect the current clip with the specified rect. 997 The maximum clip affects only future clipping operations; it is not retroactive. 998 The clip restriction is not recorded in pictures. 999 1000 Pass an empty rect to disable maximum clip. 1001 This private API is for use by Android framework only. 1002 1003 DEPRECATED: Replace usage with SkAndroidFrameworkUtils::replaceClip() 1004 1005 @param rect maximum allowed clip in device coordinates 1006 */ 1007 void androidFramework_setDeviceClipRestriction(const SkIRect& rect); 1008 1009 /** Replaces clip with the intersection or difference of clip and rrect, 1010 with an aliased or anti-aliased clip edge. 1011 rrect is transformed by SkMatrix 1012 before it is combined with clip. 1013 1014 @param rrect SkRRect to combine with clip 1015 @param op SkClipOp to apply to clip 1016 @param doAntiAlias true if clip is to be anti-aliased 1017 1018 example: https://fiddle.skia.org/c/@Canvas_clipRRect 1019 */ 1020 void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias); 1021 1022 /** Replaces clip with the intersection or difference of clip and rrect. 1023 Resulting clip is aliased; pixels are fully contained by the clip. 1024 rrect is transformed by SkMatrix before it is combined with clip. 1025 1026 @param rrect SkRRect to combine with clip 1027 @param op SkClipOp to apply to clip 1028 */ clipRRect(const SkRRect & rrect,SkClipOp op)1029 void clipRRect(const SkRRect& rrect, SkClipOp op) { 1030 this->clipRRect(rrect, op, false); 1031 } 1032 1033 /** Replaces clip with the intersection of clip and rrect, 1034 with an aliased or anti-aliased clip edge. 1035 rrect is transformed by SkMatrix before it is combined with clip. 1036 1037 @param rrect SkRRect to combine with clip 1038 @param doAntiAlias true if clip is to be anti-aliased 1039 */ 1040 void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) { 1041 this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias); 1042 } 1043 1044 /** Replaces clip with the intersection or difference of clip and path, 1045 with an aliased or anti-aliased clip edge. SkPath::FillType determines if path 1046 describes the area inside or outside its contours; and if path contour overlaps 1047 itself or another path contour, whether the overlaps form part of the area. 1048 path is transformed by SkMatrix before it is combined with clip. 1049 1050 @param path SkPath to combine with clip 1051 @param op SkClipOp to apply to clip 1052 @param doAntiAlias true if clip is to be anti-aliased 1053 1054 example: https://fiddle.skia.org/c/@Canvas_clipPath 1055 */ 1056 void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias); 1057 1058 /** Replaces clip with the intersection or difference of clip and path. 1059 Resulting clip is aliased; pixels are fully contained by the clip. 1060 SkPath::FillType determines if path 1061 describes the area inside or outside its contours; and if path contour overlaps 1062 itself or another path contour, whether the overlaps form part of the area. 1063 path is transformed by SkMatrix 1064 before it is combined with clip. 1065 1066 @param path SkPath to combine with clip 1067 @param op SkClipOp to apply to clip 1068 */ clipPath(const SkPath & path,SkClipOp op)1069 void clipPath(const SkPath& path, SkClipOp op) { 1070 this->clipPath(path, op, false); 1071 } 1072 1073 /** Replaces clip with the intersection of clip and path. 1074 Resulting clip is aliased; pixels are fully contained by the clip. 1075 SkPath::FillType determines if path 1076 describes the area inside or outside its contours; and if path contour overlaps 1077 itself or another path contour, whether the overlaps form part of the area. 1078 path is transformed by SkMatrix before it is combined with clip. 1079 1080 @param path SkPath to combine with clip 1081 @param doAntiAlias true if clip is to be anti-aliased 1082 */ 1083 void clipPath(const SkPath& path, bool doAntiAlias = false) { 1084 this->clipPath(path, SkClipOp::kIntersect, doAntiAlias); 1085 } 1086 1087 void clipShader(sk_sp<SkShader>, SkClipOp = SkClipOp::kIntersect); 1088 1089 /** Replaces clip with the intersection or difference of clip and SkRegion deviceRgn. 1090 Resulting clip is aliased; pixels are fully contained by the clip. 1091 deviceRgn is unaffected by SkMatrix. 1092 1093 @param deviceRgn SkRegion to combine with clip 1094 @param op SkClipOp to apply to clip 1095 1096 example: https://fiddle.skia.org/c/@Canvas_clipRegion 1097 */ 1098 void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect); 1099 1100 /** Returns true if SkRect rect, transformed by SkMatrix, can be quickly determined to be 1101 outside of clip. May return false even though rect is outside of clip. 1102 1103 Use to check if an area to be drawn is clipped out, to skip subsequent draw calls. 1104 1105 @param rect SkRect to compare with clip 1106 @return true if rect, transformed by SkMatrix, does not intersect clip 1107 1108 example: https://fiddle.skia.org/c/@Canvas_quickReject 1109 */ 1110 bool quickReject(const SkRect& rect) const; 1111 1112 /** Returns true if path, transformed by SkMatrix, can be quickly determined to be 1113 outside of clip. May return false even though path is outside of clip. 1114 1115 Use to check if an area to be drawn is clipped out, to skip subsequent draw calls. 1116 1117 @param path SkPath to compare with clip 1118 @return true if path, transformed by SkMatrix, does not intersect clip 1119 1120 example: https://fiddle.skia.org/c/@Canvas_quickReject_2 1121 */ 1122 bool quickReject(const SkPath& path) const; 1123 1124 /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty, 1125 return SkRect::MakeEmpty, where all SkRect sides equal zero. 1126 1127 SkRect returned is outset by one to account for partial pixel coverage if clip 1128 is anti-aliased. 1129 1130 @return bounds of clip in local coordinates 1131 1132 example: https://fiddle.skia.org/c/@Canvas_getLocalClipBounds 1133 */ 1134 SkRect getLocalClipBounds() const; 1135 1136 /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty, 1137 return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero. 1138 1139 bounds is outset by one to account for partial pixel coverage if clip 1140 is anti-aliased. 1141 1142 @param bounds SkRect of clip in local coordinates 1143 @return true if clip bounds is not empty 1144 */ getLocalClipBounds(SkRect * bounds)1145 bool getLocalClipBounds(SkRect* bounds) const { 1146 *bounds = this->getLocalClipBounds(); 1147 return !bounds->isEmpty(); 1148 } 1149 1150 /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty, 1151 return SkRect::MakeEmpty, where all SkRect sides equal zero. 1152 1153 Unlike getLocalClipBounds(), returned SkIRect is not outset. 1154 1155 @return bounds of clip in base device coordinates 1156 1157 example: https://fiddle.skia.org/c/@Canvas_getDeviceClipBounds 1158 */ 1159 SkIRect getDeviceClipBounds() const; 1160 1161 /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty, 1162 return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero. 1163 1164 Unlike getLocalClipBounds(), bounds is not outset. 1165 1166 @param bounds SkRect of clip in device coordinates 1167 @return true if clip bounds is not empty 1168 */ getDeviceClipBounds(SkIRect * bounds)1169 bool getDeviceClipBounds(SkIRect* bounds) const { 1170 *bounds = this->getDeviceClipBounds(); 1171 return !bounds->isEmpty(); 1172 } 1173 1174 /** Fills clip with color color. 1175 mode determines how ARGB is combined with destination. 1176 1177 @param color unpremultiplied ARGB 1178 @param mode SkBlendMode used to combine source color and destination 1179 1180 example: https://fiddle.skia.org/c/@Canvas_drawColor 1181 */ 1182 void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) { 1183 this->drawColor(SkColor4f::FromColor(color), mode); 1184 } 1185 1186 /** Fills clip with color color. 1187 mode determines how ARGB is combined with destination. 1188 1189 @param color SkColor4f representing unpremultiplied color. 1190 @param mode SkBlendMode used to combine source color and destination 1191 */ 1192 void drawColor(const SkColor4f& color, SkBlendMode mode = SkBlendMode::kSrcOver); 1193 1194 /** Fills clip with color color using SkBlendMode::kSrc. 1195 This has the effect of replacing all pixels contained by clip with color. 1196 1197 @param color unpremultiplied ARGB 1198 */ clear(SkColor color)1199 void clear(SkColor color) { 1200 this->clear(SkColor4f::FromColor(color)); 1201 } 1202 1203 /** Fills clip with color color using SkBlendMode::kSrc. 1204 This has the effect of replacing all pixels contained by clip with color. 1205 1206 @param color SkColor4f representing unpremultiplied color. 1207 */ clear(const SkColor4f & color)1208 void clear(const SkColor4f& color) { 1209 this->drawColor(color, SkBlendMode::kSrc); 1210 } 1211 1212 /** Makes SkCanvas contents undefined. Subsequent calls that read SkCanvas pixels, 1213 such as drawing with SkBlendMode, return undefined results. discard() does 1214 not change clip or SkMatrix. 1215 1216 discard() may do nothing, depending on the implementation of SkSurface or SkDevice 1217 that created SkCanvas. 1218 1219 discard() allows optimized performance on subsequent draws by removing 1220 cached data associated with SkSurface or SkDevice. 1221 It is not necessary to call discard() once done with SkCanvas; 1222 any cached data is deleted when owning SkSurface or SkDevice is deleted. 1223 */ discard()1224 void discard() { this->onDiscard(); } 1225 1226 /** Fills clip with SkPaint paint. SkPaint components, SkShader, 1227 SkColorFilter, SkImageFilter, and SkBlendMode affect drawing; 1228 SkMaskFilter and SkPathEffect in paint are ignored. 1229 1230 @param paint graphics state used to fill SkCanvas 1231 1232 example: https://fiddle.skia.org/c/@Canvas_drawPaint 1233 */ 1234 void drawPaint(const SkPaint& paint); 1235 1236 /** \enum SkCanvas::PointMode 1237 Selects if an array of points are drawn as discrete points, as lines, or as 1238 an open polygon. 1239 */ 1240 enum PointMode { 1241 kPoints_PointMode, //!< draw each point separately 1242 kLines_PointMode, //!< draw each pair of points as a line segment 1243 kPolygon_PointMode, //!< draw the array of points as a open polygon 1244 }; 1245 1246 /** Draws pts using clip, SkMatrix and SkPaint paint. 1247 count is the number of points; if count is less than one, has no effect. 1248 mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode. 1249 1250 If mode is kPoints_PointMode, the shape of point drawn depends on paint 1251 SkPaint::Cap. If paint is set to SkPaint::kRound_Cap, each point draws a 1252 circle of diameter SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap 1253 or SkPaint::kButt_Cap, each point draws a square of width and height 1254 SkPaint stroke width. 1255 1256 If mode is kLines_PointMode, each pair of points draws a line segment. 1257 One line is drawn for every two points; each point is used once. If count is odd, 1258 the final point is ignored. 1259 1260 If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment. 1261 count minus one lines are drawn; the first and last point are used once. 1262 1263 Each line segment respects paint SkPaint::Cap and SkPaint stroke width. 1264 SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style. 1265 1266 Always draws each element one at a time; is not affected by 1267 SkPaint::Join, and unlike drawPath(), does not create a mask from all points 1268 and lines before drawing. 1269 1270 @param mode whether pts draws points or lines 1271 @param count number of points in the array 1272 @param pts array of points to draw 1273 @param paint stroke, blend, color, and so on, used to draw 1274 1275 example: https://fiddle.skia.org/c/@Canvas_drawPoints 1276 */ 1277 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint); 1278 1279 /** Draws point at (x, y) using clip, SkMatrix and SkPaint paint. 1280 1281 The shape of point drawn depends on paint SkPaint::Cap. 1282 If paint is set to SkPaint::kRound_Cap, draw a circle of diameter 1283 SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap, 1284 draw a square of width and height SkPaint stroke width. 1285 SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style. 1286 1287 @param x left edge of circle or square 1288 @param y top edge of circle or square 1289 @param paint stroke, blend, color, and so on, used to draw 1290 1291 example: https://fiddle.skia.org/c/@Canvas_drawPoint 1292 */ 1293 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint); 1294 1295 /** Draws point p using clip, SkMatrix and SkPaint paint. 1296 1297 The shape of point drawn depends on paint SkPaint::Cap. 1298 If paint is set to SkPaint::kRound_Cap, draw a circle of diameter 1299 SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap, 1300 draw a square of width and height SkPaint stroke width. 1301 SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style. 1302 1303 @param p top-left edge of circle or square 1304 @param paint stroke, blend, color, and so on, used to draw 1305 */ drawPoint(SkPoint p,const SkPaint & paint)1306 void drawPoint(SkPoint p, const SkPaint& paint) { 1307 this->drawPoint(p.x(), p.y(), paint); 1308 } 1309 1310 /** Draws line segment from (x0, y0) to (x1, y1) using clip, SkMatrix, and SkPaint paint. 1311 In paint: SkPaint stroke width describes the line thickness; 1312 SkPaint::Cap draws the end rounded or square; 1313 SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style. 1314 1315 @param x0 start of line segment on x-axis 1316 @param y0 start of line segment on y-axis 1317 @param x1 end of line segment on x-axis 1318 @param y1 end of line segment on y-axis 1319 @param paint stroke, blend, color, and so on, used to draw 1320 1321 example: https://fiddle.skia.org/c/@Canvas_drawLine 1322 */ 1323 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint); 1324 1325 /** Draws line segment from p0 to p1 using clip, SkMatrix, and SkPaint paint. 1326 In paint: SkPaint stroke width describes the line thickness; 1327 SkPaint::Cap draws the end rounded or square; 1328 SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style. 1329 1330 @param p0 start of line segment 1331 @param p1 end of line segment 1332 @param paint stroke, blend, color, and so on, used to draw 1333 */ drawLine(SkPoint p0,SkPoint p1,const SkPaint & paint)1334 void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) { 1335 this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint); 1336 } 1337 1338 /** Draws SkRect rect using clip, SkMatrix, and SkPaint paint. 1339 In paint: SkPaint::Style determines if rectangle is stroked or filled; 1340 if stroked, SkPaint stroke width describes the line thickness, and 1341 SkPaint::Join draws the corners rounded or square. 1342 1343 @param rect rectangle to draw 1344 @param paint stroke or fill, blend, color, and so on, used to draw 1345 1346 example: https://fiddle.skia.org/c/@Canvas_drawRect 1347 */ 1348 void drawRect(const SkRect& rect, const SkPaint& paint); 1349 1350 /** Draws SkIRect rect using clip, SkMatrix, and SkPaint paint. 1351 In paint: SkPaint::Style determines if rectangle is stroked or filled; 1352 if stroked, SkPaint stroke width describes the line thickness, and 1353 SkPaint::Join draws the corners rounded or square. 1354 1355 @param rect rectangle to draw 1356 @param paint stroke or fill, blend, color, and so on, used to draw 1357 */ drawIRect(const SkIRect & rect,const SkPaint & paint)1358 void drawIRect(const SkIRect& rect, const SkPaint& paint) { 1359 SkRect r; 1360 r.set(rect); // promotes the ints to scalars 1361 this->drawRect(r, paint); 1362 } 1363 1364 /** Draws SkRegion region using clip, SkMatrix, and SkPaint paint. 1365 In paint: SkPaint::Style determines if rectangle is stroked or filled; 1366 if stroked, SkPaint stroke width describes the line thickness, and 1367 SkPaint::Join draws the corners rounded or square. 1368 1369 @param region region to draw 1370 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1371 1372 example: https://fiddle.skia.org/c/@Canvas_drawRegion 1373 */ 1374 void drawRegion(const SkRegion& region, const SkPaint& paint); 1375 1376 /** Draws oval oval using clip, SkMatrix, and SkPaint. 1377 In paint: SkPaint::Style determines if oval is stroked or filled; 1378 if stroked, SkPaint stroke width describes the line thickness. 1379 1380 @param oval SkRect bounds of oval 1381 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1382 1383 example: https://fiddle.skia.org/c/@Canvas_drawOval 1384 */ 1385 void drawOval(const SkRect& oval, const SkPaint& paint); 1386 1387 /** Draws SkRRect rrect using clip, SkMatrix, and SkPaint paint. 1388 In paint: SkPaint::Style determines if rrect is stroked or filled; 1389 if stroked, SkPaint stroke width describes the line thickness. 1390 1391 rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or 1392 may have any combination of positive non-square radii for the four corners. 1393 1394 @param rrect SkRRect with up to eight corner radii to draw 1395 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1396 1397 example: https://fiddle.skia.org/c/@Canvas_drawRRect 1398 */ 1399 void drawRRect(const SkRRect& rrect, const SkPaint& paint); 1400 1401 /** Draws SkRRect outer and inner 1402 using clip, SkMatrix, and SkPaint paint. 1403 outer must contain inner or the drawing is undefined. 1404 In paint: SkPaint::Style determines if SkRRect is stroked or filled; 1405 if stroked, SkPaint stroke width describes the line thickness. 1406 If stroked and SkRRect corner has zero length radii, SkPaint::Join can 1407 draw corners rounded or square. 1408 1409 GPU-backed platforms optimize drawing when both outer and inner are 1410 concave and outer contains inner. These platforms may not be able to draw 1411 SkPath built with identical data as fast. 1412 1413 @param outer SkRRect outer bounds to draw 1414 @param inner SkRRect inner bounds to draw 1415 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1416 1417 example: https://fiddle.skia.org/c/@Canvas_drawDRRect_a 1418 example: https://fiddle.skia.org/c/@Canvas_drawDRRect_b 1419 */ 1420 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint); 1421 1422 /** Draws circle at (cx, cy) with radius using clip, SkMatrix, and SkPaint paint. 1423 If radius is zero or less, nothing is drawn. 1424 In paint: SkPaint::Style determines if circle is stroked or filled; 1425 if stroked, SkPaint stroke width describes the line thickness. 1426 1427 @param cx circle center on the x-axis 1428 @param cy circle center on the y-axis 1429 @param radius half the diameter of circle 1430 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1431 1432 example: https://fiddle.skia.org/c/@Canvas_drawCircle 1433 */ 1434 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint); 1435 1436 /** Draws circle at center with radius using clip, SkMatrix, and SkPaint paint. 1437 If radius is zero or less, nothing is drawn. 1438 In paint: SkPaint::Style determines if circle is stroked or filled; 1439 if stroked, SkPaint stroke width describes the line thickness. 1440 1441 @param center circle center 1442 @param radius half the diameter of circle 1443 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1444 */ drawCircle(SkPoint center,SkScalar radius,const SkPaint & paint)1445 void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) { 1446 this->drawCircle(center.x(), center.y(), radius, paint); 1447 } 1448 1449 /** Draws arc using clip, SkMatrix, and SkPaint paint. 1450 1451 Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus 1452 sweepAngle. startAngle and sweepAngle are in degrees. 1453 1454 startAngle of zero places start point at the right middle edge of oval. 1455 A positive sweepAngle places arc end point clockwise from start point; 1456 a negative sweepAngle places arc end point counterclockwise from start point. 1457 sweepAngle may exceed 360 degrees, a full circle. 1458 If useCenter is true, draw a wedge that includes lines from oval 1459 center to arc end points. If useCenter is false, draw arc between end points. 1460 1461 If SkRect oval is empty or sweepAngle is zero, nothing is drawn. 1462 1463 @param oval SkRect bounds of oval containing arc to draw 1464 @param startAngle angle in degrees where arc begins 1465 @param sweepAngle sweep angle in degrees; positive is clockwise 1466 @param useCenter if true, include the center of the oval 1467 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1468 */ 1469 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 1470 bool useCenter, const SkPaint& paint); 1471 1472 /** Draws arc using clip, SkMatrix, and SkPaint paint. 1473 1474 Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus 1475 sweepAngle. startAngle and sweepAngle are in degrees. 1476 1477 startAngle of zero places start point at the right middle edge of oval. 1478 A positive sweepAngle places arc end point clockwise from start point; 1479 a negative sweepAngle places arc end point counterclockwise from start point. 1480 sweepAngle may exceed 360 degrees, a full circle. 1481 If useCenter is true, draw a wedge that includes lines from oval 1482 center to arc end points. If useCenter is false, draw arc between end points. 1483 1484 If SkRect oval is empty or sweepAngle is zero, nothing is drawn. 1485 1486 @param arc SkArc specifying oval, startAngle, sweepAngle, and arc-vs-wedge 1487 @param paint SkPaint stroke or fill, blend, color, and so on, used to draw 1488 */ drawArc(const SkArc & arc,const SkPaint & paint)1489 void drawArc(const SkArc& arc, const SkPaint& paint) { 1490 this->drawArc(arc.fOval, arc.fStartAngle, arc.fSweepAngle, arc.isWedge(), paint); 1491 } 1492 1493 /** Draws SkRRect bounded by SkRect rect, with corner radii (rx, ry) using clip, 1494 SkMatrix, and SkPaint paint. 1495 1496 In paint: SkPaint::Style determines if SkRRect is stroked or filled; 1497 if stroked, SkPaint stroke width describes the line thickness. 1498 If rx or ry are less than zero, they are treated as if they are zero. 1499 If rx plus ry exceeds rect width or rect height, radii are scaled down to fit. 1500 If rx and ry are zero, SkRRect is drawn as SkRect and if stroked is affected by 1501 SkPaint::Join. 1502 1503 @param rect SkRect bounds of SkRRect to draw 1504 @param rx axis length on x-axis of oval describing rounded corners 1505 @param ry axis length on y-axis of oval describing rounded corners 1506 @param paint stroke, blend, color, and so on, used to draw 1507 1508 example: https://fiddle.skia.org/c/@Canvas_drawRoundRect 1509 */ 1510 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint); 1511 1512 /** Draws SkPath path using clip, SkMatrix, and SkPaint paint. 1513 SkPath contains an array of path contour, each of which may be open or closed. 1514 1515 In paint: SkPaint::Style determines if SkRRect is stroked or filled: 1516 if filled, SkPath::FillType determines whether path contour describes inside or 1517 outside of fill; if stroked, SkPaint stroke width describes the line thickness, 1518 SkPaint::Cap describes line ends, and SkPaint::Join describes how 1519 corners are drawn. 1520 1521 @param path SkPath to draw 1522 @param paint stroke, blend, color, and so on, used to draw 1523 1524 example: https://fiddle.skia.org/c/@Canvas_drawPath 1525 */ 1526 void drawPath(const SkPath& path, const SkPaint& paint); 1527 drawImage(const SkImage * image,SkScalar left,SkScalar top)1528 void drawImage(const SkImage* image, SkScalar left, SkScalar top) { 1529 this->drawImage(image, left, top, SkSamplingOptions(), nullptr); 1530 } drawImage(const sk_sp<SkImage> & image,SkScalar left,SkScalar top)1531 void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top) { 1532 this->drawImage(image.get(), left, top, SkSamplingOptions(), nullptr); 1533 } 1534 1535 /** \enum SkCanvas::SrcRectConstraint 1536 SrcRectConstraint controls the behavior at the edge of source SkRect, 1537 provided to drawImageRect() when there is any filtering. If kStrict is set, 1538 then extra code is used to ensure it never samples outside of the src-rect. 1539 kStrict_SrcRectConstraint disables the use of mipmaps and anisotropic filtering. 1540 */ 1541 enum SrcRectConstraint { 1542 kStrict_SrcRectConstraint, //!< sample only inside bounds; slower 1543 kFast_SrcRectConstraint, //!< sample outside bounds; faster 1544 }; 1545 1546 void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkSamplingOptions&, 1547 const SkPaint* = nullptr); 1548 void drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y, 1549 const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) { 1550 this->drawImage(image.get(), x, y, sampling, paint); 1551 } 1552 void drawImageRect(const SkImage*, const SkRect& src, const SkRect& dst, 1553 const SkSamplingOptions&, const SkPaint*, SrcRectConstraint); 1554 void drawImageRect(const SkImage*, const SkRect& dst, const SkSamplingOptions&, 1555 const SkPaint* = nullptr); drawImageRect(const sk_sp<SkImage> & image,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SrcRectConstraint constraint)1556 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst, 1557 const SkSamplingOptions& sampling, const SkPaint* paint, 1558 SrcRectConstraint constraint) { 1559 this->drawImageRect(image.get(), src, dst, sampling, paint, constraint); 1560 } 1561 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, 1562 const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) { 1563 this->drawImageRect(image.get(), dst, sampling, paint); 1564 } 1565 1566 /** Draws SkImage image stretched proportionally to fit into SkRect dst. 1567 SkIRect center divides the image into nine sections: four sides, four corners, and 1568 the center. Corners are unmodified or scaled down proportionately if their sides 1569 are larger than dst; center and four sides are scaled to fit remaining space, if any. 1570 1571 Additionally transform draw using clip, SkMatrix, and optional SkPaint paint. 1572 1573 If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and 1574 SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader. 1575 If paint contains SkMaskFilter, generate mask from image bounds. 1576 Any SkMaskFilter on paint is ignored as is paint anti-aliasing state. 1577 1578 If generated mask extends beyond image bounds, replicate image edge colors, just 1579 as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set 1580 replicates the image edge color when it samples outside of its bounds. 1581 1582 @param image SkImage containing pixels, dimensions, and format 1583 @param center SkIRect edge of image corners and sides 1584 @param dst destination SkRect of image to draw to 1585 @param filter what technique to use when sampling the image 1586 @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter, 1587 and so on; or nullptr 1588 */ 1589 void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 1590 SkFilterMode filter, const SkPaint* paint = nullptr); 1591 1592 /** \struct SkCanvas::Lattice 1593 SkCanvas::Lattice divides SkBitmap or SkImage into a rectangular grid. 1594 Grid entries on even columns and even rows are fixed; these entries are 1595 always drawn at their original size if the destination is large enough. 1596 If the destination side is too small to hold the fixed entries, all fixed 1597 entries are proportionately scaled down to fit. 1598 The grid entries not on even columns and rows are scaled to fit the 1599 remaining space, if any. 1600 */ 1601 struct Lattice { 1602 1603 /** \enum SkCanvas::Lattice::RectType 1604 Optional setting per rectangular grid entry to make it transparent, 1605 or to fill the grid entry with a color. 1606 */ 1607 enum RectType : uint8_t { 1608 kDefault = 0, //!< draws SkBitmap into lattice rectangle 1609 kTransparent, //!< skips lattice rectangle by making it transparent 1610 kFixedColor, //!< draws one of fColors into lattice rectangle 1611 }; 1612 1613 const int* fXDivs; //!< x-axis values dividing bitmap 1614 const int* fYDivs; //!< y-axis values dividing bitmap 1615 const RectType* fRectTypes; //!< array of fill types 1616 int fXCount; //!< number of x-coordinates 1617 int fYCount; //!< number of y-coordinates 1618 const SkIRect* fBounds; //!< source bounds to draw from 1619 const SkColor* fColors; //!< array of colors 1620 }; 1621 1622 /** Draws SkImage image stretched proportionally to fit into SkRect dst. 1623 1624 SkCanvas::Lattice lattice divides image into a rectangular grid. 1625 Each intersection of an even-numbered row and column is fixed; 1626 fixed lattice elements never scale larger than their initial 1627 size and shrink proportionately when all fixed elements exceed the bitmap 1628 dimension. All other grid elements scale to fill the available space, if any. 1629 1630 Additionally transform draw using clip, SkMatrix, and optional SkPaint paint. 1631 1632 If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and 1633 SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader. 1634 If paint contains SkMaskFilter, generate mask from image bounds. 1635 Any SkMaskFilter on paint is ignored as is paint anti-aliasing state. 1636 1637 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 1638 just as SkShader made from SkShader::MakeBitmapShader with 1639 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 1640 outside of its bounds. 1641 1642 @param image SkImage containing pixels, dimensions, and format 1643 @param lattice division of bitmap into fixed and variable rectangles 1644 @param dst destination SkRect of image to draw to 1645 @param filter what technique to use when sampling the image 1646 @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter, 1647 and so on; or nullptr 1648 */ 1649 void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 1650 SkFilterMode filter, const SkPaint* paint = nullptr); drawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst)1651 void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst) { 1652 this->drawImageLattice(image, lattice, dst, SkFilterMode::kNearest, nullptr); 1653 } 1654 1655 /** 1656 * Experimental. Controls anti-aliasing of each edge of images in an image-set. 1657 */ 1658 enum QuadAAFlags : unsigned { 1659 kLeft_QuadAAFlag = 0b0001, 1660 kTop_QuadAAFlag = 0b0010, 1661 kRight_QuadAAFlag = 0b0100, 1662 kBottom_QuadAAFlag = 0b1000, 1663 1664 kNone_QuadAAFlags = 0b0000, 1665 kAll_QuadAAFlags = 0b1111, 1666 }; 1667 1668 /** This is used by the experimental API below. */ 1669 struct SK_API ImageSetEntry { 1670 ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect, 1671 int matrixIndex, float alpha, unsigned aaFlags, bool hasClip); 1672 1673 ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect, 1674 float alpha, unsigned aaFlags); 1675 1676 ImageSetEntry(); 1677 ~ImageSetEntry(); 1678 ImageSetEntry(const ImageSetEntry&); 1679 ImageSetEntry& operator=(const ImageSetEntry&); 1680 1681 sk_sp<const SkImage> fImage; 1682 SkRect fSrcRect; 1683 SkRect fDstRect; 1684 int fMatrixIndex = -1; // Index into the preViewMatrices arg, or < 0 1685 float fAlpha = 1.f; 1686 unsigned fAAFlags = kNone_QuadAAFlags; // QuadAAFlags 1687 bool fHasClip = false; // True to use next 4 points in dstClip arg as quad 1688 }; 1689 1690 /** 1691 * This is an experimental API for the SkiaRenderer Chromium project, and its API will surely 1692 * evolve if it is not removed outright. 1693 * 1694 * This behaves very similarly to drawRect() combined with a clipPath() formed by clip 1695 * quadrilateral. 'rect' and 'clip' are in the same coordinate space. If 'clip' is null, then it 1696 * is as if the rectangle was not clipped (or, alternatively, clipped to itself). If not null, 1697 * then it must provide 4 points. 1698 * 1699 * In addition to combining the draw and clipping into one operation, this function adds the 1700 * additional capability of controlling each of the rectangle's edges anti-aliasing 1701 * independently. The edges of the clip will respect the per-edge AA flags. It is required that 1702 * 'clip' be contained inside 'rect'. In terms of mapping to edge labels, the 'clip' points 1703 * should be ordered top-left, top-right, bottom-right, bottom-left so that the edge between [0] 1704 * and [1] is "top", [1] and [2] is "right", [2] and [3] is "bottom", and [3] and [0] is "left". 1705 * This ordering matches SkRect::toQuad(). 1706 * 1707 * This API only draws solid color, filled rectangles so it does not accept a full SkPaint. 1708 */ 1709 void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags, 1710 const SkColor4f& color, SkBlendMode mode); experimental_DrawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],QuadAAFlags aaFlags,SkColor color,SkBlendMode mode)1711 void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags, 1712 SkColor color, SkBlendMode mode) { 1713 this->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, SkColor4f::FromColor(color), mode); 1714 } 1715 1716 /** 1717 * This is an bulk variant of experimental_DrawEdgeAAQuad() that renders 'cnt' textured quads. 1718 * For each entry, 'fDstRect' is rendered with its clip (determined by entry's 'fHasClip' and 1719 * the current index in 'dstClip'). The entry's fImage is applied to the destination rectangle 1720 * by sampling from 'fSrcRect' sub-image. The corners of 'fSrcRect' map to the corners of 1721 * 'fDstRect', just like in drawImageRect(), and they will be properly interpolated when 1722 * applying a clip. 1723 * 1724 * Like experimental_DrawEdgeAAQuad(), each entry can specify edge AA flags that apply to both 1725 * the destination rect and its clip. 1726 * 1727 * If provided, the 'dstClips' array must have length equal 4 * the number of entries with 1728 * fHasClip true. If 'dstClips' is null, every entry must have 'fHasClip' set to false. The 1729 * destination clip coordinates will be read consecutively with the image set entries, advancing 1730 * by 4 points every time an entry with fHasClip is passed. 1731 * 1732 * This entry point supports per-entry manipulations to the canvas's current matrix. If an 1733 * entry provides 'fMatrixIndex' >= 0, it will be drawn as if the canvas's CTM was 1734 * canvas->getTotalMatrix() * preViewMatrices[fMatrixIndex]. If 'fMatrixIndex' is less than 0, 1735 * the pre-view matrix transform is implicitly the identity, so it will be drawn using just the 1736 * current canvas matrix. The pre-view matrix modifies the canvas's view matrix, it does not 1737 * affect the local coordinates of each entry. 1738 * 1739 * An optional paint may be provided, which supports the same subset of features usable with 1740 * drawImageRect (i.e. assumed to be filled and no path effects). When a paint is provided, the 1741 * image set is drawn as if each image used the applied paint independently, so each is affected 1742 * by the image, color, and/or mask filter. 1743 */ 1744 void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt, 1745 const SkPoint dstClips[], const SkMatrix preViewMatrices[], 1746 const SkSamplingOptions&, const SkPaint* paint = nullptr, 1747 SrcRectConstraint constraint = kStrict_SrcRectConstraint); 1748 1749 /** Draws text, with origin at (x, y), using clip, SkMatrix, SkFont font, 1750 and SkPaint paint. 1751 1752 When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or 1753 SkTextEncoding::kUTF32, this function uses the default 1754 character-to-glyph mapping from the SkTypeface in font. It does not 1755 perform typeface fallback for characters not found in the SkTypeface. 1756 It does not perform kerning or other complex shaping; glyphs are 1757 positioned based on their default advances. 1758 1759 Text meaning depends on SkTextEncoding. 1760 1761 Text size is affected by SkMatrix and SkFont text size. Default text 1762 size is 12 point. 1763 1764 All elements of paint: SkPathEffect, SkMaskFilter, SkShader, 1765 SkColorFilter, and SkImageFilter; apply to text. By 1766 default, draws filled black glyphs. 1767 1768 @param text character code points or glyphs drawn 1769 @param byteLength byte length of text array 1770 @param encoding text encoding used in the text array 1771 @param x start of text on x-axis 1772 @param y start of text on y-axis 1773 @param font typeface, text size and so, used to describe the text 1774 @param paint blend, color, and so on, used to draw 1775 */ 1776 void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding, 1777 SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint); 1778 1779 /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, 1780 SkFont font, and SkPaint paint. 1781 1782 This function uses the default character-to-glyph mapping from the 1783 SkTypeface in font. It does not perform typeface fallback for 1784 characters not found in the SkTypeface. It does not perform kerning; 1785 glyphs are positioned based on their default advances. 1786 1787 String str is encoded as UTF-8. 1788 1789 Text size is affected by SkMatrix and font text size. Default text 1790 size is 12 point. 1791 1792 All elements of paint: SkPathEffect, SkMaskFilter, SkShader, 1793 SkColorFilter, and SkImageFilter; apply to text. By 1794 default, draws filled black glyphs. 1795 1796 @param str character code points drawn, 1797 ending with a char value of zero 1798 @param x start of string on x-axis 1799 @param y start of string on y-axis 1800 @param font typeface, text size and so, used to describe the text 1801 @param paint blend, color, and so on, used to draw 1802 */ drawString(const char str[],SkScalar x,SkScalar y,const SkFont & font,const SkPaint & paint)1803 void drawString(const char str[], SkScalar x, SkScalar y, const SkFont& font, 1804 const SkPaint& paint) { 1805 this->drawSimpleText(str, strlen(str), SkTextEncoding::kUTF8, x, y, font, paint); 1806 } 1807 1808 /** Draws SkString, with origin at (x, y), using clip, SkMatrix, SkFont font, 1809 and SkPaint paint. 1810 1811 This function uses the default character-to-glyph mapping from the 1812 SkTypeface in font. It does not perform typeface fallback for 1813 characters not found in the SkTypeface. It does not perform kerning; 1814 glyphs are positioned based on their default advances. 1815 1816 SkString str is encoded as UTF-8. 1817 1818 Text size is affected by SkMatrix and SkFont text size. Default text 1819 size is 12 point. 1820 1821 All elements of paint: SkPathEffect, SkMaskFilter, SkShader, 1822 SkColorFilter, and SkImageFilter; apply to text. By 1823 default, draws filled black glyphs. 1824 1825 @param str character code points drawn, 1826 ending with a char value of zero 1827 @param x start of string on x-axis 1828 @param y start of string on y-axis 1829 @param font typeface, text size and so, used to describe the text 1830 @param paint blend, color, and so on, used to draw 1831 */ drawString(const SkString & str,SkScalar x,SkScalar y,const SkFont & font,const SkPaint & paint)1832 void drawString(const SkString& str, SkScalar x, SkScalar y, const SkFont& font, 1833 const SkPaint& paint) { 1834 this->drawSimpleText(str.c_str(), str.size(), SkTextEncoding::kUTF8, x, y, font, paint); 1835 } 1836 1837 /** Draws count glyphs, at positions relative to origin styled with font and paint with 1838 supporting utf8 and cluster information. 1839 1840 This function draw glyphs at the given positions relative to the given origin. 1841 It does not perform typeface fallback for glyphs not found in the SkTypeface in font. 1842 1843 The drawing obeys the current transform matrix and clipping. 1844 1845 All elements of paint: SkPathEffect, SkMaskFilter, SkShader, 1846 SkColorFilter, and SkImageFilter; apply to text. By 1847 default, draws filled black glyphs. 1848 1849 @param count number of glyphs to draw 1850 @param glyphs the array of glyphIDs to draw 1851 @param positions where to draw each glyph relative to origin 1852 @param clusters array of size count of cluster information 1853 @param textByteCount size of the utf8text 1854 @param utf8text utf8text supporting information for the glyphs 1855 @param origin the origin of all the positions 1856 @param font typeface, text size and so, used to describe the text 1857 @param paint blend, color, and so on, used to draw 1858 */ 1859 void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[], 1860 const uint32_t clusters[], int textByteCount, const char utf8text[], 1861 SkPoint origin, const SkFont& font, const SkPaint& paint); 1862 1863 /** Draws count glyphs, at positions relative to origin styled with font and paint. 1864 1865 This function draw glyphs at the given positions relative to the given origin. 1866 It does not perform typeface fallback for glyphs not found in the SkTypeface in font. 1867 1868 The drawing obeys the current transform matrix and clipping. 1869 1870 All elements of paint: SkPathEffect, SkMaskFilter, SkShader, 1871 SkColorFilter, and SkImageFilter; apply to text. By 1872 default, draws filled black glyphs. 1873 1874 @param count number of glyphs to draw 1875 @param glyphs the array of glyphIDs to draw 1876 @param positions where to draw each glyph relative to origin 1877 @param origin the origin of all the positions 1878 @param font typeface, text size and so, used to describe the text 1879 @param paint blend, color, and so on, used to draw 1880 */ 1881 void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[], 1882 SkPoint origin, const SkFont& font, const SkPaint& paint); 1883 1884 /** Draws count glyphs, at positions relative to origin styled with font and paint. 1885 1886 This function draw glyphs using the given scaling and rotations. They are positioned 1887 relative to the given origin. It does not perform typeface fallback for glyphs not found 1888 in the SkTypeface in font. 1889 1890 The drawing obeys the current transform matrix and clipping. 1891 1892 All elements of paint: SkPathEffect, SkMaskFilter, SkShader, 1893 SkColorFilter, and SkImageFilter; apply to text. By 1894 default, draws filled black glyphs. 1895 1896 @param count number of glyphs to draw 1897 @param glyphs the array of glyphIDs to draw 1898 @param xforms where to draw and orient each glyph 1899 @param origin the origin of all the positions 1900 @param font typeface, text size and so, used to describe the text 1901 @param paint blend, color, and so on, used to draw 1902 */ 1903 void drawGlyphs(int count, const SkGlyphID glyphs[], const SkRSXform xforms[], 1904 SkPoint origin, const SkFont& font, const SkPaint& paint); 1905 1906 /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint. 1907 1908 blob contains glyphs, their positions, and paint attributes specific to text: 1909 SkTypeface, SkPaint text size, SkPaint text scale x, 1910 SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold, 1911 SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text, 1912 and SkPaint subpixel text. 1913 1914 SkTextEncoding must be set to SkTextEncoding::kGlyphID. 1915 1916 Elements of paint: anti-alias, SkBlendMode, color including alpha, 1917 SkColorFilter, SkPaint dither, SkMaskFilter, SkPathEffect, SkShader, and 1918 SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style: 1919 SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width; 1920 apply to SkPath created from blob. 1921 1922 @param blob glyphs, positions, and their paints' text size, typeface, and so on 1923 @param x horizontal offset applied to blob 1924 @param y vertical offset applied to blob 1925 @param paint blend, color, stroking, and so on, used to draw 1926 1927 example: https://fiddle.skia.org/c/@Canvas_drawTextBlob 1928 */ 1929 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint); 1930 1931 /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint. 1932 1933 blob contains glyphs, their positions, and paint attributes specific to text: 1934 SkTypeface, SkPaint text size, SkPaint text scale x, 1935 SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold, 1936 SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text, 1937 and SkPaint subpixel text. 1938 1939 SkTextEncoding must be set to SkTextEncoding::kGlyphID. 1940 1941 Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter, 1942 and SkImageFilter; apply to blob. 1943 1944 @param blob glyphs, positions, and their paints' text size, typeface, and so on 1945 @param x horizontal offset applied to blob 1946 @param y vertical offset applied to blob 1947 @param paint blend, color, stroking, and so on, used to draw 1948 */ drawTextBlob(const sk_sp<SkTextBlob> & blob,SkScalar x,SkScalar y,const SkPaint & paint)1949 void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) { 1950 this->drawTextBlob(blob.get(), x, y, paint); 1951 } 1952 1953 /** Draws SkPicture picture, using clip and SkMatrix. 1954 Clip and SkMatrix are unchanged by picture contents, as if 1955 save() was called before and restore() was called after drawPicture(). 1956 1957 SkPicture records a series of draw commands for later playback. 1958 1959 @param picture recorded drawing commands to play 1960 */ drawPicture(const SkPicture * picture)1961 void drawPicture(const SkPicture* picture) { 1962 this->drawPicture(picture, nullptr, nullptr); 1963 } 1964 1965 /** Draws SkPicture picture, using clip and SkMatrix. 1966 Clip and SkMatrix are unchanged by picture contents, as if 1967 save() was called before and restore() was called after drawPicture(). 1968 1969 SkPicture records a series of draw commands for later playback. 1970 1971 @param picture recorded drawing commands to play 1972 */ drawPicture(const sk_sp<SkPicture> & picture)1973 void drawPicture(const sk_sp<SkPicture>& picture) { 1974 this->drawPicture(picture.get()); 1975 } 1976 1977 /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with 1978 SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter, 1979 SkImageFilter, and SkBlendMode, if provided. 1980 1981 If paint is non-null, then the picture is always drawn into a temporary layer before 1982 actually landing on the canvas. Note that drawing into a layer can also change its 1983 appearance if there are any non-associative blendModes inside any of the pictures elements. 1984 1985 @param picture recorded drawing commands to play 1986 @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr 1987 @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr 1988 1989 example: https://fiddle.skia.org/c/@Canvas_drawPicture_3 1990 */ 1991 void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint); 1992 1993 /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with 1994 SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter, 1995 SkImageFilter, and SkBlendMode, if provided. 1996 1997 If paint is non-null, then the picture is always drawn into a temporary layer before 1998 actually landing on the canvas. Note that drawing into a layer can also change its 1999 appearance if there are any non-associative blendModes inside any of the pictures elements. 2000 2001 @param picture recorded drawing commands to play 2002 @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr 2003 @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr 2004 */ drawPicture(const sk_sp<SkPicture> & picture,const SkMatrix * matrix,const SkPaint * paint)2005 void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, 2006 const SkPaint* paint) { 2007 this->drawPicture(picture.get(), matrix, paint); 2008 } 2009 2010 /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix. 2011 If paint contains an SkShader and vertices does not contain texCoords, the shader 2012 is mapped using the vertices' positions. 2013 2014 SkBlendMode is ignored if SkVertices does not have colors. Otherwise, it combines 2015 - the SkShader if SkPaint contains SkShader 2016 - or the opaque SkPaint color if SkPaint does not contain SkShader 2017 as the src of the blend and the interpolated vertex colors as the dst. 2018 2019 SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored. 2020 2021 @param vertices triangle mesh to draw 2022 @param mode combines vertices' colors with SkShader if present or SkPaint opaque color 2023 if not. Ignored if the vertices do not contain color. 2024 @param paint specifies the SkShader, used as SkVertices texture, and SkColorFilter. 2025 2026 example: https://fiddle.skia.org/c/@Canvas_drawVertices 2027 */ 2028 void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint); 2029 2030 /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix. 2031 If paint contains an SkShader and vertices does not contain texCoords, the shader 2032 is mapped using the vertices' positions. 2033 2034 SkBlendMode is ignored if SkVertices does not have colors. Otherwise, it combines 2035 - the SkShader if SkPaint contains SkShader 2036 - or the opaque SkPaint color if SkPaint does not contain SkShader 2037 as the src of the blend and the interpolated vertex colors as the dst. 2038 2039 SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored. 2040 2041 @param vertices triangle mesh to draw 2042 @param mode combines vertices' colors with SkShader if present or SkPaint opaque color 2043 if not. Ignored if the vertices do not contain color. 2044 @param paint specifies the SkShader, used as SkVertices texture, may be nullptr 2045 2046 example: https://fiddle.skia.org/c/@Canvas_drawVertices_2 2047 */ 2048 void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint); 2049 2050 /** 2051 Experimental, under active development, and subject to change without notice. 2052 2053 Draws a mesh using a user-defined specification (see SkMeshSpecification). Requires 2054 a GPU backend or SkSL to be compiled in. 2055 2056 SkBlender is ignored if SkMesh's specification does not output fragment shader color. 2057 Otherwise, it combines 2058 - the SkShader if SkPaint contains SkShader 2059 - or the opaque SkPaint color if SkPaint does not contain SkShader 2060 as the src of the blend and the mesh's fragment color as the dst. 2061 2062 SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored. 2063 2064 @param mesh the mesh vertices and compatible specification. 2065 @param blender combines vertices colors with SkShader if present or SkPaint opaque color 2066 if not. Ignored if the custom mesh does not output color. Defaults to 2067 SkBlendMode::kModulate if nullptr. 2068 @param paint specifies the SkShader, used as SkVertices texture, may be nullptr 2069 */ 2070 void drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint); 2071 2072 /** Draws a Coons patch: the interpolation of four cubics with shared corners, 2073 associating a color, and optionally a texture SkPoint, with each corner. 2074 2075 SkPoint array cubics specifies four SkPath cubic starting at the top-left corner, 2076 in clockwise order, sharing every fourth point. The last SkPath cubic ends at the 2077 first point. 2078 2079 Color array color associates colors with corners in top-left, top-right, 2080 bottom-right, bottom-left order. 2081 2082 If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to 2083 corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is 2084 nullptr, SkShader is mapped using positions (derived from cubics). 2085 2086 SkBlendMode is ignored if colors is null. Otherwise, it combines 2087 - the SkShader if SkPaint contains SkShader 2088 - or the opaque SkPaint color if SkPaint does not contain SkShader 2089 as the src of the blend and the interpolated patch colors as the dst. 2090 2091 SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored. 2092 2093 @param cubics SkPath cubic array, sharing common points 2094 @param colors color array, one for each corner 2095 @param texCoords SkPoint array of texture coordinates, mapping SkShader to corners; 2096 may be nullptr 2097 @param mode combines patch's colors with SkShader if present or SkPaint opaque color 2098 if not. Ignored if colors is null. 2099 @param paint SkShader, SkColorFilter, SkBlendMode, used to draw 2100 */ 2101 void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2102 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint); 2103 2104 /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint. 2105 paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode 2106 to draw, if present. For each entry in the array, SkRect tex locates sprite in 2107 atlas, and SkRSXform xform transforms it into destination space. 2108 2109 SkMaskFilter and SkPathEffect on paint are ignored. 2110 2111 xform, tex, and colors if present, must contain count entries. 2112 Optional colors are applied for each sprite using SkBlendMode mode, treating 2113 sprite as source and colors as destination. 2114 Optional cullRect is a conservative bounds of all transformed sprites. 2115 If cullRect is outside of clip, canvas can skip drawing. 2116 2117 If atlas is nullptr, this draws nothing. 2118 2119 @param atlas SkImage containing sprites 2120 @param xform SkRSXform mappings for sprites in atlas 2121 @param tex SkRect locations of sprites in atlas 2122 @param colors one per sprite, blended with sprite using SkBlendMode; may be nullptr 2123 @param count number of sprites to draw 2124 @param mode SkBlendMode combining colors and sprites 2125 @param sampling SkSamplingOptions used when sampling from the atlas image 2126 @param cullRect bounds of transformed sprites for efficient clipping; may be nullptr 2127 @param paint SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr 2128 */ 2129 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 2130 const SkColor colors[], int count, SkBlendMode mode, 2131 const SkSamplingOptions& sampling, const SkRect* cullRect, const SkPaint* paint); 2132 2133 /** Draws SkDrawable drawable using clip and SkMatrix, concatenated with 2134 optional matrix. 2135 2136 If SkCanvas has an asynchronous implementation, as is the case 2137 when it is recording into SkPicture, then drawable will be referenced, 2138 so that SkDrawable::draw() can be called when the operation is finalized. To force 2139 immediate drawing, call SkDrawable::draw() instead. 2140 2141 @param drawable custom struct encapsulating drawing commands 2142 @param matrix transformation applied to drawing; may be nullptr 2143 2144 example: https://fiddle.skia.org/c/@Canvas_drawDrawable 2145 */ 2146 void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr); 2147 2148 /** Draws SkDrawable drawable using clip and SkMatrix, offset by (x, y). 2149 2150 If SkCanvas has an asynchronous implementation, as is the case 2151 when it is recording into SkPicture, then drawable will be referenced, 2152 so that SkDrawable::draw() can be called when the operation is finalized. To force 2153 immediate drawing, call SkDrawable::draw() instead. 2154 2155 @param drawable custom struct encapsulating drawing commands 2156 @param x offset into SkCanvas writable pixels on x-axis 2157 @param y offset into SkCanvas writable pixels on y-axis 2158 2159 example: https://fiddle.skia.org/c/@Canvas_drawDrawable_2 2160 */ 2161 void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y); 2162 2163 /** Associates SkRect on SkCanvas with an annotation; a key-value pair, where the key is 2164 a null-terminated UTF-8 string, and optional value is stored as SkData. 2165 2166 Only some canvas implementations, such as recording to SkPicture, or drawing to 2167 document PDF, use annotations. 2168 2169 @param rect SkRect extent of canvas to annotate 2170 @param key string used for lookup 2171 @param value data holding value stored in annotation 2172 2173 example: https://fiddle.skia.org/c/@Canvas_drawAnnotation_2 2174 */ 2175 void drawAnnotation(const SkRect& rect, const char key[], SkData* value); 2176 2177 /** Associates SkRect on SkCanvas when an annotation; a key-value pair, where the key is 2178 a null-terminated UTF-8 string, and optional value is stored as SkData. 2179 2180 Only some canvas implementations, such as recording to SkPicture, or drawing to 2181 document PDF, use annotations. 2182 2183 @param rect SkRect extent of canvas to annotate 2184 @param key string used for lookup 2185 @param value data holding value stored in annotation 2186 */ drawAnnotation(const SkRect & rect,const char key[],const sk_sp<SkData> & value)2187 void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) { 2188 this->drawAnnotation(rect, key, value.get()); 2189 } 2190 2191 /** Returns true if clip is empty; that is, nothing will draw. 2192 2193 May do work when called; it should not be called 2194 more often than needed. However, once called, subsequent calls perform no 2195 work until clip changes. 2196 2197 @return true if clip is empty 2198 2199 example: https://fiddle.skia.org/c/@Canvas_isClipEmpty 2200 */ 2201 virtual bool isClipEmpty() const; 2202 2203 /** Returns true if clip is SkRect and not empty. 2204 Returns false if the clip is empty, or if it is not SkRect. 2205 2206 @return true if clip is SkRect and not empty 2207 2208 example: https://fiddle.skia.org/c/@Canvas_isClipRect 2209 */ 2210 virtual bool isClipRect() const; 2211 2212 /** Returns the current transform from local coordinates to the 'device', which for most 2213 * purposes means pixels. 2214 * 2215 * @return transformation from local coordinates to device / pixels. 2216 */ 2217 SkM44 getLocalToDevice() const; 2218 2219 /** 2220 * Throws away the 3rd row and column in the matrix, so be warned. 2221 */ getLocalToDeviceAs3x3()2222 SkMatrix getLocalToDeviceAs3x3() const { 2223 return this->getLocalToDevice().asM33(); 2224 } 2225 2226 #ifdef SK_SUPPORT_LEGACY_GETTOTALMATRIX 2227 /** DEPRECATED 2228 * Legacy version of getLocalToDevice(), which strips away any Z information, and 2229 * just returns a 3x3 version. 2230 * 2231 * @return 3x3 version of getLocalToDevice() 2232 * 2233 * example: https://fiddle.skia.org/c/@Canvas_getTotalMatrix 2234 * example: https://fiddle.skia.org/c/@Clip 2235 */ 2236 SkMatrix getTotalMatrix() const; 2237 #endif 2238 2239 /////////////////////////////////////////////////////////////////////////// 2240 2241 /** 2242 * Returns the global clip as a region. If the clip contains AA, then only the bounds 2243 * of the clip may be returned. 2244 */ 2245 void temporary_internal_getRgnClip(SkRegion* region); 2246 2247 void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&); 2248 2249 2250 protected: 2251 // default impl defers to getDevice()->newSurface(info) 2252 virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props); 2253 2254 // default impl defers to its device 2255 virtual bool onPeekPixels(SkPixmap* pixmap); 2256 virtual bool onAccessTopLayerPixels(SkPixmap* pixmap); 2257 virtual SkImageInfo onImageInfo() const; 2258 virtual bool onGetProps(SkSurfaceProps* props, bool top) const; 2259 2260 // Subclass save/restore notifiers. 2261 // Overriders should call the corresponding INHERITED method up the inheritance chain. 2262 // getSaveLayerStrategy()'s return value may suppress full layer allocation. 2263 enum SaveLayerStrategy { 2264 kFullLayer_SaveLayerStrategy, 2265 kNoLayer_SaveLayerStrategy, 2266 }; 2267 willSave()2268 virtual void willSave() {} 2269 // Overriders should call the corresponding INHERITED method up the inheritance chain. getSaveLayerStrategy(const SaveLayerRec &)2270 virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) { 2271 return kFullLayer_SaveLayerStrategy; 2272 } 2273 2274 // returns true if we should actually perform the saveBehind, or false if we should just save. onDoSaveBehind(const SkRect *)2275 virtual bool onDoSaveBehind(const SkRect*) { return true; } willRestore()2276 virtual void willRestore() {} didRestore()2277 virtual void didRestore() {} 2278 didConcat44(const SkM44 &)2279 virtual void didConcat44(const SkM44&) {} didSetM44(const SkM44 &)2280 virtual void didSetM44(const SkM44&) {} didTranslate(SkScalar,SkScalar)2281 virtual void didTranslate(SkScalar, SkScalar) {} didScale(SkScalar,SkScalar)2282 virtual void didScale(SkScalar, SkScalar) {} 2283 2284 // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to 2285 // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using 2286 // that mechanism will be required to implement the new function. 2287 virtual void onDrawPaint(const SkPaint& paint); 2288 virtual void onDrawBehind(const SkPaint& paint); 2289 virtual void onDrawRect(const SkRect& rect, const SkPaint& paint); 2290 virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint); 2291 virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint); 2292 virtual void onDrawOval(const SkRect& rect, const SkPaint& paint); 2293 virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, 2294 bool useCenter, const SkPaint& paint); 2295 virtual void onDrawPath(const SkPath& path, const SkPaint& paint); 2296 virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint); 2297 2298 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2299 const SkPaint& paint); 2300 2301 virtual void onDrawGlyphRunList(const sktext::GlyphRunList& glyphRunList, const SkPaint& paint); 2302 2303 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2304 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint); 2305 virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 2306 const SkPaint& paint); 2307 2308 virtual void onDrawImage2(const SkImage*, SkScalar dx, SkScalar dy, const SkSamplingOptions&, 2309 const SkPaint*); 2310 virtual void onDrawImageRect2(const SkImage*, const SkRect& src, const SkRect& dst, 2311 const SkSamplingOptions&, const SkPaint*, SrcRectConstraint); 2312 virtual void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect& dst, 2313 SkFilterMode, const SkPaint*); 2314 virtual void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect src[], 2315 const SkColor[], int count, SkBlendMode, const SkSamplingOptions&, 2316 const SkRect* cull, const SkPaint*); 2317 virtual void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count, 2318 const SkPoint dstClips[], const SkMatrix preViewMatrices[], 2319 const SkSamplingOptions&, const SkPaint*, 2320 SrcRectConstraint); 2321 2322 virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode, 2323 const SkPaint& paint); 2324 virtual void onDrawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&); 2325 virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value); 2326 virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&); 2327 2328 virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix); 2329 virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2330 const SkPaint* paint); 2331 2332 virtual void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags, 2333 const SkColor4f& color, SkBlendMode mode); 2334 2335 enum ClipEdgeStyle { 2336 kHard_ClipEdgeStyle, 2337 kSoft_ClipEdgeStyle 2338 }; 2339 2340 virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle); 2341 virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle); 2342 virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle); 2343 virtual void onClipShader(sk_sp<SkShader>, SkClipOp); 2344 virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op); 2345 virtual void onResetClip(); 2346 2347 virtual void onDiscard(); 2348 2349 /** 2350 */ 2351 virtual sk_sp<sktext::gpu::Slug> onConvertGlyphRunListToSlug( 2352 const sktext::GlyphRunList& glyphRunList, const SkPaint& paint); 2353 2354 /** 2355 */ 2356 virtual void onDrawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint); 2357 2358 private: 2359 enum class PredrawFlags : unsigned { 2360 kNone = 0, 2361 kOpaqueShaderOverride = 1, // The paint's shader is overridden with an opaque image 2362 kNonOpaqueShaderOverride = 2, // The paint's shader is overridden but is not opaque 2363 kCheckForOverwrite = 4, // Check if the draw would overwrite the entire surface 2364 kSkipMaskFilterAutoLayer = 8, // Do not apply mask filters in the AutoLayer 2365 }; 2366 // Inlined SK_DECL_BITMASK_OPS_FRIENDS to avoid including SkEnumBitMask.h 2367 friend constexpr SkEnumBitMask<PredrawFlags> operator|(PredrawFlags, PredrawFlags); 2368 friend constexpr SkEnumBitMask<PredrawFlags> operator&(PredrawFlags, PredrawFlags); 2369 friend constexpr SkEnumBitMask<PredrawFlags> operator^(PredrawFlags, PredrawFlags); 2370 friend constexpr SkEnumBitMask<PredrawFlags> operator~(PredrawFlags); 2371 2372 // notify our surface (if we have one) that we are about to draw, so it 2373 // can perform copy-on-write or invalidate any cached images 2374 // returns false if the copy failed 2375 [[nodiscard]] bool predrawNotify(bool willOverwritesEntireSurface = false); 2376 [[nodiscard]] bool predrawNotify(const SkRect*, const SkPaint*, SkEnumBitMask<PredrawFlags>); 2377 2378 // call the appropriate predrawNotify and create a layer if needed. 2379 std::optional<AutoLayerForImageFilter> aboutToDraw( 2380 const SkPaint& paint, 2381 const SkRect* rawBounds, 2382 SkEnumBitMask<PredrawFlags> flags); 2383 std::optional<AutoLayerForImageFilter> aboutToDraw( 2384 const SkPaint& paint, 2385 const SkRect* rawBounds = nullptr); 2386 2387 // The bottom-most device in the stack, only changed by init(). Image properties and the final 2388 // canvas pixels are determined by this device. rootDevice()2389 SkDevice* rootDevice() const { 2390 SkASSERT(fRootDevice); 2391 return fRootDevice.get(); 2392 } 2393 2394 // The top-most device in the stack, will change within saveLayer()'s. All drawing and clipping 2395 // operations should route to this device. 2396 SkDevice* topDevice() const; 2397 2398 // Canvases maintain a sparse stack of layers, where the top-most layer receives the drawing, 2399 // clip, and matrix commands. There is a layer per call to saveLayer() using the 2400 // kFullLayer_SaveLayerStrategy. 2401 struct Layer { 2402 sk_sp<SkDevice> fDevice; 2403 skia_private::STArray<1, sk_sp<SkImageFilter>> fImageFilters; 2404 SkPaint fPaint; 2405 bool fIsCoverage; 2406 bool fDiscard; 2407 2408 Layer(sk_sp<SkDevice> device, 2409 FilterSpan imageFilters, 2410 const SkPaint& paint, 2411 bool isCoverage); 2412 }; 2413 2414 // Encapsulate state needed to restore from saveBehind() 2415 struct BackImage { 2416 // Out of line to avoid including SkSpecialImage.h 2417 BackImage(sk_sp<SkSpecialImage>, SkIPoint); 2418 BackImage(const BackImage&); 2419 BackImage(BackImage&&); 2420 BackImage& operator=(const BackImage&); 2421 ~BackImage(); 2422 2423 sk_sp<SkSpecialImage> fImage; 2424 SkIPoint fLoc; 2425 }; 2426 2427 class MCRec { 2428 public: 2429 // If not null, this MCRec corresponds with the saveLayer() record that made the layer. 2430 // The base "layer" is not stored here, since it is stored inline in SkCanvas and has no 2431 // restoration behavior. 2432 std::unique_ptr<Layer> fLayer; 2433 2434 // This points to the device of the top-most layer (which may be lower in the stack), or 2435 // to the canvas's fRootDevice. The MCRec does not own the device. 2436 SkDevice* fDevice; 2437 2438 std::unique_ptr<BackImage> fBackImage; 2439 SkM44 fMatrix; 2440 int fDeferredSaveCount = 0; 2441 2442 MCRec(SkDevice* device); 2443 MCRec(const MCRec* prev); 2444 ~MCRec(); 2445 2446 void newLayer(sk_sp<SkDevice> layerDevice, 2447 FilterSpan filters, 2448 const SkPaint& restorePaint, 2449 bool layerIsCoverage); 2450 2451 void reset(SkDevice* device); 2452 }; 2453 2454 // the first N recs that can fit here mean we won't call malloc 2455 static constexpr int kMCRecSize = 96; // most recent measurement 2456 static constexpr int kMCRecCount = 32; // common depth for save/restores 2457 2458 intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)]; 2459 2460 SkDeque fMCStack; 2461 // points to top of stack 2462 MCRec* fMCRec; 2463 2464 // Installed via init() 2465 sk_sp<SkDevice> fRootDevice; 2466 const SkSurfaceProps fProps; 2467 2468 int fSaveCount; // value returned by getSaveCount() 2469 2470 std::unique_ptr<SkRasterHandleAllocator> fAllocator; 2471 2472 SkSurface_Base* fSurfaceBase; getSurfaceBase()2473 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; } setSurfaceBase(SkSurface_Base * sb)2474 void setSurfaceBase(SkSurface_Base* sb) { 2475 fSurfaceBase = sb; 2476 } 2477 friend class SkSurface_Base; 2478 friend class SkSurface_Ganesh; 2479 2480 SkIRect fClipRestrictionRect = SkIRect::MakeEmpty(); 2481 int fClipRestrictionSaveCount = -1; 2482 2483 void doSave(); 2484 void checkForDeferredSave(); 2485 void internalSetMatrix(const SkM44&); 2486 2487 friend class SkAndroidFrameworkUtils; 2488 friend class SkCanvasPriv; // needs to expose android functions for testing outside android 2489 friend class AutoLayerForImageFilter; 2490 friend class SkSurface_Raster; // needs getDevice() 2491 friend class SkNoDrawCanvas; // needs resetForNextPicture() 2492 friend class SkNWayCanvas; 2493 friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>) 2494 friend class SkOverdrawCanvas; 2495 friend class SkRasterHandleAllocator; 2496 friend class SkRecords::Draw; 2497 template <typename Key> 2498 friend class SkTestCanvas; 2499 2500 protected: 2501 // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend) 2502 SkCanvas(const SkIRect& bounds); 2503 private: 2504 SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>, 2505 SkRasterHandleAllocator::Handle, const SkSurfaceProps* props); 2506 2507 SkCanvas(SkCanvas&&) = delete; 2508 SkCanvas(const SkCanvas&) = delete; 2509 SkCanvas& operator=(SkCanvas&&) = delete; 2510 SkCanvas& operator=(const SkCanvas&) = delete; 2511 2512 friend class sktext::gpu::Slug; 2513 friend class SkPicturePlayback; 2514 /** 2515 * Convert a SkTextBlob to a sktext::gpu::Slug using the current canvas state. 2516 */ 2517 sk_sp<sktext::gpu::Slug> convertBlobToSlug(const SkTextBlob& blob, SkPoint origin, 2518 const SkPaint& paint); 2519 2520 /** 2521 * Draw an sktext::gpu::Slug given the current canvas state. 2522 */ 2523 void drawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint); 2524 2525 /** Experimental 2526 * Saves the specified subset of the current pixels in the current layer, 2527 * and then clears those pixels to transparent black. 2528 * Restores the pixels on restore() by drawing them in SkBlendMode::kDstOver. 2529 * 2530 * @param subset conservative bounds of the area to be saved / restored. 2531 * @return depth of save state stack before this call was made. 2532 */ 2533 int only_axis_aligned_saveBehind(const SkRect* subset); 2534 2535 /** 2536 * Like drawPaint, but magically clipped to the most recent saveBehind buffer rectangle. 2537 * If there is no active saveBehind, then this draws nothing. 2538 */ 2539 void drawClippedToSaveBehind(const SkPaint&); 2540 2541 void resetForNextPicture(const SkIRect& bounds); 2542 2543 // needs gettotalclip() 2544 friend class SkCanvasStateUtils; 2545 2546 void init(sk_sp<SkDevice>); 2547 2548 // All base onDrawX() functions should call this and skip drawing if it returns true. 2549 // If 'matrix' is non-null, it maps the paint's fast bounds before checking for quick rejection 2550 bool internalQuickReject(const SkRect& bounds, const SkPaint& paint, 2551 const SkMatrix* matrix = nullptr); 2552 2553 void internalDrawPaint(const SkPaint& paint); 2554 void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy, bool coverageOnly=false); 2555 void internalSaveBehind(const SkRect*); 2556 2557 void internalConcat44(const SkM44&); 2558 2559 // shared by save() and saveLayer() 2560 void internalSave(); 2561 void internalRestore(); 2562 2563 enum class DeviceCompatibleWithFilter : bool { 2564 // Check the src device's local-to-device matrix for compatibility with the filter, and if 2565 // it is not compatible, introduce an intermediate image and transformation that allows the 2566 // filter to be evaluated on the modified src content. 2567 kUnknown = false, 2568 // Assume that the src device's local-to-device matrix is compatible with the filter. 2569 kYes = true 2570 }; 2571 /** 2572 * Filters the contents of 'src' and draws the result into 'dst'. The filter is evaluated 2573 * relative to the current canvas matrix, and src is drawn to dst using their relative transform 2574 * 'paint' is applied after the filter and must not have a mask or image filter of its own. 2575 * A null 'filter' behaves as if the identity filter were used. 2576 * 2577 * 'scaleFactor' is an extra uniform scale transform applied to downscale the 'src' image 2578 * before any filtering, or as part of the copy, and is then drawn with 1/scaleFactor to 'dst'. 2579 * Must be 1.0 if 'compat' is kYes (i.e. any scale factor has already been baked into the 2580 * relative transforms between the devices). 2581 */ 2582 void internalDrawDeviceWithFilter(SkDevice* src, SkDevice* dst, 2583 FilterSpan filters, const SkPaint& paint, 2584 DeviceCompatibleWithFilter compat, 2585 const SkColorInfo& filterColorInfo, 2586 SkScalar scaleFactor = 1.f, 2587 bool srcIsCoverageLayer = false); 2588 2589 /* 2590 * Returns true if drawing the specified rect (or all if it is null) with the specified 2591 * paint (or default if null) would overwrite the entire root device of the canvas 2592 * (i.e. the canvas' surface if it had one). 2593 */ 2594 bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, 2595 SkEnumBitMask<PredrawFlags>) const; 2596 2597 /** 2598 * Returns true if the clip (for any active layer) contains antialiasing. 2599 * If the clip is empty, this will return false. 2600 */ 2601 bool androidFramework_isClipAA() const; 2602 2603 /** 2604 * Reset the clip to be wide-open (modulo any separately specified device clip restriction). 2605 * This operate within the save/restore clip stack so it can be undone by restoring to an 2606 * earlier save point. 2607 */ 2608 void internal_private_resetClip(); 2609 internal_private_asPaintFilterCanvas()2610 virtual SkPaintFilterCanvas* internal_private_asPaintFilterCanvas() const { return nullptr; } 2611 2612 // Keep track of the device clip bounds in the canvas' global space to reject draws before 2613 // invoking the top-level device. 2614 SkRect fQuickRejectBounds; 2615 2616 // Compute the clip's bounds based on all clipped SkDevice's reported device bounds transformed 2617 // into the canvas' global space. 2618 SkRect computeDeviceClipBounds(bool outsetForAA=true) const; 2619 2620 // Attempt to draw a rrect with an analytic blur. If the paint does not contain a blur, or the 2621 // geometry can't be drawn with an analytic blur by the device, a layer is returned for a 2622 // regular draw. If the draw succeeds or predrawNotify fails, nullopt is returned indicating 2623 // that nothing further should be drawn. 2624 std::optional<AutoLayerForImageFilter> attemptBlurredRRectDraw(const SkRRect&, 2625 const SkPaint&, 2626 SkEnumBitMask<PredrawFlags>); 2627 2628 class AutoUpdateQRBounds; 2629 void validateClip() const; 2630 2631 std::unique_ptr<sktext::GlyphRunBuilder> fScratchGlyphRunBuilder; 2632 }; 2633 2634 /** \class SkAutoCanvasRestore 2635 Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore 2636 goes out of scope. Use this to guarantee that the canvas is restored to a known 2637 state. 2638 */ 2639 class SkAutoCanvasRestore { 2640 public: 2641 2642 /** Preserves SkCanvas::save() count. Optionally saves SkCanvas clip and SkCanvas matrix. 2643 2644 @param canvas SkCanvas to guard 2645 @param doSave call SkCanvas::save() 2646 @return utility to restore SkCanvas state on destructor 2647 */ SkAutoCanvasRestore(SkCanvas * canvas,bool doSave)2648 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) { 2649 if (fCanvas) { 2650 fSaveCount = canvas->getSaveCount(); 2651 if (doSave) { 2652 canvas->save(); 2653 } 2654 } 2655 } 2656 2657 /** Restores SkCanvas to saved state. Destructor is called when container goes out of 2658 scope. 2659 */ ~SkAutoCanvasRestore()2660 ~SkAutoCanvasRestore() { 2661 if (fCanvas) { 2662 fCanvas->restoreToCount(fSaveCount); 2663 } 2664 } 2665 2666 /** Restores SkCanvas to saved state immediately. Subsequent calls and 2667 ~SkAutoCanvasRestore() have no effect. 2668 */ restore()2669 void restore() { 2670 if (fCanvas) { 2671 fCanvas->restoreToCount(fSaveCount); 2672 fCanvas = nullptr; 2673 } 2674 } 2675 2676 private: 2677 SkCanvas* fCanvas; 2678 int fSaveCount; 2679 2680 SkAutoCanvasRestore(SkAutoCanvasRestore&&) = delete; 2681 SkAutoCanvasRestore(const SkAutoCanvasRestore&) = delete; 2682 SkAutoCanvasRestore& operator=(SkAutoCanvasRestore&&) = delete; 2683 SkAutoCanvasRestore& operator=(const SkAutoCanvasRestore&) = delete; 2684 }; 2685 2686 #endif 2687