1 #Topic Canvas 2 #Alias Canvas_Reference 3 4 #Subtopic Overview 5 #Subtopic Subtopics 6 #Populate 7 ## 8 ## 9 10 #Class SkCanvas 11 12 Canvas provides an interface for drawing, and how the drawing is clipped and transformed. 13 Canvas contains a stack of Matrix and Clip values. 14 15 Canvas and Paint together provide the state to draw into Surface or Device. 16 Each Canvas draw call transforms the geometry of the object by the concatenation of all 17 Matrix values in the stack. The transformed geometry is clipped by the intersection 18 of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing 19 state such as Color, Typeface, text size, stroke width, Shader and so on. 20 21 To draw to a pixel-based destination, create Raster_Surface or GPU_Surface. 22 Request Canvas from Surface to obtain the interface to draw. 23 Canvas generated by Raster_Surface draws to memory visible to the CPU. 24 Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU. 25 26 To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder. 27 Document based Canvas and other Canvas Subclasses reference Device describing the 28 destination. 29 30 Canvas can be constructed to draw to Bitmap without first creating Raster_Surface. 31 This approach may be deprecated in the future. 32 33 #Subtopic Related_Functions 34 #Populate 35 ## 36 37 #Subtopic Constants 38 #Populate 39 ## 40 41 #Subtopic Classes_and_Structs 42 #Populate 43 ## 44 45 #Subtopic Constructors 46 47 Create the desired type of Surface to obtain its Canvas when possible. Constructors are useful 48 when no Surface is required, and some helpers implicitly create Raster_Surface. 49 50 #Populate 51 ## 52 53 #Subtopic Member_Functions 54 #Populate 55 ## 56 57 # ------------------------------------------------------------------------------ 58 59 #Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels, 60 size_t rowBytes, 61 const SkSurfaceProps* props = nullptr) 62 #Line # creates from SkImageInfo and Pixel_Storage ## 63 64 Allocates raster Canvas that will draw directly into pixels. 65 66 Canvas is returned if all parameters are valid. 67 Valid parameters include: 68 info dimensions are zero or positive; 69 info contains Color_Type and Alpha_Type supported by Raster_Surface; 70 pixels is not nullptr; 71 rowBytes is zero or large enough to contain info width pixels of Color_Type. 72 73 Pass zero for rowBytes to compute rowBytes from info width and size of pixel. 74 If rowBytes is greater than zero, it must be equal to or greater than 75 info width times bytes required for Color_Type. 76 77 Pixel buffer size should be info height times computed rowBytes. 78 Pixels are not initialized. 79 To access pixels after drawing, call flush() or peekPixels. 80 81 #Param info width, height, Color_Type, Alpha_Type, Color_Space, of Raster_Surface; 82 width, or height, or both, may be zero 83 ## 84 #Param pixels pointer to destination pixels buffer 85 ## 86 #Param rowBytes interval from one Surface row to the next, or zero 87 ## 88 #Param props LCD striping orientation and setting for device independent fonts; 89 may be nullptr 90 ## 91 92 #Return Canvas if all parameters are valid; otherwise, nullptr ## 93 94 #Example 95 #Description 96 Allocates a three by three bitmap, clears it to white, and draws a black pixel 97 in the center. 98 ## 99 void draw(SkCanvas* ) { 100 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied 101 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row 102 const size_t size = info.computeMinByteSize(); // bytes used by all rows 103 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels 104 SkPMColor* pixels = storage.get(); // get pointer to allocated storage 105 // create a SkCanvas backed by a raster device, and delete it when the 106 // function goes out of scope. 107 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes); 108 canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order 109 canvas->flush(); // ensure that pixels are cleared 110 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary 111 SkPaint paint; // by default, draws black 112 canvas->drawPoint(1, 1, paint); // draw in the center 113 canvas->flush(); // ensure that point was drawn 114 for (int y = 0; y < info.height(); ++y) { 115 for (int x = 0; x < info.width(); ++x) { 116 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); 117 } 118 SkDebugf("\n"); 119 } 120 } 121 #StdOut 122 --- 123 -x- 124 --- 125 ## 126 ## 127 128 #SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect 129 130 ## 131 132 # ------------------------------------------------------------------------------ 133 134 #Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels, 135 size_t rowBytes) 136 #Line # creates from image data and Pixel_Storage ## 137 138 Allocates raster Canvas specified by inline image specification. Subsequent Canvas 139 calls draw into pixels. 140 Color_Type is set to kN32_SkColorType. 141 Alpha_Type is set to kPremul_SkAlphaType. 142 To access pixels after drawing, call flush() or peekPixels. 143 144 Canvas 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 Color_Type. 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 ## 161 #Param rowBytes interval from one Surface row to the next, or zero 162 ## 163 164 #Return Canvas if all parameters are valid; otherwise, nullptr ## 165 166 #Example 167 #Description 168 Allocates a three by three bitmap, clears it to white, and draws a black pixel 169 in the center. 170 ## 171 void draw(SkCanvas* ) { 172 const int width = 3; 173 const int height = 3; 174 SkPMColor pixels[height][width]; // allocate a 3x3 Premultiplied bitmap on the stack 175 // create a SkCanvas backed by a raster device, and delete it when the 176 // function goes out of scope. 177 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32( 178 width, 179 height, 180 pixels[0], // top-left of the bitmap 181 sizeof(pixels[0])); // byte width of the each row 182 // write a premultiplied value for white into all pixels in the bitmap 183 canvas->clear(SK_ColorWHITE); 184 SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary 185 SkPaint paint; // by default, draws black 186 canvas->drawPoint(1, 1, paint); // draw in the center 187 canvas->flush(); // ensure that pixels is ready to be read 188 for (int y = 0; y < height; ++y) { 189 for (int x = 0; x < width; ++x) { 190 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x'); 191 } 192 SkDebugf("\n"); 193 } 194 } 195 #StdOut 196 --- 197 -x- 198 --- 199 ## 200 ## 201 202 #SeeAlso MakeRasterDirect SkSurface::MakeRasterDirect SkImageInfo::MakeN32Premul 203 204 ## 205 206 # ------------------------------------------------------------------------------ 207 208 #Method SkCanvas() 209 210 #Line # creates with no Surface, no dimensions ## 211 Creates an empty Canvas with no backing device or pixels, with 212 a width and height of zero. 213 214 #Return empty Canvas ## 215 216 #Example 217 218 #Description 219 Passes a placeholder to a function that requires one. 220 ## 221 222 #Function 223 // Returns true if either the canvas rotates the text by 90 degrees, or the paint does. 224 static void check_for_up_and_down_text(const SkCanvas* canvas, const SkPaint& paint) { 225 bool paintHasVertical = paint.isVerticalText(); 226 const SkMatrix& matrix = canvas->getTotalMatrix(); 227 bool matrixIsVertical = matrix.preservesRightAngles() && !matrix.isScaleTranslate(); 228 SkDebugf("paint draws text %s\n", paintHasVertical != matrixIsVertical ? 229 "top to bottom" : "left to right"); 230 } 231 232 static void check_for_up_and_down_text(const SkPaint& paint) { 233 SkCanvas canvas; // placeholder only, does not have an associated device 234 check_for_up_and_down_text(&canvas, paint); 235 } 236 237 ## 238 void draw(SkCanvas* canvas) { 239 SkPaint paint; 240 check_for_up_and_down_text(paint); // paint draws text left to right 241 paint.setVerticalText(true); 242 check_for_up_and_down_text(paint); // paint draws text top to bottom 243 paint.setVerticalText(false); 244 canvas->rotate(90); 245 check_for_up_and_down_text(canvas, paint); // paint draws text top to bottom 246 } 247 248 #StdOut 249 paint draws text left to right 250 paint draws text top to bottom 251 paint draws text top to bottom 252 ## 253 ## 254 255 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 256 257 ## 258 259 # ------------------------------------------------------------------------------ 260 261 #Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr) 262 263 #Line # no Surface, set dimensions, Surface_Properties ## 264 Creates Canvas of the specified dimensions without a Surface. 265 Used by Subclasses with custom implementations for draw methods. 266 267 If props equals nullptr, Surface_Properties are created with 268 Surface_Properties_Legacy_Font_Host settings, which choose the pixel striping 269 direction and order. Since a platform may dynamically change its direction when 270 the device is rotated, and since a platform may have multiple monitors with 271 different characteristics, it is best not to rely on this legacy behavior. 272 273 #Param width zero or greater ## 274 #Param height zero or greater ## 275 #Param props LCD striping orientation and setting for device independent fonts; 276 may be nullptr 277 ## 278 279 #Return Canvas placeholder with dimensions ## 280 281 #Example 282 SkCanvas canvas(10, 20); // 10 units wide, 20 units high 283 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device 284 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not"); 285 286 #StdOut 287 canvas is empty 288 ## 289 ## 290 291 #SeeAlso MakeRasterDirect SkSurfaceProps SkPixelGeometry SkCreateColorSpaceXformCanvas 292 293 ## 294 295 # ------------------------------------------------------------------------------ 296 297 #Method explicit SkCanvas(SkBaseDevice* device) 298 299 #Line # to be deprecated ## 300 Construct a canvas that draws into device. 301 Used by child classes of SkCanvas. 302 303 #ToDo Since SkBaseDevice is private, shouldn't this be private also? ## 304 305 #Param device specifies a device for the canvas to draw into ## 306 307 #Return Canvas that can be used to draw into device ## 308 309 #ToDo unsure how to create a meaningful example ## 310 #NoExample 311 ## 312 313 #ToDo either remove doc or figure out a way to fiddle it ## 314 315 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 316 317 ## 318 319 # ------------------------------------------------------------------------------ 320 321 #Method explicit SkCanvas(const SkBitmap& bitmap) 322 323 #Line # uses existing Bitmap ## 324 Construct a canvas that draws into bitmap. 325 Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed Surface. 326 327 Bitmap is copied so that subsequently editing bitmap will not affect 328 constructed Canvas. 329 330 May be deprecated in the future. 331 332 #ToDo Should be deprecated? ## 333 334 #Param bitmap width, height, Color_Type, Alpha_Type, and pixel 335 storage of Raster_Surface 336 ## 337 338 #Return Canvas that can be used to draw into bitmap ## 339 340 #Example 341 #Description 342 The actual output depends on the installed fonts. 343 ## 344 SkBitmap bitmap; 345 // create a bitmap 5 wide and 11 high 346 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11)); 347 SkCanvas canvas(bitmap); 348 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order 349 SkPixmap pixmap; // provides guaranteed access to the drawn pixels 350 if (!canvas.peekPixels(&pixmap)) { 351 SkDebugf("peekPixels should never fail.\n"); 352 } 353 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap 354 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary 355 SkPaint paint; // by default, draws black, 12 point text 356 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10) 357 for (int y = 0; y < bitmap.height(); ++y) { 358 for (int x = 0; x < bitmap.width(); ++x) { 359 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); 360 } 361 SkDebugf("\n"); 362 } 363 364 #StdOut 365 ----- 366 ---x- 367 ---x- 368 ---x- 369 ---x- 370 ---x- 371 ---x- 372 ----- 373 ---x- 374 ---x- 375 ----- 376 #StdOut ## 377 ## 378 379 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 380 381 ## 382 383 #EnumClass ColorBehavior 384 #Line # Android framework only ## 385 #Private 386 Android framework only. 387 ## 388 389 #Code 390 enum class ColorBehavior { 391 kLegacy, 392 }; 393 ## 394 #Const kLegacy 0 395 Is a placeholder to allow specialized constructor; has no meaning. 396 ## 397 ## 398 399 #Method SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior) 400 401 #Line # Android framework only ## 402 #Private 403 Android framework only. 404 ## 405 406 #Param bitmap specifies a bitmap for the canvas to draw into ## 407 #Param behavior specializes this constructor; value is unused ## 408 #Return Canvas that can be used to draw into bitmap ## 409 410 #NoExample 411 ## 412 ## 413 414 # ------------------------------------------------------------------------------ 415 416 #Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) 417 418 #Line # uses existing Bitmap and Surface_Properties ## 419 Construct a canvas that draws into bitmap. 420 Use props to match the device characteristics, like LCD striping. 421 422 bitmap is copied so that subsequently editing bitmap will not affect 423 constructed Canvas. 424 425 #Param bitmap width, height, Color_Type, Alpha_Type, 426 and pixel storage of Raster_Surface 427 ## 428 #Param props order and orientation of RGB striping; and whether to use 429 device independent fonts 430 ## 431 432 #Return Canvas that can be used to draw into bitmap ## 433 434 #Example 435 #Description 436 The actual output depends on the installed fonts. 437 ## 438 SkBitmap bitmap; 439 // create a bitmap 5 wide and 11 high 440 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11)); 441 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); 442 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order 443 SkPixmap pixmap; // provides guaranteed access to the drawn pixels 444 if (!canvas.peekPixels(&pixmap)) { 445 SkDebugf("peekPixels should never fail.\n"); 446 } 447 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap 448 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary 449 SkPaint paint; // by default, draws black, 12 point text 450 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10) 451 for (int y = 0; y < bitmap.height(); ++y) { 452 for (int x = 0; x < bitmap.width(); ++x) { 453 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); 454 } 455 SkDebugf("\n"); 456 } 457 458 #StdOut 459 ----- 460 ---x- 461 ---x- 462 ---x- 463 ---x- 464 ---x- 465 ---x- 466 ----- 467 ---x- 468 ---x- 469 ----- 470 #StdOut ## 471 ## 472 473 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 474 475 ## 476 477 # ------------------------------------------------------------------------------ 478 479 #Method virtual ~SkCanvas() 480 481 #Line # draws saved Layers, frees resources ## 482 Draws saved Layers, if any. 483 Frees up resources used by Canvas. 484 485 #Example 486 #Description 487 Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional 488 drawing surface that blends with the bitmap. When Layer goes out of 489 scope, Layer Destructor is called. The saved Layer is restored, drawing 490 transparent letters. 491 ## 492 void draw(SkCanvas* canvas) { 493 SkBitmap bitmap; 494 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200)); 495 { 496 SkCanvas offscreen(bitmap); 497 SkPaint paint; 498 paint.setTextSize(100); 499 offscreen.drawString("ABC", 20, 160, paint); 500 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192); 501 offscreen.saveLayerAlpha(&layerBounds, 128); 502 offscreen.clear(SK_ColorWHITE); 503 offscreen.drawString("DEF", 20, 160, paint); 504 } 505 canvas->drawBitmap(bitmap, 0, 0, nullptr); 506 } 507 ## 508 509 #SeeAlso State_Stack 510 511 ## 512 513 # ------------------------------------------------------------------------------ 514 515 #Method SkMetaData& getMetaData() 516 517 #Line # associates additional data with the canvas ## 518 Returns storage to associate additional data with the canvas. 519 The storage is freed when Canvas is deleted. 520 521 #Return storage that can be read from and written to ## 522 523 #Example 524 const char* kHelloMetaData = "HelloMetaData"; 525 SkCanvas canvas; 526 SkMetaData& metaData = canvas.getMetaData(); 527 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData)); 528 metaData.setString(kHelloMetaData, "Hello!"); 529 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData)); 530 metaData.removeString(kHelloMetaData); 531 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData)); 532 533 #StdOut 534 before: (null) 535 during: Hello! 536 after: (null) 537 #StdOut ## 538 ## 539 540 #SeeAlso SkMetaData 541 542 ## 543 544 # ------------------------------------------------------------------------------ 545 546 #Method SkImageInfo imageInfo() const 547 548 #Line # returns Image_Info for Canvas ## 549 Returns Image_Info for Canvas. If Canvas is not associated with Raster_Surface or 550 GPU_Surface, returned Color_Type is set to kUnknown_SkColorType. 551 552 #Return dimensions and Color_Type of Canvas ## 553 554 #Example 555 SkCanvas emptyCanvas; 556 SkImageInfo canvasInfo = emptyCanvas.imageInfo(); 557 SkImageInfo emptyInfo; 558 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!'); 559 560 #StdOut 561 emptyInfo == canvasInfo 562 ## 563 ## 564 565 #SeeAlso SkImageInfo MakeRasterDirect makeSurface 566 567 ## 568 569 # ------------------------------------------------------------------------------ 570 571 #Method bool getProps(SkSurfaceProps* props) const 572 573 #Line # copies Surface_Properties if available ## 574 If Canvas is associated with Raster_Surface or 575 GPU_Surface, copies Surface_Properties and returns true. Otherwise, 576 return false and leave props unchanged. 577 578 #Param props storage for writable SkSurfaceProps ## 579 580 #Return true if Surface_Properties was copied ## 581 582 #ToDo This seems old style. Deprecate? ## 583 584 #Example 585 SkBitmap bitmap; 586 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry)); 587 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); 588 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry())); 589 if (!canvas.getProps(&surfaceProps)) { 590 SkDebugf("getProps failed unexpectedly.\n"); 591 } 592 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry())); 593 594 #StdOut 595 isRGB:0 596 isRGB:1 597 #StdOut ## 598 ## 599 600 #SeeAlso SkSurfaceProps makeSurface 601 602 ## 603 604 # ------------------------------------------------------------------------------ 605 606 #Method void flush() 607 608 #Line # triggers execution of all pending draw operations ## 609 Triggers the immediate execution of all pending draw operations. 610 If Canvas is associated with GPU_Surface, resolves all pending GPU operations. 611 If Canvas is associated with Raster_Surface, has no effect; raster draw 612 operations are never deferred. 613 614 #ToDo 615 In an overview section on managing the GPU, include: 616 - flush should never change what is drawn 617 - call to kick off gpu work 618 - calling too much impacts performance 619 - some calls (peekPixels, prepareForExternalIO) call it internally 620 - canvas call is local, GrContext::flush is global 621 - diffentiate between flush, flushAndSignalSemaphores 622 - normally never needs to be called 623 - call it when sharing gpu resources, feeling memory pressure, swapping out app, and before 624 abandoning context 625 - also call to say "I'm finished drawing here", e.g., when drawing to a GPU-backed offscreen surface 626 (created with SkSurface::MakeRenderTarget) 627 628 for posterity: this doesn't show a difference: fiddle.skia.org/c/@flushfail 629 ## 630 631 #ToDo haven't thought of a useful example to put here ## 632 #NoExample 633 ## 634 635 #SeeAlso peekPixels SkSurface::flush() GrContext::flush() SkSurface::prepareForExternalIO GrContext::abandonContext() 636 637 ## 638 639 # ------------------------------------------------------------------------------ 640 641 #Method virtual SkISize getBaseLayerSize() const 642 643 #Line # returns size of base Layer in global coordinates ## 644 Gets the size of the base or root Layer in global canvas coordinates. The 645 origin of the base Layer is always (0,0). The area available for drawing may be 646 smaller (due to clipping or saveLayer). 647 648 #Return integral width and height of base Layer ## 649 650 #Example 651 SkBitmap bitmap; 652 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30)); 653 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); 654 canvas.clipRect(SkRect::MakeWH(10, 40)); 655 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds(); 656 if (clipDeviceBounds.isEmpty()) { 657 SkDebugf("Empty clip bounds is unexpected!\n"); 658 } 659 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height()); 660 SkISize baseLayerSize = canvas.getBaseLayerSize(); 661 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height()); 662 663 #StdOut 664 clip=10,30 665 size=20,30 666 ## 667 ## 668 669 #ToDo is this the same as the width and height of surface? ## 670 671 #SeeAlso getDeviceClipBounds 672 673 ## 674 675 # ------------------------------------------------------------------------------ 676 677 #Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr) 678 679 #Line # creates Surface matching SkImageInfo and SkSurfaceProps ## 680 Creates Surface matching info and props, and associates it with Canvas. 681 Returns nullptr if no match found. 682 683 If props is nullptr, matches Surface_Properties in Canvas. If props is nullptr and Canvas 684 does not have Surface_Properties, creates Surface with default Surface_Properties. 685 686 #Param info width, height, Color_Type, Alpha_Type, and Color_Space ## 687 #Param props Surface_Properties to match; may be nullptr to match Canvas ## 688 689 #Return Surface matching info and props, or nullptr if no match is available ## 690 691 #Example 692 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6); 693 SkCanvas* smallCanvas = surface->getCanvas(); 694 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4); 695 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo); 696 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!'); 697 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height()); 698 699 #StdOut 700 compatible != nullptr 701 size = 3, 4 702 ## 703 ## 704 705 #SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps 706 707 ## 708 709 # ------------------------------------------------------------------------------ 710 711 #Method virtual GrContext* getGrContext() 712 713 #Line # returns GPU_Context of the GPU_Surface ## 714 Returns GPU_Context of the GPU_Surface associated with Canvas. 715 716 #Return GPU_Context, if available; nullptr otherwise ## 717 718 #Example 719 void draw(SkCanvas* canvas) { 720 if (canvas->getGrContext()) { 721 canvas->clear(SK_ColorRED); 722 } else { 723 canvas->clear(SK_ColorBLUE); 724 } 725 } 726 ## 727 728 #ToDo fiddle should show both CPU and GPU out ## 729 730 #SeeAlso GrContext 731 732 ## 733 734 # ------------------------------------------------------------------------------ 735 736 #Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr) 737 738 #Line # returns writable pixel access if available ## 739 Returns the pixel base address, Image_Info, rowBytes, and origin if the pixels 740 can be read directly. The returned address is only valid 741 while Canvas is in scope and unchanged. Any Canvas call or Surface call 742 may invalidate the returned address and other returned values. 743 744 If pixels are inaccessible, info, rowBytes, and origin are unchanged. 745 746 #Param info storage for writable pixels' Image_Info; may be nullptr ## 747 #Param rowBytes storage for writable pixels' row bytes; may be nullptr ## 748 #Param origin storage for Canvas top Layer origin, its top-left corner; 749 may be nullptr 750 ## 751 752 #Return address of pixels, or nullptr if inaccessible ## 753 754 #Example 755 void draw(SkCanvas* canvas) { 756 if (canvas->accessTopLayerPixels(nullptr, nullptr)) { 757 canvas->clear(SK_ColorRED); 758 } else { 759 canvas->clear(SK_ColorBLUE); 760 } 761 } 762 ## 763 764 #Example 765 #Description 766 Draws "ABC" on the device. Then draws "DEF" in Layer, and reads 767 Layer to add a large dotted "DEF". Finally blends Layer with the 768 device. 769 770 The Layer and blended result appear on the CPU and GPU but the large dotted 771 "DEF" appear only on the CPU. 772 ## 773 void draw(SkCanvas* canvas) { 774 SkPaint paint; 775 paint.setTextSize(100); 776 canvas->drawString("ABC", 20, 160, paint); 777 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192); 778 canvas->saveLayerAlpha(&layerBounds, 128); 779 canvas->clear(SK_ColorWHITE); 780 canvas->drawString("DEF", 20, 160, paint); 781 SkImageInfo imageInfo; 782 size_t rowBytes; 783 SkIPoint origin; 784 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin); 785 if (access) { 786 int h = imageInfo.height(); 787 int v = imageInfo.width(); 788 int rowWords = rowBytes / sizeof(uint32_t); 789 for (int y = 0; y < h; ++y) { 790 int newY = (y - h / 2) * 2 + h / 2; 791 if (newY < 0 || newY >= h) { 792 continue; 793 } 794 for (int x = 0; x < v; ++x) { 795 int newX = (x - v / 2) * 2 + v / 2; 796 if (newX < 0 || newX >= v) { 797 continue; 798 } 799 if (access[y * rowWords + x] == SK_ColorBLACK) { 800 access[newY * rowWords + newX] = SK_ColorGRAY; 801 } 802 } 803 } 804 805 } 806 canvas->restore(); 807 } 808 ## 809 810 #ToDo there are no callers of this that I can find. Deprecate? ## 811 #ToDo fiddle should show both CPU and GPU out ## 812 813 #SeeAlso SkImageInfo SkPixmap 814 815 ## 816 817 # ------------------------------------------------------------------------------ 818 819 #Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const 820 821 #Line # returns context that tracks Clip and Matrix ## 822 Returns custom context that tracks the Matrix and Clip. 823 824 Use Raster_Handle_Allocator to blend Skia drawing with custom drawing, typically performed 825 by the host platform user interface. The custom context returned is generated by 826 SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for 827 the drawing destination. 828 829 #Return context of custom allocation ## 830 831 #Example 832 #Description 833 #ToDo ## 834 ## 835 #Function 836 static void DeleteCallback(void*, void* context) { 837 delete (char*) context; 838 } 839 840 class CustomAllocator : public SkRasterHandleAllocator { 841 public: 842 bool allocHandle(const SkImageInfo& info, Rec* rec) override { 843 char* context = new char[4]{'s', 'k', 'i', 'a'}; 844 rec->fReleaseProc = DeleteCallback; 845 rec->fReleaseCtx = context; 846 rec->fHandle = context; 847 rec->fPixels = context; 848 rec->fRowBytes = 4; 849 return true; 850 } 851 852 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override { 853 // apply canvas matrix and clip to custom environment 854 } 855 }; 856 857 ## 858 void draw(SkCanvas* canvas) { 859 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); 860 std::unique_ptr<SkCanvas> c2 = 861 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>( 862 new CustomAllocator()), info); 863 char* context = (char*) c2->accessTopRasterHandle(); 864 SkDebugf("context = %.4s\n", context); 865 866 } 867 #StdOut 868 context = skia 869 ## 870 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ## 871 ## 872 873 #SeeAlso SkRasterHandleAllocator 874 875 ## 876 877 # ------------------------------------------------------------------------------ 878 879 #Method bool peekPixels(SkPixmap* pixmap) 880 881 #Line # returns if Canvas has direct access to its pixels ## 882 Returns true if Canvas has direct access to its pixels. 883 884 Pixels are readable when Device is raster. Pixels are not readable when Canvas 885 is returned from GPU_Surface, returned by SkDocument::beginPage, returned by 886 SkPictureRecorder::beginRecording, or Canvas is the base of a utility class 887 like SkDumpCanvas. 888 889 pixmap is valid only while Canvas is in scope and unchanged. Any 890 Canvas or Surface call may invalidate the pixmap values. 891 892 #Param pixmap storage for pixel state if pixels are readable; otherwise, ignored ## 893 894 #Return true if Canvas has direct access to pixels ## 895 896 #Example 897 SkPixmap pixmap; 898 if (canvas->peekPixels(&pixmap)) { 899 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height()); 900 } 901 #StdOut 902 width=256 height=256 903 ## 904 ## 905 906 #SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels 907 908 ## 909 910 # ------------------------------------------------------------------------------ 911 912 #Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 913 int srcX, int srcY) 914 #Line # copies and converts rectangle of pixels from Canvas ## 915 916 Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are 917 ignored. 918 919 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 920 Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()). 921 Copies each readable pixel intersecting both rectangles, without scaling, 922 converting to dstInfo.colorType() and dstInfo.alphaType() if required. 923 924 Pixels are readable when Device is raster, or backed by a GPU. 925 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 926 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 927 class like SkDumpCanvas. 928 929 The destination pixel storage must be allocated by the caller. 930 931 Pixel values are converted only if Color_Type and Alpha_Type 932 do not match. Only pixels within both source and destination rectangles 933 are copied. dstPixels contents outside Rect intersection are unchanged. 934 935 Pass negative values for srcX or srcY to offset pixels across or down destination. 936 937 Does not copy, and returns false if: 938 939 #List 940 # Source and destination rectangles do not intersect. ## 941 # Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ## 942 # Canvas pixels are not readable; for instance, Canvas is document-based. ## 943 # dstRowBytes is too small to contain one row of pixels. ## 944 ## 945 946 #Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ## 947 #Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ## 948 #Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ## 949 #Param srcX offset into readable pixels in x; may be negative ## 950 #Param srcY offset into readable pixels in y; may be negative ## 951 952 #Return true if pixels were copied ## 953 954 #Example 955 #Width 64 956 #Height 64 957 #Description 958 A black circle drawn on a blue background provides an image to copy. 959 readPixels copies one quarter of the canvas into each of the four corners. 960 The copied quarter circles overdraw the original circle. 961 ## 962 canvas->clear(SK_ColorBLUE); 963 SkPaint paint; 964 canvas->drawCircle(32, 32, 28, paint); 965 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType); 966 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height())); 967 sk_bzero(data->writable_data(), info.minRowBytes() * info.height()); 968 for (int x : { 32, -32 } ) { 969 for (int y : { 32, -32 } ) { 970 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y); 971 } 972 } 973 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes()); 974 canvas->drawImage(image, 0, 0); 975 ## 976 977 #Example 978 #Description 979 Canvas returned by Raster_Surface has Premultiplied pixel values. 980 clear() takes Unpremultiplied input with Color_Alpha equal 0x80 981 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha 982 to generate Premultiplied value 0x802B5580. readPixels converts pixel back 983 to Unpremultiplied value 0x8056A9FF, introducing error. 984 ## 985 canvas->clear(0x8055aaff); 986 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) { 987 uint32_t pixel = 0; 988 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType); 989 if (canvas->readPixels(info, &pixel, 4, 0, 0)) { 990 SkDebugf("pixel = %08x\n", pixel); 991 } 992 } 993 994 #StdOut 995 pixel = 802b5580 996 pixel = 8056a9ff 997 ## 998 ## 999 1000 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels 1001 1002 ## 1003 1004 # ------------------------------------------------------------------------------ 1005 1006 #Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY) 1007 1008 Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are 1009 ignored. 1010 1011 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 1012 Destination Rect corners are (0, 0) and (pixmap.width(), pixmap.height()). 1013 Copies each readable pixel intersecting both rectangles, without scaling, 1014 converting to pixmap.colorType() and pixmap.alphaType() if required. 1015 1016 Pixels are readable when Device is raster, or backed by a GPU. 1017 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 1018 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 1019 class like SkDumpCanvas. 1020 1021 Caller must allocate pixel storage in pixmap if needed. 1022 1023 Pixel values are converted only if Color_Type and Alpha_Type 1024 do not match. Only pixels within both source and destination Rects 1025 are copied. pixmap pixels contents outside Rect intersection are unchanged. 1026 1027 Pass negative values for srcX or srcY to offset pixels across or down pixmap. 1028 1029 Does not copy, and returns false if: 1030 1031 #List 1032 # Source and destination rectangles do not intersect. ## 1033 # Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ## 1034 # Canvas pixels are not readable; for instance, Canvas is document-based. ## 1035 # Pixmap pixels could not be allocated. ## 1036 # pixmap.rowBytes() is too small to contain one row of pixels. ## 1037 ## 1038 1039 #Param pixmap storage for pixels copied from Canvas ## 1040 #Param srcX offset into readable pixels in x; may be negative ## 1041 #Param srcY offset into readable pixels in y; may be negative ## 1042 1043 #Return true if pixels were copied ## 1044 1045 #Example 1046 #Description 1047 clear() takes Unpremultiplied input with Color_Alpha equal 0x80 1048 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha 1049 to generate Premultiplied value 0x802B5580. 1050 ## 1051 void draw(SkCanvas* canvas) { 1052 canvas->clear(0x8055aaff); 1053 uint32_t pixels[1] = { 0 }; 1054 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4); 1055 canvas->readPixels(pixmap, 0, 0); 1056 SkDebugf("pixel = %08x\n", pixels[0]); 1057 } 1058 #StdOut 1059 pixel = 802b5580 1060 ## 1061 ## 1062 1063 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels 1064 1065 ## 1066 1067 # ------------------------------------------------------------------------------ 1068 1069 #Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY) 1070 1071 Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are 1072 ignored. 1073 1074 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 1075 Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()). 1076 Copies each readable pixel intersecting both rectangles, without scaling, 1077 converting to bitmap.colorType() and bitmap.alphaType() if required. 1078 1079 Pixels are readable when Device is raster, or backed by a GPU. 1080 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 1081 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 1082 class like SkDumpCanvas. 1083 1084 Caller must allocate pixel storage in bitmap if needed. 1085 1086 Bitmap values are converted only if Color_Type and Alpha_Type 1087 do not match. Only pixels within both source and destination rectangles 1088 are copied. Bitmap pixels outside Rect intersection are unchanged. 1089 1090 Pass negative values for srcX or srcY to offset pixels across or down bitmap. 1091 1092 Does not copy, and returns false if: 1093 1094 #List 1095 # Source and destination rectangles do not intersect. ## 1096 # Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ## 1097 # Canvas pixels are not readable; for instance, Canvas is document-based. ## 1098 # bitmap pixels could not be allocated. ## 1099 # bitmap.rowBytes() is too small to contain one row of pixels. ## 1100 ## 1101 1102 #Param bitmap storage for pixels copied from Canvas ## 1103 #Param srcX offset into readable pixels in x; may be negative ## 1104 #Param srcY offset into readable pixels in y; may be negative ## 1105 1106 #Return true if pixels were copied ## 1107 1108 #Example 1109 #Description 1110 clear() takes Unpremultiplied input with Color_Alpha equal 0x80 1111 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha 1112 to generate Premultiplied value 0x802B5580. 1113 ## 1114 void draw(SkCanvas* canvas) { 1115 canvas->clear(0x8055aaff); 1116 SkBitmap bitmap; 1117 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1)); 1118 canvas->readPixels(bitmap, 0, 0); 1119 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]); 1120 } 1121 #StdOut 1122 pixel = 802b5580 1123 ## 1124 ## 1125 1126 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels 1127 1128 ## 1129 1130 # ------------------------------------------------------------------------------ 1131 1132 #Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y) 1133 1134 #Line # copies and converts rectangle of pixels to Canvas ## 1135 Copies Rect from pixels to Canvas. Matrix and Clip are ignored. 1136 Source Rect corners are (0, 0) and (info.width(), info.height()). 1137 Destination Rect corners are (x, y) and 1138 (imageInfo().width(), imageInfo().height()). 1139 1140 Copies each readable pixel intersecting both rectangles, without scaling, 1141 converting to imageInfo().colorType() and imageInfo().alphaType() if required. 1142 1143 Pixels are writable when Device is raster, or backed by a GPU. 1144 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage, 1145 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 1146 class like SkDumpCanvas. 1147 1148 Pixel values are converted only if Color_Type and Alpha_Type 1149 do not match. Only pixels within both source and destination rectangles 1150 are copied. Canvas pixels outside Rect intersection are unchanged. 1151 1152 Pass negative values for x or y to offset pixels to the left or 1153 above Canvas pixels. 1154 1155 Does not copy, and returns false if: 1156 1157 #List 1158 # Source and destination rectangles do not intersect. ## 1159 # pixels could not be converted to Canvas imageInfo().colorType() or 1160 imageInfo().alphaType(). ## 1161 # Canvas pixels are not writable; for instance, Canvas is document-based. ## 1162 # rowBytes is too small to contain one row of pixels. ## 1163 ## 1164 1165 #Param info width, height, Color_Type, and Alpha_Type of pixels ## 1166 #Param pixels pixels to copy, of size info.height() times rowBytes, or larger ## 1167 #Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ## 1168 #Param x offset into Canvas writable pixels in x; may be negative ## 1169 #Param y offset into Canvas writable pixels in y; may be negative ## 1170 1171 #Return true if pixels were written to Canvas ## 1172 1173 #Example 1174 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType); 1175 for (int y = 0; y < 256; ++y) { 1176 uint32_t pixels[256]; 1177 for (int x = 0; x < 256; ++x) { 1178 pixels[x] = SkColorSetARGB(x, x + y, x, x - y); 1179 } 1180 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y); 1181 } 1182 ## 1183 1184 #SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels 1185 1186 ## 1187 1188 # ------------------------------------------------------------------------------ 1189 1190 #Method bool writePixels(const SkBitmap& bitmap, int x, int y) 1191 1192 Copies Rect from pixels to Canvas. Matrix and Clip are ignored. 1193 Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()). 1194 1195 Destination Rect corners are (x, y) and 1196 (imageInfo().width(), imageInfo().height()). 1197 1198 Copies each readable pixel intersecting both rectangles, without scaling, 1199 converting to imageInfo().colorType() and imageInfo().alphaType() if required. 1200 1201 Pixels are writable when Device is raster, or backed by a GPU. 1202 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage, 1203 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 1204 class like SkDumpCanvas. 1205 1206 Pixel values are converted only if Color_Type and Alpha_Type 1207 do not match. Only pixels within both source and destination rectangles 1208 are copied. Canvas pixels outside Rect intersection are unchanged. 1209 1210 Pass negative values for x or y to offset pixels to the left or 1211 above Canvas pixels. 1212 1213 Does not copy, and returns false if: 1214 1215 #List 1216 # Source and destination rectangles do not intersect. ## 1217 # bitmap does not have allocated pixels. ## 1218 # bitmap pixels could not be converted to Canvas imageInfo().colorType() or 1219 imageInfo().alphaType(). ## 1220 # Canvas pixels are not writable; for instance, Canvas is document based. ## 1221 # bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ## 1222 ## 1223 1224 #Param bitmap contains pixels copied to Canvas ## 1225 #Param x offset into Canvas writable pixels in x; may be negative ## 1226 #Param y offset into Canvas writable pixels in y; may be negative ## 1227 1228 #Return true if pixels were written to Canvas ## 1229 1230 #Example 1231 void draw(SkCanvas* canvas) { 1232 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2); 1233 SkBitmap bitmap; 1234 bitmap.setInfo(imageInfo); 1235 uint32_t pixels[4]; 1236 bitmap.setPixels(pixels); 1237 for (int y = 0; y < 256; y += 2) { 1238 for (int x = 0; x < 256; x += 2) { 1239 pixels[0] = SkColorSetRGB(x, y, x | y); 1240 pixels[1] = SkColorSetRGB(x ^ y, y, x); 1241 pixels[2] = SkColorSetRGB(x, x & y, y); 1242 pixels[3] = SkColorSetRGB(~x, ~y, x); 1243 canvas->writePixels(bitmap, x, y); 1244 } 1245 } 1246 } 1247 ## 1248 1249 #SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels 1250 1251 ## 1252 1253 # ------------------------------------------------------------------------------ 1254 #Subtopic State_Stack 1255 #Line # stack of state for hierarchical drawing ## 1256 1257 Canvas maintains a stack of state that allows hierarchical drawing, commonly used 1258 to implement windows and views. The initial state has an identity matrix and and 1259 an infinite clip. Even with a wide-open clip, drawing is constrained by the 1260 bounds of the Canvas Surface or Device. 1261 1262 Canvas savable state consists of Clip, Matrix, and Draw_Filter. 1263 Clip describes the area that may be drawn to. 1264 Matrix transforms the geometry. 1265 Draw_Filter (deprecated on most platforms) modifies the paint before drawing. 1266 1267 save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha 1268 save state and return the depth of the stack. 1269 1270 restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved. 1271 1272 Each state on the stack intersects Clip with the previous Clip, 1273 and concatenates Matrix with the previous Matrix. 1274 The intersected Clip makes the drawing area the same or smaller; 1275 the concatenated Matrix may move the origin and potentially scale or rotate 1276 the coordinate space. 1277 1278 Canvas does not require balancing the state stack but it is a good idea 1279 to do so. Calling save() without restore() will eventually cause Skia to fail; 1280 mismatched save() and restore() create hard to find bugs. 1281 1282 It is not possible to use state to draw outside of the clip defined by the 1283 previous state. 1284 1285 #Example 1286 #Description 1287 Draw to ever smaller clips; then restore drawing to full canvas. 1288 Note that the second clipRect is not permitted to enlarge Clip. 1289 ## 1290 #Height 160 1291 void draw(SkCanvas* canvas) { 1292 SkPaint paint; 1293 canvas->save(); // records stack depth to restore 1294 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip 1295 canvas->clear(SK_ColorRED); // draws to limit of clip 1296 canvas->save(); // records stack depth to restore 1297 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored 1298 canvas->clear(SK_ColorBLUE); // draws to smaller clip 1299 canvas->restore(); // enlarges clip 1300 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn 1301 canvas->restore(); // enlarges clip 1302 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn 1303 } 1304 ## 1305 1306 Each Clip uses the current Matrix for its coordinates. 1307 1308 #Example 1309 #Description 1310 While clipRect is given the same rectangle twice, Matrix makes the second 1311 clipRect draw at half the size of the first. 1312 ## 1313 #Height 128 1314 void draw(SkCanvas* canvas) { 1315 canvas->clipRect(SkRect::MakeWH(100, 100)); 1316 canvas->clear(SK_ColorRED); 1317 canvas->scale(.5, .5); 1318 canvas->clipRect(SkRect::MakeWH(100, 100)); 1319 canvas->clear(SK_ColorBLUE); 1320 } 1321 ## 1322 1323 #SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount 1324 1325 #Method int save() 1326 1327 #In State_Stack 1328 #Line # saves Clip and Matrix on stack ## 1329 Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms). 1330 Calling restore() discards changes to Matrix, Clip, and Draw_Filter, 1331 restoring the Matrix, Clip, and Draw_Filter to their state when save() was called. 1332 1333 Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, 1334 and resetMatrix. Clip may be changed by clipRect, clipRRect, clipPath, clipRegion. 1335 1336 Saved Canvas state is put on a stack; multiple calls to save() should be balance 1337 by an equal number of calls to restore(). 1338 1339 Call restoreToCount with result to restore this and subsequent saves. 1340 1341 #Return depth of saved stack ## 1342 1343 #Example 1344 #Description 1345 The black square is translated 50 pixels down and to the right. 1346 Restoring Canvas state removes translate() from Canvas stack; 1347 the red square is not translated, and is drawn at the origin. 1348 ## 1349 #Height 100 1350 void draw(SkCanvas* canvas) { 1351 SkPaint paint; 1352 SkRect rect = { 0, 0, 25, 25 }; 1353 canvas->drawRect(rect, paint); 1354 canvas->save(); 1355 canvas->translate(50, 50); 1356 canvas->drawRect(rect, paint); 1357 canvas->restore(); 1358 paint.setColor(SK_ColorRED); 1359 canvas->drawRect(rect, paint); 1360 } 1361 ## 1362 1363 #SeeAlso saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount 1364 1365 ## 1366 1367 # ------------------------------------------------------------------------------ 1368 1369 #Method void restore() 1370 1371 #In State_Stack 1372 #Line # restores changes to Clip and Matrix, pops save stack ## 1373 Removes changes to Matrix, Clip, and Draw_Filter since Canvas state was 1374 last saved. The state is removed from the stack. 1375 1376 Does nothing if the stack is empty. 1377 1378 #Example 1379 void draw(SkCanvas* canvas) { 1380 SkCanvas simple; 1381 SkDebugf("depth = %d\n", simple.getSaveCount()); 1382 simple.restore(); 1383 SkDebugf("depth = %d\n", simple.getSaveCount()); 1384 } 1385 ## 1386 1387 #SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restoreToCount 1388 1389 ## 1390 1391 # ------------------------------------------------------------------------------ 1392 1393 #Method int getSaveCount() const 1394 1395 #In State_Stack 1396 #Line # returns depth of stack containing Clip and Matrix ## 1397 Returns the number of saved states, each containing: Matrix, Clip, and Draw_Filter. 1398 Equals the number of save() calls less the number of restore() calls plus one. 1399 The save count of a new canvas is one. 1400 1401 #Return depth of save state stack ## 1402 1403 #Example 1404 void draw(SkCanvas* canvas) { 1405 SkCanvas simple; 1406 SkDebugf("depth = %d\n", simple.getSaveCount()); 1407 simple.save(); 1408 SkDebugf("depth = %d\n", simple.getSaveCount()); 1409 simple.restore(); 1410 SkDebugf("depth = %d\n", simple.getSaveCount()); 1411 } 1412 #StdOut 1413 depth = 1 1414 depth = 2 1415 depth = 1 1416 ## 1417 ## 1418 1419 #SeeAlso save() restore() restoreToCount 1420 1421 ## 1422 1423 # ------------------------------------------------------------------------------ 1424 1425 #Method void restoreToCount(int saveCount) 1426 1427 #In State_Stack 1428 #Line # restores changes to Clip and Matrix to given depth ## 1429 Restores state to Matrix, Clip, and Draw_Filter values when save(), saveLayer, 1430 saveLayerPreserveLCDTextRequests, or saveLayerAlpha returned saveCount. 1431 1432 Does nothing if saveCount is greater than state stack count. 1433 Restores state to initial values if saveCount is less than or equal to one. 1434 1435 #Param saveCount depth of state stack to restore ## 1436 1437 #Example 1438 void draw(SkCanvas* canvas) { 1439 SkDebugf("depth = %d\n", canvas->getSaveCount()); 1440 canvas->save(); 1441 canvas->save(); 1442 SkDebugf("depth = %d\n", canvas->getSaveCount()); 1443 canvas->restoreToCount(0); 1444 SkDebugf("depth = %d\n", canvas->getSaveCount()); 1445 } 1446 #StdOut 1447 depth = 1 1448 depth = 3 1449 depth = 1 1450 ## 1451 ## 1452 1453 #SeeAlso restore() getSaveCount save() 1454 1455 ## 1456 1457 #Subtopic State_Stack ## 1458 1459 # ------------------------------------------------------------------------------ 1460 1461 #Subtopic Layer 1462 #Substitute layer 1463 #Alias Layers 1464 #Line # temporary Bitmap to draw into ## 1465 1466 Layer allocates a temporary Bitmap to draw into. When the drawing is 1467 complete, the Bitmap is drawn into the Canvas. 1468 1469 Layer is saved in a stack along with other saved state. When state with a Layer 1470 is restored, the Bitmap is drawn into the previous Layer. 1471 1472 Layer may be initialized with the contents of the previous Layer. When Layer is 1473 restored, its Bitmap can be modified by Paint passed to Layer to apply 1474 Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode. 1475 1476 #Method int saveLayer(const SkRect* bounds, const SkPaint* paint) 1477 1478 #In Layer 1479 #Line # saves Clip and Matrix on stack; creates Layer ## 1480 Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms), 1481 and allocates a Bitmap for subsequent drawing. 1482 Calling restore() discards changes to Matrix, Clip, and Draw_Filter, 1483 and draws the Bitmap. 1484 1485 Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), 1486 setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect, 1487 clipPath, clipRegion. 1488 1489 Rect bounds suggests but does not define the Bitmap size. To clip drawing to 1490 a specific rectangle, use clipRect. 1491 1492 Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and 1493 Blend_Mode when restore() is called. 1494 1495 Call restoreToCount with returned value to restore this and subsequent saves. 1496 1497 #Param bounds hint to limit the size of the Layer; may be nullptr ## 1498 #Param paint graphics state for Layer; may be nullptr ## 1499 1500 #Return depth of saved stack ## 1501 1502 #Example 1503 #Description 1504 Rectangles are blurred by Image_Filter when restore() draws Layer to main 1505 Canvas. 1506 ## 1507 #Height 128 1508 void draw(SkCanvas* canvas) { 1509 SkPaint paint, blur; 1510 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr)); 1511 canvas->saveLayer(nullptr, &blur); 1512 SkRect rect = { 25, 25, 50, 50}; 1513 canvas->drawRect(rect, paint); 1514 canvas->translate(50, 50); 1515 paint.setColor(SK_ColorRED); 1516 canvas->drawRect(rect, paint); 1517 canvas->restore(); 1518 } 1519 ## 1520 1521 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec 1522 1523 ## 1524 1525 #Method int saveLayer(const SkRect& bounds, const SkPaint* paint) 1526 1527 #In Layer 1528 Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms), 1529 and allocates a Bitmap for subsequent drawing. 1530 Calling restore() discards changes to Matrix, Clip, and Draw_Filter, 1531 and draws the Bitmap. 1532 1533 Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), 1534 setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect, 1535 clipPath, clipRegion. 1536 1537 Rect bounds suggests but does not define the Layer size. To clip drawing to 1538 a specific rectangle, use clipRect. 1539 1540 Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and 1541 Blend_Mode when restore() is called. 1542 1543 Call restoreToCount with returned value to restore this and subsequent saves. 1544 1545 #Param bounds hint to limit the size of Layer; may be nullptr ## 1546 #Param paint graphics state for Layer; may be nullptr ## 1547 1548 #Return depth of saved stack ## 1549 1550 #Example 1551 #Description 1552 Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas. 1553 The red rectangle is clipped; it does not fully fit on Layer. 1554 Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides. 1555 ## 1556 #Height 128 1557 void draw(SkCanvas* canvas) { 1558 SkPaint paint, blur; 1559 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr)); 1560 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur); 1561 SkRect rect = { 25, 25, 50, 50}; 1562 canvas->drawRect(rect, paint); 1563 canvas->translate(50, 50); 1564 paint.setColor(SK_ColorRED); 1565 canvas->drawRect(rect, paint); 1566 canvas->restore(); 1567 } 1568 ## 1569 1570 #SeeAlso save() restore() saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec 1571 1572 ## 1573 1574 #Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) 1575 1576 #In Layer 1577 #Line # saves Clip and Matrix on stack; creates Layer for LCD text ## 1578 Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms), 1579 and allocates a Bitmap for subsequent drawing. 1580 LCD_Text is preserved when the Layer is drawn to the prior Layer. 1581 1582 Calling restore() discards changes to Matrix, Clip, and Draw_Filter, 1583 and draws Layer. 1584 1585 Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), 1586 setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect, 1587 clipPath, clipRegion. 1588 1589 Rect bounds suggests but does not define the Layer size. To clip drawing to 1590 a specific rectangle, use clipRect. 1591 1592 Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and 1593 Blend_Mode when restore() is called. 1594 1595 Call restoreToCount with returned value to restore this and subsequent saves. 1596 1597 Draw text on an opaque background so that LCD_Text blends correctly with the 1598 prior Layer. LCD_Text drawn on a background with transparency may result in 1599 incorrect blending. 1600 1601 #Param bounds hint to limit the size of Layer; may be nullptr ## 1602 #Param paint graphics state for Layer; may be nullptr ## 1603 1604 #Return depth of saved stack ## 1605 1606 #Example 1607 SkPaint paint; 1608 paint.setAntiAlias(true); 1609 paint.setLCDRenderText(true); 1610 paint.setTextSize(20); 1611 for (auto preserve : { false, true } ) { 1612 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr) 1613 : canvas->saveLayer(nullptr, nullptr); 1614 SkPaint p; 1615 p.setColor(SK_ColorWHITE); 1616 // Comment out the next line to draw on a non-opaque background. 1617 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p); 1618 canvas->drawString("Hamburgefons", 30, 60, paint); 1619 1620 p.setColor(0xFFCCCCCC); 1621 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p); 1622 canvas->drawString("Hamburgefons", 30, 90, paint); 1623 1624 canvas->restore(); 1625 canvas->translate(0, 80); 1626 } 1627 ## 1628 1629 #SeeAlso save() restore() saveLayer saveLayerAlpha SaveLayerRec 1630 1631 ## 1632 1633 #Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) 1634 1635 #In Layer 1636 #Line # saves Clip and Matrix on stack; creates Layer; sets opacity ## 1637 Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms), 1638 and allocates Bitmap for subsequent drawing. 1639 1640 Calling restore() discards changes to Matrix, Clip, and Draw_Filter, 1641 and blends Layer with alpha opacity onto prior Layer. 1642 1643 Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), 1644 setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect, 1645 clipPath, clipRegion. 1646 1647 Rect bounds suggests but does not define Layer size. To clip drawing to 1648 a specific rectangle, use clipRect. 1649 1650 alpha of zero is fully transparent, 255 is fully opaque. 1651 1652 Call restoreToCount with returned value to restore this and subsequent saves. 1653 1654 #Param bounds hint to limit the size of Layer; may be nullptr ## 1655 #Param alpha opacity of Layer ## 1656 1657 #Return depth of saved stack ## 1658 1659 #Example 1660 SkPaint paint; 1661 paint.setColor(SK_ColorRED); 1662 canvas->drawCircle(50, 50, 50, paint); 1663 canvas->saveLayerAlpha(nullptr, 128); 1664 paint.setColor(SK_ColorBLUE); 1665 canvas->drawCircle(100, 50, 50, paint); 1666 paint.setColor(SK_ColorGREEN); 1667 paint.setAlpha(128); 1668 canvas->drawCircle(75, 90, 50, paint); 1669 canvas->restore(); 1670 ## 1671 1672 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests SaveLayerRec 1673 1674 ## 1675 1676 #ToDo 1677 add new markup to associate typedef SaveLayerFlags with Enum so that, for 1678 documentation purposes, this enum is named rather than anonymous 1679 ## 1680 1681 #Enum 1682 #Line # sets SaveLayerRec options ## 1683 #Code 1684 enum { 1685 kIsOpaque_SaveLayerFlag = 1 << 0, 1686 kPreserveLCDText_SaveLayerFlag = 1 << 1, 1687 kInitWithPrevious_SaveLayerFlag = 1 << 2, 1688 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag, 1689 }; 1690 ## 1691 1692 SaveLayerFlags provides options that may be used in any combination in SaveLayerRec, 1693 defining how Layer allocated by saveLayer operates. 1694 1695 #Const kIsOpaque_SaveLayerFlag 1 1696 Creates Layer without transparency. Flag is ignored if Layer Paint contains 1697 Image_Filter or Color_Filter. 1698 ## 1699 1700 #Const kPreserveLCDText_SaveLayerFlag 2 1701 Creates Layer for LCD text. Flag is ignored if Layer Paint contains 1702 Image_Filter or Color_Filter. 1703 ## 1704 1705 #Const kInitWithPrevious_SaveLayerFlag 4 1706 Initializes Layer with the contents of the previous Layer. 1707 ## 1708 1709 #Const kDontClipToLayer_Legacy_SaveLayerFlag 0x80000000 1710 #Private 1711 to be deprecated: bug.skia.org/2440 1712 ## 1713 Only present on Android. 1714 Skips setting a clip to the Layer bounds. 1715 ## 1716 1717 #Example 1718 #Height 160 1719 #Description 1720 Canvas Layer captures red and blue circles scaled up by four. 1721 scalePaint blends Layer back with transparency. 1722 ## 1723 void draw(SkCanvas* canvas) { 1724 SkPaint redPaint, bluePaint, scalePaint; 1725 redPaint.setColor(SK_ColorRED); 1726 canvas->drawCircle(21, 21, 8, redPaint); 1727 bluePaint.setColor(SK_ColorBLUE); 1728 canvas->drawCircle(31, 21, 8, bluePaint); 1729 SkMatrix matrix; 1730 matrix.setScale(4, 4); 1731 scalePaint.setAlpha(0x40); 1732 scalePaint.setImageFilter( 1733 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr)); 1734 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint, 1735 SkCanvas::kInitWithPrevious_SaveLayerFlag); 1736 canvas->saveLayer(saveLayerRec); 1737 canvas->restore(); 1738 } 1739 ## 1740 1741 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec 1742 1743 #Enum ## 1744 1745 #Typedef uint32_t SaveLayerFlags 1746 1747 ## 1748 1749 #Struct SaveLayerRec 1750 #Line # contains the state used to create the Layer ## 1751 #Code 1752 struct SaveLayerRec { 1753 SaveLayerRec*(... 1754 1755 const SkRect* fBounds; 1756 const SkPaint* fPaint; 1757 const SkImageFilter* fBackdrop; 1758 SaveLayerFlags fSaveLayerFlags; 1759 }; 1760 ## 1761 1762 SaveLayerRec contains the state used to create the Layer. 1763 1764 #Member const SkRect* fBounds 1765 fBounds is used as a hint to limit the size of Layer; may be nullptr. 1766 fBounds suggests but does not define Layer size. To clip drawing to 1767 a specific rectangle, use clipRect. 1768 ## 1769 1770 #Member const SkPaint* fPaint 1771 fPaint modifies how Layer overlays the prior Layer; may be nullptr. 1772 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and 1773 Mask_Filter affect Layer draw. 1774 ## 1775 1776 #Member const SkImageFilter* fBackdrop 1777 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer; 1778 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the 1779 prior Layer without an Image_Filter. 1780 ## 1781 1782 #Member const SkImage* fClipMask 1783 restore() clips Layer by the Color_Alpha channel of fClipMask when 1784 Layer is copied to Device. fClipMask may be nullptr. . 1785 ## 1786 1787 #Member const SkMatrix* fClipMatrix 1788 fClipMatrix transforms fClipMask before it clips Layer. If 1789 fClipMask describes a translucent gradient, it may be scaled and rotated 1790 without introducing artifacts. fClipMatrix may be nullptr. 1791 ## 1792 1793 #Member SaveLayerFlags fSaveLayerFlags 1794 fSaveLayerFlags are used to create Layer without transparency, 1795 create Layer for LCD text, and to create Layer with the 1796 contents of the previous Layer. 1797 ## 1798 1799 #Example 1800 #Height 160 1801 #Description 1802 Canvas Layer captures a red Anti-aliased circle and a blue Aliased circle scaled 1803 up by four. After drawing another red circle without scaling on top, the Layer is 1804 transferred to the main canvas. 1805 ## 1806 void draw(SkCanvas* canvas) { 1807 SkPaint redPaint, bluePaint; 1808 redPaint.setAntiAlias(true); 1809 redPaint.setColor(SK_ColorRED); 1810 canvas->drawCircle(21, 21, 8, redPaint); 1811 bluePaint.setColor(SK_ColorBLUE); 1812 canvas->drawCircle(31, 21, 8, bluePaint); 1813 SkMatrix matrix; 1814 matrix.setScale(4, 4); 1815 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr); 1816 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0); 1817 canvas->saveLayer(saveLayerRec); 1818 canvas->drawCircle(125, 85, 8, redPaint); 1819 canvas->restore(); 1820 } 1821 ## 1822 1823 #Method SaveLayerRec() 1824 1825 Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags. 1826 1827 #Return empty SaveLayerRec ## 1828 1829 #Example 1830 SkCanvas::SaveLayerRec rec1; 1831 rec1.fSaveLayerFlags = SkCanvas::kIsOpaque_SaveLayerFlag; 1832 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kIsOpaque_SaveLayerFlag); 1833 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds 1834 && rec1.fPaint == rec2.fPaint 1835 && rec1.fBackdrop == rec2.fBackdrop 1836 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!'); 1837 #StdOut 1838 rec1 == rec2 1839 ## 1840 ## 1841 1842 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha 1843 1844 ## 1845 1846 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0) 1847 1848 Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr. 1849 1850 #Param bounds Layer dimensions; may be nullptr ## 1851 #Param paint applied to Layer when overlaying prior Layer; may be nullptr ## 1852 #Param saveLayerFlags SaveLayerRec options to modify Layer ## 1853 1854 #Return SaveLayerRec with empty backdrop ## 1855 1856 #Example 1857 SkCanvas::SaveLayerRec rec1; 1858 SkCanvas::SaveLayerRec rec2(nullptr, nullptr); 1859 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds 1860 && rec1.fPaint == rec2.fPaint 1861 && rec1.fBackdrop == rec2.fBackdrop 1862 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!'); 1863 #StdOut 1864 rec1 == rec2 1865 ## 1866 ## 1867 1868 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha 1869 1870 ## 1871 1872 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, 1873 SaveLayerFlags saveLayerFlags) 1874 1875 Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags. 1876 1877 #Param bounds Layer dimensions; may be nullptr ## 1878 #Param paint applied to Layer when overlaying prior Layer; 1879 may be nullptr 1880 ## 1881 #Param backdrop prior Layer copied with Image_Filter; may be nullptr 1882 ## 1883 #Param saveLayerFlags SaveLayerRec options to modify Layer ## 1884 1885 #Return SaveLayerRec fully specified ## 1886 1887 #Example 1888 SkCanvas::SaveLayerRec rec1; 1889 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0); 1890 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds 1891 && rec1.fPaint == rec2.fPaint 1892 && rec1.fBackdrop == rec2.fBackdrop 1893 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!'); 1894 #StdOut 1895 rec1 == rec2 1896 ## 1897 ## 1898 1899 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha 1900 1901 ## 1902 1903 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, 1904 const SkImage* clipMask, const SkMatrix* clipMatrix, 1905 SaveLayerFlags saveLayerFlags) 1906 1907 #Experimental 1908 Not ready for general use. 1909 ## 1910 1911 Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags. 1912 clipMatrix uses Color_Alpha channel of image, transformed by clipMatrix, to clip 1913 Layer when drawn to Canvas. 1914 1915 Implementation is not complete; has no effect if Device is GPU-backed. 1916 1917 #Param bounds Layer dimensions; may be nullptr ## 1918 #Param paint graphics state applied to Layer when overlaying prior 1919 Layer; may be nullptr 1920 ## 1921 #Param backdrop prior Layer copied with Image_Filter; 1922 may be nullptr 1923 ## 1924 #Param clipMask clip applied to Layer; may be nullptr ## 1925 #Param clipMatrix matrix applied to clipMask; may be nullptr to use 1926 identity matrix 1927 ## 1928 #Param saveLayerFlags SaveLayerRec options to modify Layer ## 1929 1930 #Return SaveLayerRec fully specified ## 1931 1932 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha 1933 1934 ## 1935 1936 #Struct ## 1937 1938 #Method int saveLayer(const SaveLayerRec& layerRec) 1939 1940 #In Layer 1941 Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms), 1942 and allocates Bitmap for subsequent drawing. 1943 1944 Calling restore() discards changes to Matrix, Clip, and Draw_Filter, 1945 and blends Bitmap with Color_Alpha opacity onto the prior Layer. 1946 1947 Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), 1948 setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect, 1949 clipPath, clipRegion. 1950 1951 SaveLayerRec contains the state used to create the Layer. 1952 1953 Call restoreToCount with returned value to restore this and subsequent saves. 1954 1955 #Param layerRec Layer state ## 1956 1957 #Return depth of save state stack ## 1958 1959 #Example 1960 #Description 1961 The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag. 1962 Next it punches a hole in Layer and restore with SkBlendMode::kPlus. 1963 Where Layer was cleared, the original image will draw unchanged. 1964 Outside of the circle the mandrill is brightened. 1965 ## 1966 #Image 3 1967 // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png"); 1968 canvas->drawImage(image, 0, 0, nullptr); 1969 SkCanvas::SaveLayerRec rec; 1970 SkPaint paint; 1971 paint.setBlendMode(SkBlendMode::kPlus); 1972 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag; 1973 rec.fPaint = &paint; 1974 canvas->saveLayer(rec); 1975 paint.setBlendMode(SkBlendMode::kClear); 1976 canvas->drawCircle(128, 128, 96, paint); 1977 canvas->restore(); 1978 ## 1979 1980 #ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ## 1981 1982 #SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha 1983 1984 ## 1985 1986 #Subtopic Layer ## 1987 1988 # ------------------------------------------------------------------------------ 1989 #Subtopic Matrix 1990 #Line # coordinate transformation ## 1991 1992 #Method void translate(SkScalar dx, SkScalar dy) 1993 1994 #In Matrix 1995 #Line # translates Matrix ## 1996 Translate Matrix by dx along the x-axis and dy along the y-axis. 1997 1998 Mathematically, replace Matrix with a translation matrix 1999 Premultiplied with Matrix. 2000 2001 This has the effect of moving the drawing by (dx, dy) before transforming 2002 the result with Matrix. 2003 2004 #Param dx distance to translate in x ## 2005 #Param dy distance to translate in y ## 2006 2007 #Example 2008 #Height 128 2009 #Description 2010 scale() followed by translate() produces different results from translate() followed 2011 by scale(). 2012 2013 The blue stroke follows translate of (50, 50); a black 2014 fill follows scale of (2, 1/2.f). After restoring the clip, which resets 2015 Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill 2016 follows translate of (50, 50). 2017 ## 2018 void draw(SkCanvas* canvas) { 2019 SkPaint filledPaint; 2020 SkPaint outlinePaint; 2021 outlinePaint.setStyle(SkPaint::kStroke_Style); 2022 outlinePaint.setColor(SK_ColorBLUE); 2023 canvas->save(); 2024 canvas->translate(50, 50); 2025 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28) 2026 canvas->scale(2, 1/2.f); 2027 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2)) 2028 canvas->restore(); 2029 filledPaint.setColor(SK_ColorGRAY); 2030 outlinePaint.setColor(SK_ColorRED); 2031 canvas->scale(2, 1/2.f); 2032 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2) 2033 canvas->translate(50, 50); 2034 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2) 2035 } 2036 ## 2037 2038 #SeeAlso concat() scale() skew() rotate() setMatrix 2039 2040 ## 2041 2042 # ------------------------------------------------------------------------------ 2043 2044 #Method void scale(SkScalar sx, SkScalar sy) 2045 2046 #In Matrix 2047 #Line # scales Matrix ## 2048 Scale Matrix by sx on the x-axis and sy on the y-axis. 2049 2050 Mathematically, replace Matrix with a scale matrix 2051 Premultiplied with Matrix. 2052 2053 This has the effect of scaling the drawing by (sx, sy) before transforming 2054 the result with Matrix. 2055 2056 #Param sx amount to scale in x ## 2057 #Param sy amount to scale in y ## 2058 2059 #Example 2060 #Height 160 2061 void draw(SkCanvas* canvas) { 2062 SkPaint paint; 2063 SkRect rect = { 10, 20, 60, 120 }; 2064 canvas->translate(20, 20); 2065 canvas->drawRect(rect, paint); 2066 canvas->scale(2, .5f); 2067 paint.setColor(SK_ColorGRAY); 2068 canvas->drawRect(rect, paint); 2069 } 2070 ## 2071 2072 #SeeAlso concat() translate() skew() rotate() setMatrix 2073 2074 ## 2075 2076 # ------------------------------------------------------------------------------ 2077 2078 #Method void rotate(SkScalar degrees) 2079 2080 #In Matrix 2081 #Line # rotates Matrix ## 2082 Rotate Matrix by degrees. Positive degrees rotates clockwise. 2083 2084 Mathematically, replace Matrix with a rotation matrix 2085 Premultiplied with Matrix. 2086 2087 This has the effect of rotating the drawing by degrees before transforming 2088 the result with Matrix. 2089 2090 #Param degrees amount to rotate, in degrees ## 2091 2092 #Example 2093 #Description 2094 Draw clock hands at time 5:10. The hour hand and minute hand point up and 2095 are rotated clockwise. 2096 ## 2097 void draw(SkCanvas* canvas) { 2098 SkPaint paint; 2099 paint.setStyle(SkPaint::kStroke_Style); 2100 canvas->translate(128, 128); 2101 canvas->drawCircle(0, 0, 60, paint); 2102 canvas->save(); 2103 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees 2104 canvas->drawLine(0, 0, 0, -50, paint); 2105 canvas->restore(); 2106 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees 2107 canvas->drawLine(0, 0, 0, -30, paint); 2108 } 2109 ## 2110 2111 #SeeAlso concat() translate() skew() scale() setMatrix 2112 2113 ## 2114 2115 # ------------------------------------------------------------------------------ 2116 2117 #Method void rotate(SkScalar degrees, SkScalar px, SkScalar py) 2118 2119 #In Matrix 2120 Rotate Matrix by degrees about a point at (px, py). Positive degrees rotates 2121 clockwise. 2122 2123 Mathematically, construct a rotation matrix. Premultiply the rotation matrix by 2124 a translation matrix, then replace Matrix with the resulting matrix 2125 Premultiplied with Matrix. 2126 2127 This has the effect of rotating the drawing about a given point before 2128 transforming the result with Matrix. 2129 2130 #Param degrees amount to rotate, in degrees ## 2131 #Param px x-coordinate of the point to rotate about ## 2132 #Param py y-coordinate of the point to rotate about ## 2133 2134 #Example 2135 #Height 192 2136 void draw(SkCanvas* canvas) { 2137 SkPaint paint; 2138 paint.setTextSize(96); 2139 canvas->drawString("A1", 130, 100, paint); 2140 canvas->rotate(180, 130, 100); 2141 canvas->drawString("A1", 130, 100, paint); 2142 } 2143 ## 2144 2145 #SeeAlso concat() translate() skew() scale() setMatrix 2146 2147 ## 2148 2149 # ------------------------------------------------------------------------------ 2150 2151 #Method void skew(SkScalar sx, SkScalar sy) 2152 2153 #In Matrix 2154 #Line # skews Matrix ## 2155 Skew Matrix by sx on the x-axis and sy on the y-axis. A positive value of sx 2156 skews the drawing right as y increases; a positive value of sy skews the drawing 2157 down as x increases. 2158 2159 Mathematically, replace Matrix with a skew matrix Premultiplied with Matrix. 2160 2161 This has the effect of skewing the drawing by (sx, sy) before transforming 2162 the result with Matrix. 2163 2164 #Param sx amount to skew in x ## 2165 #Param sy amount to skew in y ## 2166 2167 #Example 2168 #Description 2169 Black text mimics an oblique text style by using a negative skew in x that 2170 shifts the geometry to the right as the y values decrease. 2171 Red text uses a positive skew in y to shift the geometry down as the x values 2172 increase. 2173 Blue text combines x and y skew to rotate and scale. 2174 ## 2175 SkPaint paint; 2176 paint.setTextSize(128); 2177 canvas->translate(30, 130); 2178 canvas->save(); 2179 canvas->skew(-.5, 0); 2180 canvas->drawString("A1", 0, 0, paint); 2181 canvas->restore(); 2182 canvas->save(); 2183 canvas->skew(0, .5); 2184 paint.setColor(SK_ColorRED); 2185 canvas->drawString("A1", 0, 0, paint); 2186 canvas->restore(); 2187 canvas->skew(-.5, .5); 2188 paint.setColor(SK_ColorBLUE); 2189 canvas->drawString("A1", 0, 0, paint); 2190 ## 2191 2192 #SeeAlso concat() translate() rotate() scale() setMatrix 2193 2194 ## 2195 2196 # ------------------------------------------------------------------------------ 2197 2198 #Method void concat(const SkMatrix& matrix) 2199 2200 #In Matrix 2201 #Line # multiplies Matrix by Matrix ## 2202 Replace Matrix with matrix Premultiplied with existing Matrix. 2203 2204 This has the effect of transforming the drawn geometry by matrix, before 2205 transforming the result with existing Matrix. 2206 2207 #Param matrix matrix to Premultiply with existing Matrix ## 2208 2209 #Example 2210 void draw(SkCanvas* canvas) { 2211 SkPaint paint; 2212 paint.setTextSize(80); 2213 paint.setTextScaleX(.3); 2214 SkMatrix matrix; 2215 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }}; 2216 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit); 2217 canvas->drawRect(rect[0], paint); 2218 canvas->drawRect(rect[1], paint); 2219 paint.setColor(SK_ColorWHITE); 2220 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint); 2221 canvas->concat(matrix); 2222 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint); 2223 } 2224 ## 2225 2226 #SeeAlso translate() rotate() scale() skew() setMatrix 2227 2228 ## 2229 2230 # ------------------------------------------------------------------------------ 2231 2232 #Method void setMatrix(const SkMatrix& matrix) 2233 2234 #In Matrix 2235 #Line # sets Matrix ## 2236 Replace Matrix with matrix. 2237 Unlike concat(), any prior matrix state is overwritten. 2238 2239 #Param matrix matrix to copy, replacing existing Matrix ## 2240 2241 #Example 2242 #Height 128 2243 void draw(SkCanvas* canvas) { 2244 SkPaint paint; 2245 canvas->scale(4, 6); 2246 canvas->drawString("truth", 2, 10, paint); 2247 SkMatrix matrix; 2248 matrix.setScale(2.8f, 6); 2249 canvas->setMatrix(matrix); 2250 canvas->drawString("consequences", 2, 20, paint); 2251 } 2252 ## 2253 2254 #SeeAlso resetMatrix concat() translate() rotate() scale() skew() 2255 2256 ## 2257 2258 # ------------------------------------------------------------------------------ 2259 2260 #Method void resetMatrix() 2261 2262 #In Matrix 2263 #Line # resets Matrix to identity ## 2264 Sets Matrix to the identity matrix. 2265 Any prior matrix state is overwritten. 2266 2267 #Example 2268 #Height 128 2269 void draw(SkCanvas* canvas) { 2270 SkPaint paint; 2271 canvas->scale(4, 6); 2272 canvas->drawString("truth", 2, 10, paint); 2273 canvas->resetMatrix(); 2274 canvas->scale(2.8f, 6); 2275 canvas->drawString("consequences", 2, 20, paint); 2276 } 2277 ## 2278 2279 #SeeAlso setMatrix concat() translate() rotate() scale() skew() 2280 2281 ## 2282 2283 # ------------------------------------------------------------------------------ 2284 2285 #Method const SkMatrix& getTotalMatrix() const 2286 2287 #In Matrix 2288 #Line # returns Matrix ## 2289 Returns Matrix. 2290 This does not account for translation by Device or Surface. 2291 2292 #Return Matrix in Canvas ## 2293 2294 #Example 2295 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false"); 2296 #StdOut 2297 isIdentity true 2298 ## 2299 ## 2300 2301 #SeeAlso setMatrix resetMatrix concat() 2302 2303 ## 2304 2305 #Subtopic Matrix ## 2306 2307 # ------------------------------------------------------------------------------ 2308 #Subtopic Clip 2309 #Line # stack of clipping Paths ## 2310 2311 Clip is built from a stack of clipping paths. Each Path in the 2312 stack can be constructed from one or more Path_Contour elements. The 2313 Path_Contour may be composed of any number of Path_Verb segments. Each 2314 Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed 2315 by Path_Contour. 2316 2317 Clip stack of Path elements successfully restrict the Path area. Each 2318 Path is transformed by Matrix, then intersected with or subtracted from the 2319 prior Clip to form the replacement Clip. Use SkClipOp::kDifference 2320 to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path 2321 with Clip. 2322 2323 A clipping Path may be Anti-aliased; if Path, after transformation, is 2324 composed of horizontal and vertical lines, clearing Anti-alias allows whole pixels 2325 to either be inside or outside the clip. The fastest drawing has a Aliased, 2326 rectangular clip. 2327 2328 If clipping Path has Anti-alias set, clip may partially clip a pixel, requiring 2329 that drawing blend partially with the destination along the edge. A rotated 2330 rectangular Anti-aliased clip looks smoother but draws slower. 2331 2332 Clip can combine with Rect and Round_Rect primitives; like 2333 Path, these are transformed by Matrix before they are combined with Clip. 2334 2335 Clip can combine with Region. Region is assumed to be in Device coordinates 2336 and is unaffected by Matrix. 2337 2338 #Example 2339 #Height 90 2340 #Description 2341 Draw a red circle with an Aliased clip and an Anti-aliased clip. 2342 Use an image filter to zoom into the pixels drawn. 2343 The edge of the Aliased clip fully draws pixels in the red circle. 2344 The edge of the Anti-aliased clip partially draws pixels in the red circle. 2345 ## 2346 SkPaint redPaint, scalePaint; 2347 redPaint.setAntiAlias(true); 2348 redPaint.setColor(SK_ColorRED); 2349 canvas->save(); 2350 for (bool antialias : { false, true } ) { 2351 canvas->save(); 2352 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias); 2353 canvas->drawCircle(17, 11, 8, redPaint); 2354 canvas->restore(); 2355 canvas->translate(16, 0); 2356 } 2357 canvas->restore(); 2358 SkMatrix matrix; 2359 matrix.setScale(6, 6); 2360 scalePaint.setImageFilter( 2361 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr)); 2362 SkCanvas::SaveLayerRec saveLayerRec( 2363 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag); 2364 canvas->saveLayer(saveLayerRec); 2365 canvas->restore(); 2366 ## 2367 2368 #Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias) 2369 2370 #In Clip 2371 #Line # combines Clip with Rect ## 2372 Replace Clip with the intersection or difference of Clip and rect, 2373 with an Aliased or Anti-aliased clip edge. rect is transformed by Matrix 2374 before it is combined with Clip. 2375 2376 #Param rect Rect to combine with Clip ## 2377 #Param op Clip_Op to apply to Clip ## 2378 #Param doAntiAlias true if Clip is to be Anti-aliased ## 2379 2380 #Example 2381 #Height 128 2382 void draw(SkCanvas* canvas) { 2383 canvas->rotate(10); 2384 SkPaint paint; 2385 paint.setAntiAlias(true); 2386 for (auto alias: { false, true } ) { 2387 canvas->save(); 2388 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias); 2389 canvas->drawCircle(100, 60, 60, paint); 2390 canvas->restore(); 2391 canvas->translate(80, 0); 2392 } 2393 } 2394 ## 2395 2396 #SeeAlso clipRRect clipPath clipRegion 2397 2398 ## 2399 2400 #Method void clipRect(const SkRect& rect, SkClipOp op) 2401 2402 #In Clip 2403 Replace Clip with the intersection or difference of Clip and rect. 2404 Resulting Clip is Aliased; pixels are fully contained by the clip. 2405 rect is transformed by Matrix before it is combined with Clip. 2406 2407 #Param rect Rect to combine with Clip ## 2408 #Param op Clip_Op to apply to Clip ## 2409 2410 #Example 2411 #Height 192 2412 #Width 280 2413 void draw(SkCanvas* canvas) { 2414 SkPaint paint; 2415 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) { 2416 canvas->save(); 2417 canvas->clipRect(SkRect::MakeWH(90, 120), op, false); 2418 canvas->drawCircle(100, 100, 60, paint); 2419 canvas->restore(); 2420 canvas->translate(80, 0); 2421 } 2422 } 2423 ## 2424 2425 #SeeAlso clipRRect clipPath clipRegion 2426 2427 ## 2428 2429 #Method void clipRect(const SkRect& rect, bool doAntiAlias = false) 2430 2431 #In Clip 2432 Replace Clip with the intersection of Clip and rect. 2433 Resulting Clip is Aliased; pixels are fully contained by the clip. 2434 rect is transformed by Matrix 2435 before it is combined with Clip. 2436 2437 #Param rect Rect to combine with Clip ## 2438 #Param doAntiAlias true if Clip is to be Anti-aliased ## 2439 2440 #Example 2441 #Height 133 2442 #Description 2443 A circle drawn in pieces looks uniform when drawn Aliased. 2444 The same circle pieces blend with pixels more than once when Anti-aliased, 2445 visible as a thin pair of lines through the right circle. 2446 ## 2447 void draw(SkCanvas* canvas) { 2448 canvas->clear(SK_ColorWHITE); 2449 SkPaint paint; 2450 paint.setAntiAlias(true); 2451 paint.setColor(0x8055aaff); 2452 SkRect clipRect = { 0, 0, 87.4f, 87.4f }; 2453 for (auto alias: { false, true } ) { 2454 canvas->save(); 2455 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias); 2456 canvas->drawCircle(67, 67, 60, paint); 2457 canvas->restore(); 2458 canvas->save(); 2459 canvas->clipRect(clipRect, SkClipOp::kDifference, alias); 2460 canvas->drawCircle(67, 67, 60, paint); 2461 canvas->restore(); 2462 canvas->translate(120, 0); 2463 } 2464 } 2465 ## 2466 2467 #SeeAlso clipRRect clipPath clipRegion 2468 2469 ## 2470 2471 #Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect) 2472 2473 #In Clip 2474 #Line # for use by Android framework ## 2475 Sets the maximum clip rectangle, which can be set by clipRect, clipRRect and 2476 clipPath and intersect the current clip with the specified rect. 2477 The maximum clip affects only future clipping operations; it is not retroactive. 2478 The clip restriction is not recorded in pictures. 2479 2480 Pass an empty rect to disable maximum clip. 2481 2482 #Private 2483 This is private API to be used only by Android framework. 2484 ## 2485 2486 #Param rect maximum allowed clip in device coordinates 2487 #Param ## 2488 2489 ## 2490 2491 #Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias) 2492 2493 #In Clip 2494 #Line # combines Clip with Round_Rect ## 2495 Replace Clip with the intersection or difference of Clip and rrect, 2496 with an Aliased or Anti-aliased clip edge. 2497 rrect is transformed by Matrix 2498 before it is combined with Clip. 2499 2500 #Param rrect Round_Rect to combine with Clip ## 2501 #Param op Clip_Op to apply to Clip ## 2502 #Param doAntiAlias true if Clip is to be Anti-aliased ## 2503 2504 #Example 2505 #Height 128 2506 void draw(SkCanvas* canvas) { 2507 canvas->clear(SK_ColorWHITE); 2508 SkPaint paint; 2509 paint.setAntiAlias(true); 2510 paint.setColor(0x8055aaff); 2511 SkRRect oval; 2512 oval.setOval({10, 20, 90, 100}); 2513 canvas->clipRRect(oval, SkClipOp::kIntersect, true); 2514 canvas->drawCircle(70, 100, 60, paint); 2515 } 2516 ## 2517 2518 #SeeAlso clipRect clipPath clipRegion 2519 2520 ## 2521 2522 #Method void clipRRect(const SkRRect& rrect, SkClipOp op) 2523 2524 #In Clip 2525 Replace Clip with the intersection or difference of Clip and rrect. 2526 Resulting Clip is Aliased; pixels are fully contained by the clip. 2527 rrect is transformed by Matrix before it is combined with Clip. 2528 2529 #Param rrect Round_Rect to combine with Clip ## 2530 #Param op Clip_Op to apply to Clip ## 2531 2532 #Example 2533 #Height 128 2534 void draw(SkCanvas* canvas) { 2535 SkPaint paint; 2536 paint.setColor(0x8055aaff); 2537 auto oval = SkRRect::MakeOval({10, 20, 90, 100}); 2538 canvas->clipRRect(oval, SkClipOp::kIntersect); 2539 canvas->drawCircle(70, 100, 60, paint); 2540 } 2541 ## 2542 2543 #SeeAlso clipRect clipPath clipRegion 2544 2545 ## 2546 2547 #Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) 2548 2549 #In Clip 2550 Replace Clip with the intersection of Clip and rrect, 2551 with an Aliased or Anti-aliased clip edge. 2552 rrect is transformed by Matrix before it is combined with Clip. 2553 2554 #Param rrect Round_Rect to combine with Clip ## 2555 #Param doAntiAlias true if Clip is to be Anti-aliased ## 2556 2557 #Example 2558 #Height 128 2559 void draw(SkCanvas* canvas) { 2560 SkPaint paint; 2561 paint.setAntiAlias(true); 2562 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13); 2563 canvas->clipRRect(oval, true); 2564 canvas->drawCircle(70, 100, 60, paint); 2565 } 2566 ## 2567 2568 #SeeAlso clipRect clipPath clipRegion 2569 2570 ## 2571 2572 #Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias) 2573 2574 #In Clip 2575 #Line # combines Clip with Path ## 2576 Replace Clip with the intersection or difference of Clip and path, 2577 with an Aliased or Anti-aliased clip edge. Path_Fill_Type determines if path 2578 describes the area inside or outside its contours; and if Path_Contour overlaps 2579 itself or another Path_Contour, whether the overlaps form part of the area. 2580 path is transformed by Matrix before it is combined with Clip. 2581 2582 #Param path Path to combine with Clip ## 2583 #Param op Clip_Op to apply to Clip ## 2584 #Param doAntiAlias true if Clip is to be Anti-aliased ## 2585 2586 #Example 2587 #Description 2588 Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference; 2589 area outside clip is subtracted from circle. 2590 2591 Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect; 2592 area inside clip is intersected with circle. 2593 ## 2594 void draw(SkCanvas* canvas) { 2595 SkPaint paint; 2596 paint.setAntiAlias(true); 2597 SkPath path; 2598 path.addRect({20, 30, 100, 110}); 2599 path.setFillType(SkPath::kInverseWinding_FillType); 2600 canvas->save(); 2601 canvas->clipPath(path, SkClipOp::kDifference, false); 2602 canvas->drawCircle(70, 100, 60, paint); 2603 canvas->restore(); 2604 canvas->translate(100, 100); 2605 path.setFillType(SkPath::kWinding_FillType); 2606 canvas->clipPath(path, SkClipOp::kIntersect, false); 2607 canvas->drawCircle(70, 100, 60, paint); 2608 } 2609 ## 2610 2611 #SeeAlso clipRect clipRRect clipRegion 2612 2613 ## 2614 2615 #Method void clipPath(const SkPath& path, SkClipOp op) 2616 2617 #In Clip 2618 Replace Clip with the intersection or difference of Clip and path. 2619 Resulting Clip is Aliased; pixels are fully contained by the clip. 2620 Path_Fill_Type determines if path 2621 describes the area inside or outside its contours; and if Path_Contour overlaps 2622 itself or another Path_Contour, whether the overlaps form part of the area. 2623 path is transformed by Matrix 2624 before it is combined with Clip. 2625 2626 #Param path Path to combine with Clip ## 2627 #Param op Clip_Op to apply to Clip ## 2628 2629 #Example 2630 #Description 2631 Overlapping Rects form a clip. When clip Path_Fill_Type is set to 2632 SkPath::kWinding_FillType, the overlap is included. Set to 2633 SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole. 2634 ## 2635 void draw(SkCanvas* canvas) { 2636 SkPaint paint; 2637 paint.setAntiAlias(true); 2638 SkPath path; 2639 path.addRect({20, 15, 100, 95}); 2640 path.addRect({50, 65, 130, 135}); 2641 path.setFillType(SkPath::kWinding_FillType); 2642 canvas->save(); 2643 canvas->clipPath(path, SkClipOp::kIntersect); 2644 canvas->drawCircle(70, 85, 60, paint); 2645 canvas->restore(); 2646 canvas->translate(100, 100); 2647 path.setFillType(SkPath::kEvenOdd_FillType); 2648 canvas->clipPath(path, SkClipOp::kIntersect); 2649 canvas->drawCircle(70, 85, 60, paint); 2650 } 2651 ## 2652 2653 #SeeAlso clipRect clipRRect clipRegion 2654 2655 ## 2656 2657 #Method void clipPath(const SkPath& path, bool doAntiAlias = false) 2658 2659 #In Clip 2660 Replace Clip with the intersection of Clip and path. 2661 Resulting Clip is Aliased; pixels are fully contained by the clip. 2662 Path_Fill_Type determines if path 2663 describes the area inside or outside its contours; and if Path_Contour overlaps 2664 itself or another Path_Contour, whether the overlaps form part of the area. 2665 path is transformed by Matrix before it is combined with Clip. 2666 2667 #Param path Path to combine with Clip ## 2668 #Param doAntiAlias true if Clip is to be Anti-aliased ## 2669 2670 #Example 2671 #Height 212 2672 #Description 2673 Clip loops over itself covering its center twice. When clip Path_Fill_Type 2674 is set to SkPath::kWinding_FillType, the overlap is included. Set to 2675 SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole. 2676 ## 2677 void draw(SkCanvas* canvas) { 2678 SkPaint paint; 2679 paint.setAntiAlias(true); 2680 SkPath path; 2681 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80}, 2682 {40, 40}, {100, 40}, {100, 100}, {20, 100}}; 2683 path.addPoly(poly, SK_ARRAY_COUNT(poly), true); 2684 path.setFillType(SkPath::kWinding_FillType); 2685 canvas->save(); 2686 canvas->clipPath(path, SkClipOp::kIntersect); 2687 canvas->drawCircle(50, 50, 45, paint); 2688 canvas->restore(); 2689 canvas->translate(100, 100); 2690 path.setFillType(SkPath::kEvenOdd_FillType); 2691 canvas->clipPath(path, SkClipOp::kIntersect); 2692 canvas->drawCircle(50, 50, 45, paint); 2693 } 2694 ## 2695 2696 #SeeAlso clipRect clipRRect clipRegion 2697 2698 ## 2699 2700 # ------------------------------------------------------------------------------ 2701 2702 #Method void setAllowSimplifyClip(bool allow) 2703 2704 #In Clip 2705 #Line # experimental ## 2706 #Experimental 2707 Only used for testing. 2708 ## 2709 2710 Set to simplify clip stack using PathOps. 2711 2712 ## 2713 2714 # ------------------------------------------------------------------------------ 2715 2716 #Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect) 2717 2718 #In Clip 2719 #Line # combines Clip with Region ## 2720 Replace Clip with the intersection or difference of Clip and Region deviceRgn. 2721 Resulting Clip is Aliased; pixels are fully contained by the clip. 2722 deviceRgn is unaffected by Matrix. 2723 2724 #Param deviceRgn Region to combine with Clip ## 2725 #Param op Clip_Op to apply to Clip ## 2726 2727 #Example 2728 #Description 2729 region is unaffected by canvas rotation; iRect is affected by canvas rotation. 2730 Both clips are Aliased; this is not noticeable on Region clip because it 2731 aligns to pixel boundaries. 2732 ## 2733 void draw(SkCanvas* canvas) { 2734 SkPaint paint; 2735 paint.setAntiAlias(true); 2736 SkIRect iRect = {30, 40, 120, 130 }; 2737 SkRegion region(iRect); 2738 canvas->rotate(10); 2739 canvas->save(); 2740 canvas->clipRegion(region, SkClipOp::kIntersect); 2741 canvas->drawCircle(50, 50, 45, paint); 2742 canvas->restore(); 2743 canvas->translate(100, 100); 2744 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect); 2745 canvas->drawCircle(50, 50, 45, paint); 2746 } 2747 ## 2748 2749 #SeeAlso clipRect clipRRect clipPath 2750 2751 ## 2752 2753 #Method bool quickReject(const SkRect& rect) const 2754 2755 #In Clip 2756 #Line # returns if Rect is outside Clip ## 2757 Return true if Rect rect, transformed by Matrix, can be quickly determined to be 2758 outside of Clip. May return false even though rect is outside of Clip. 2759 2760 Use to check if an area to be drawn is clipped out, to skip subsequent draw calls. 2761 2762 #Param rect Rect to compare with Clip ## 2763 2764 #Return true if rect, transformed by Matrix, does not intersect Clip ## 2765 2766 #Example 2767 void draw(SkCanvas* canvas) { 2768 SkRect testRect = {30, 30, 120, 129 }; 2769 SkRect clipRect = {30, 130, 120, 230 }; 2770 canvas->save(); 2771 canvas->clipRect(clipRect); 2772 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false"); 2773 canvas->restore(); 2774 canvas->rotate(10); 2775 canvas->clipRect(clipRect); 2776 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false"); 2777 } 2778 #StdOut 2779 quickReject true 2780 quickReject false 2781 ## 2782 ## 2783 2784 #SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing 2785 2786 ## 2787 2788 #Method bool quickReject(const SkPath& path) const 2789 2790 #In Clip 2791 Return true if path, transformed by Matrix, can be quickly determined to be 2792 outside of Clip. May return false even though path is outside of Clip. 2793 2794 Use to check if an area to be drawn is clipped out, to skip subsequent draw calls. 2795 2796 #Param path Path to compare with Clip ## 2797 2798 #Return true if path, transformed by Matrix, does not intersect Clip ## 2799 2800 #Example 2801 void draw(SkCanvas* canvas) { 2802 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} }; 2803 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; 2804 SkPath testPath, clipPath; 2805 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true); 2806 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); 2807 canvas->save(); 2808 canvas->clipPath(clipPath); 2809 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false"); 2810 canvas->restore(); 2811 canvas->rotate(10); 2812 canvas->clipPath(clipPath); 2813 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false"); 2814 #StdOut 2815 quickReject true 2816 quickReject false 2817 ## 2818 } 2819 ## 2820 2821 #SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing 2822 2823 ## 2824 2825 #Method SkRect getLocalClipBounds() const 2826 2827 #In Clip 2828 #Line # returns Clip bounds in source coordinates ## 2829 Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty, 2830 return SkRect::MakeEmpty, where all Rect sides equal zero. 2831 2832 Rect returned is outset by one to account for partial pixel coverage if Clip 2833 is Anti-aliased. 2834 2835 #Return bounds of Clip in local coordinates ## 2836 2837 #Example 2838 #Description 2839 Initial bounds is device bounds outset by 1 on all sides. 2840 Clipped bounds is clipPath bounds outset by 1 on all sides. 2841 Scaling the canvas by two in x and y scales the local bounds by 1/2 in x and y. 2842 ## 2843 SkCanvas local(256, 256); 2844 canvas = &local; 2845 SkRect bounds = canvas->getLocalClipBounds(); 2846 SkDebugf("left:%g top:%g right:%g bottom:%g\n", 2847 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2848 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; 2849 SkPath clipPath; 2850 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); 2851 canvas->clipPath(clipPath); 2852 bounds = canvas->getLocalClipBounds(); 2853 SkDebugf("left:%g top:%g right:%g bottom:%g\n", 2854 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2855 canvas->scale(2, 2); 2856 bounds = canvas->getLocalClipBounds(); 2857 SkDebugf("left:%g top:%g right:%g bottom:%g\n", 2858 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2859 #StdOut 2860 left:-1 top:-1 right:257 bottom:257 2861 left:29 top:129 right:121 bottom:231 2862 left:14.5 top:64.5 right:60.5 bottom:115.5 2863 ## 2864 ## 2865 2866 # local canvas in example works around bug in fiddle ## 2867 #Bug 6524 ## 2868 #SeeAlso getDeviceClipBounds getBaseLayerSize quickReject 2869 2870 ## 2871 2872 #Method bool getLocalClipBounds(SkRect* bounds) const 2873 2874 #In Clip 2875 Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty, 2876 return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero. 2877 2878 bounds is outset by one to account for partial pixel coverage if Clip 2879 is Anti-aliased. 2880 2881 #Param bounds Rect of Clip in local coordinates ## 2882 2883 #Return true if Clip bounds is not empty ## 2884 2885 #Example 2886 void draw(SkCanvas* canvas) { 2887 SkCanvas local(256, 256); 2888 canvas = &local; 2889 SkRect bounds; 2890 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds) 2891 ? "false" : "true"); 2892 SkPath path; 2893 canvas->clipPath(path); 2894 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds) 2895 ? "false" : "true"); 2896 } 2897 #StdOut 2898 local bounds empty = false 2899 local bounds empty = true 2900 ## 2901 ## 2902 2903 # local canvas in example works around bug in fiddle ## 2904 #Bug 6524 ## 2905 #SeeAlso getDeviceClipBounds getBaseLayerSize quickReject 2906 2907 ## 2908 2909 #Method SkIRect getDeviceClipBounds() const 2910 2911 #In Clip 2912 #Line # returns IRect bounds of Clip ## 2913 Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty, 2914 return SkRect::MakeEmpty, where all Rect sides equal zero. 2915 2916 Unlike getLocalClipBounds, returned IRect is not outset. 2917 2918 #Return bounds of Clip in Device coordinates ## 2919 2920 #Example 2921 void draw(SkCanvas* canvas) { 2922 #Description 2923 Initial bounds is device bounds, not outset. 2924 Clipped bounds is clipPath bounds, not outset. 2925 Scaling the canvas by 1/2 in x and y scales the device bounds by 1/2 in x and y. 2926 ## 2927 SkCanvas device(256, 256); 2928 canvas = &device; 2929 SkIRect bounds = canvas->getDeviceClipBounds(); 2930 SkDebugf("left:%d top:%d right:%d bottom:%d\n", 2931 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2932 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; 2933 SkPath clipPath; 2934 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); 2935 canvas->save(); 2936 canvas->clipPath(clipPath); 2937 bounds = canvas->getDeviceClipBounds(); 2938 SkDebugf("left:%d top:%d right:%d bottom:%d\n", 2939 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2940 canvas->restore(); 2941 canvas->scale(1.f/2, 1.f/2); 2942 canvas->clipPath(clipPath); 2943 bounds = canvas->getDeviceClipBounds(); 2944 SkDebugf("left:%d top:%d right:%d bottom:%d\n", 2945 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2946 #StdOut 2947 left:0 top:0 right:256 bottom:256 2948 left:30 top:130 right:120 bottom:230 2949 left:15 top:65 right:60 bottom:115 2950 ## 2951 } 2952 ## 2953 2954 #ToDo some confusion on why with an identity Matrix local and device are different ## 2955 #SeeAlso getLocalClipBounds getBaseLayerSize quickReject 2956 2957 # device canvas in example works around bug in fiddle ## 2958 #Bug 6524 ## 2959 2960 ## 2961 2962 #Method bool getDeviceClipBounds(SkIRect* bounds) const 2963 2964 #In Clip 2965 Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty, 2966 return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero. 2967 2968 Unlike getLocalClipBounds, bounds is not outset. 2969 2970 #Param bounds Rect of Clip in device coordinates ## 2971 2972 #Return true if Clip bounds is not empty ## 2973 2974 #Example 2975 void draw(SkCanvas* canvas) { 2976 SkIRect bounds; 2977 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds) 2978 ? "false" : "true"); 2979 SkPath path; 2980 canvas->clipPath(path); 2981 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds) 2982 ? "false" : "true"); 2983 } 2984 #StdOut 2985 device bounds empty = false 2986 device bounds empty = true 2987 ## 2988 ## 2989 2990 #SeeAlso getLocalClipBounds getBaseLayerSize quickReject 2991 2992 ## 2993 2994 #Subtopic Clip ## 2995 2996 # ------------------------------------------------------------------------------ 2997 2998 #Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) 2999 3000 #Line # fills Clip with Color and Blend_Mode ## 3001 Fill Clip with Color color. 3002 mode determines how Color_ARGB is combined with destination. 3003 3004 #Param color Unpremultiplied Color_ARGB ## 3005 #Param mode SkBlendMode used to combine source color and destination ## 3006 3007 #Example 3008 canvas->drawColor(SK_ColorRED); 3009 canvas->clipRect(SkRect::MakeWH(150, 150)); 3010 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus); 3011 canvas->clipRect(SkRect::MakeWH(75, 75)); 3012 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus); 3013 ## 3014 3015 #SeeAlso clear SkBitmap::erase drawPaint 3016 3017 ## 3018 3019 # ------------------------------------------------------------------------------ 3020 3021 #Method void clear(SkColor color) 3022 3023 #Line # fills Clip with Color ## 3024 Fill Clip with Color color using SkBlendMode::kSrc. 3025 This has the effect of replacing all pixels contained by Clip with color. 3026 3027 #Param color Unpremultiplied Color_ARGB ## 3028 3029 #Example 3030 void draw(SkCanvas* canvas) { 3031 canvas->save(); 3032 canvas->clipRect(SkRect::MakeWH(256, 128)); 3033 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00)); 3034 canvas->restore(); 3035 canvas->save(); 3036 canvas->clipRect(SkRect::MakeWH(150, 192)); 3037 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00)); 3038 canvas->restore(); 3039 canvas->clipRect(SkRect::MakeWH(75, 256)); 3040 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF)); 3041 } 3042 ## 3043 3044 #SeeAlso drawColor SkBitmap::erase drawPaint 3045 3046 ## 3047 3048 # ------------------------------------------------------------------------------ 3049 3050 #Method void discard() 3051 3052 #Line # makes Canvas contents undefined ## 3053 Make Canvas contents undefined. Subsequent calls that read Canvas pixels, 3054 such as drawing with SkBlendMode, return undefined results. discard() does 3055 not change Clip or Matrix. 3056 3057 discard() may do nothing, depending on the implementation of Surface or Device 3058 that created Canvas. 3059 3060 discard() allows optimized performance on subsequent draws by removing 3061 cached data associated with Surface or Device. 3062 It is not necessary to call discard() once done with Canvas; 3063 any cached data is deleted when owning Surface or Device is deleted. 3064 3065 #ToDo example? not sure how to make this meaningful w/o more implementation detail ## 3066 #SeeAlso flush() SkSurface::prepareForExternalIO GrContext::abandonContext 3067 3068 #NoExample 3069 ## 3070 3071 ## 3072 3073 # ------------------------------------------------------------------------------ 3074 3075 #Method void drawPaint(const SkPaint& paint) 3076 3077 #Line # fills Clip with Paint ## 3078 Fill Clip with Paint paint. Paint components Mask_Filter, Shader, 3079 Color_Filter, Image_Filter, and Blend_Mode affect drawing; 3080 Path_Effect in paint is ignored. 3081 3082 # can Path_Effect in paint ever alter drawPaint? 3083 3084 #Param paint graphics state used to fill Canvas ## 3085 3086 #Example 3087 void draw(SkCanvas* canvas) { 3088 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; 3089 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 }; 3090 SkPaint paint; 3091 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors))); 3092 canvas->drawPaint(paint); 3093 } 3094 ## 3095 3096 #SeeAlso clear drawColor SkBitmap::erase 3097 3098 ## 3099 3100 # ------------------------------------------------------------------------------ 3101 3102 #Enum PointMode 3103 #Line # sets drawPoints options ## 3104 3105 #Code 3106 enum PointMode { 3107 kPoints_PointMode, 3108 kLines_PointMode, 3109 kPolygon_PointMode, 3110 }; 3111 ## 3112 3113 Selects if an array of points are drawn as discrete points, as lines, or as 3114 an open polygon. 3115 3116 #Const kPoints_PointMode 0 3117 Draw each point separately. 3118 ## 3119 3120 #Const kLines_PointMode 1 3121 Draw each pair of points as a line segment. 3122 ## 3123 3124 #Const kPolygon_PointMode 2 3125 Draw the array of points as a open polygon. 3126 ## 3127 3128 #Example 3129 #Description 3130 The upper left corner shows three squares when drawn as points. 3131 The upper right corner shows one line; when drawn as lines, two points are required per line. 3132 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner. 3133 The lower left corner shows two lines with a miter when path contains polygon. 3134 ## 3135 void draw(SkCanvas* canvas) { 3136 SkPaint paint; 3137 paint.setStyle(SkPaint::kStroke_Style); 3138 paint.setStrokeWidth(10); 3139 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}}; 3140 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint); 3141 canvas->translate(128, 0); 3142 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint); 3143 canvas->translate(0, 128); 3144 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint); 3145 SkPath path; 3146 path.addPoly(points, 3, false); 3147 canvas->translate(-128, 0); 3148 canvas->drawPath(path, paint); 3149 } 3150 ## 3151 3152 #SeeAlso drawLine drawPoint drawPath 3153 3154 ## 3155 3156 # ------------------------------------------------------------------------------ 3157 3158 #Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) 3159 3160 #Line # draws array as points, lines, polygon ## 3161 Draw pts using Clip, Matrix and Paint paint. 3162 count is the number of points; if count is less than one, has no effect. 3163 mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode. 3164 3165 If mode is kPoints_PointMode, the shape of point drawn depends on paint 3166 Paint_Stroke_Cap. If paint is set to SkPaint::kRound_Cap, each point draws a 3167 circle of diameter Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap 3168 or SkPaint::kButt_Cap, each point draws a square of width and height 3169 Paint_Stroke_Width. 3170 3171 If mode is kLines_PointMode, each pair of points draws a line segment. 3172 One line is drawn for every two points; each point is used once. If count is odd, 3173 the final point is ignored. 3174 3175 If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment. 3176 count minus one lines are drawn; the first and last point are used once. 3177 3178 Each line segment respects paint Paint_Stroke_Cap and Paint_Stroke_Width. 3179 Paint_Style is ignored, as if were set to SkPaint::kStroke_Style. 3180 3181 Always draws each element one at a time; is not affected by 3182 Paint_Stroke_Join, and unlike drawPath, does not create a mask from all points 3183 and lines before drawing. 3184 3185 #Param mode whether pts draws points or lines ## 3186 #Param count number of points in the array ## 3187 #Param pts array of points to draw ## 3188 #Param paint stroke, blend, color, and so on, used to draw ## 3189 3190 #Example 3191 #Height 200 3192 #Description 3193 #List 3194 # The first column draws points. ## 3195 # The second column draws points as lines. ## 3196 # The third column draws points as a polygon. ## 3197 # The fourth column draws points as a polygonal path. ## 3198 # The first row uses a round cap and round join. ## 3199 # The second row uses a square cap and a miter join. ## 3200 # The third row uses a butt cap and a bevel join. ## 3201 ## 3202 The transparent color makes multiple line draws visible; 3203 the path is drawn all at once. 3204 ## 3205 void draw(SkCanvas* canvas) { 3206 SkPaint paint; 3207 paint.setAntiAlias(true); 3208 paint.setStyle(SkPaint::kStroke_Style); 3209 paint.setStrokeWidth(10); 3210 paint.setColor(0x80349a45); 3211 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}}; 3212 const SkPaint::Join join[] = { SkPaint::kRound_Join, 3213 SkPaint::kMiter_Join, 3214 SkPaint::kBevel_Join }; 3215 int joinIndex = 0; 3216 SkPath path; 3217 path.addPoly(points, 3, false); 3218 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) { 3219 paint.setStrokeCap(cap); 3220 paint.setStrokeJoin(join[joinIndex++]); 3221 for (const auto mode : { SkCanvas::kPoints_PointMode, 3222 SkCanvas::kLines_PointMode, 3223 SkCanvas::kPolygon_PointMode } ) { 3224 canvas->drawPoints(mode, 3, points, paint); 3225 canvas->translate(64, 0); 3226 } 3227 canvas->drawPath(path, paint); 3228 canvas->translate(-192, 64); 3229 } 3230 } 3231 ## 3232 3233 #SeeAlso drawLine drawPoint drawPath 3234 3235 ## 3236 3237 # ------------------------------------------------------------------------------ 3238 3239 #Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) 3240 3241 #Line # draws point at (x, y) position ## 3242 Draw point at (x, y) using Clip, Matrix and Paint paint. 3243 3244 The shape of point drawn depends on paint Paint_Stroke_Cap. 3245 If paint is set to SkPaint::kRound_Cap, draw a circle of diameter 3246 Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap, 3247 draw a square of width and height Paint_Stroke_Width. 3248 Paint_Style is ignored, as if were set to SkPaint::kStroke_Style. 3249 3250 #Param x left edge of circle or square ## 3251 #Param y top edge of circle or square ## 3252 #Param paint stroke, blend, color, and so on, used to draw ## 3253 3254 #Example 3255 void draw(SkCanvas* canvas) { 3256 SkPaint paint; 3257 paint.setAntiAlias(true); 3258 paint.setColor(0x80349a45); 3259 paint.setStyle(SkPaint::kStroke_Style); 3260 paint.setStrokeWidth(100); 3261 paint.setStrokeCap(SkPaint::kRound_Cap); 3262 canvas->scale(1, 1.2f); 3263 canvas->drawPoint(64, 96, paint); 3264 canvas->scale(.6f, .8f); 3265 paint.setColor(SK_ColorWHITE); 3266 canvas->drawPoint(106, 120, paint); 3267 } 3268 ## 3269 3270 #SeeAlso drawPoints drawCircle drawRect drawLine drawPath 3271 3272 ## 3273 3274 #Method void drawPoint(SkPoint p, const SkPaint& paint) 3275 3276 Draw point p using Clip, Matrix and Paint paint. 3277 3278 The shape of point drawn depends on paint Paint_Stroke_Cap. 3279 If paint is set to SkPaint::kRound_Cap, draw a circle of diameter 3280 Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap, 3281 draw a square of width and height Paint_Stroke_Width. 3282 Paint_Style is ignored, as if were set to SkPaint::kStroke_Style. 3283 3284 #Param p top-left edge of circle or square ## 3285 #Param paint stroke, blend, color, and so on, used to draw ## 3286 3287 #Example 3288 void draw(SkCanvas* canvas) { 3289 SkPaint paint; 3290 paint.setAntiAlias(true); 3291 paint.setColor(0x80349a45); 3292 paint.setStyle(SkPaint::kStroke_Style); 3293 paint.setStrokeWidth(100); 3294 paint.setStrokeCap(SkPaint::kSquare_Cap); 3295 canvas->scale(1, 1.2f); 3296 canvas->drawPoint({64, 96}, paint); 3297 canvas->scale(.6f, .8f); 3298 paint.setColor(SK_ColorWHITE); 3299 canvas->drawPoint(106, 120, paint); 3300 } 3301 ## 3302 3303 #SeeAlso drawPoints drawCircle drawRect drawLine drawPath 3304 3305 ## 3306 3307 # ------------------------------------------------------------------------------ 3308 3309 #Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) 3310 3311 #Line # draws line segment between two points ## 3312 Draws line segment from (x0, y0) to (x1, y1) using Clip, Matrix, and Paint paint. 3313 In paint: Paint_Stroke_Width describes the line thickness; 3314 Paint_Stroke_Cap draws the end rounded or square; 3315 Paint_Style is ignored, as if were set to SkPaint::kStroke_Style. 3316 3317 #Param x0 start of line segment on x-axis ## 3318 #Param y0 start of line segment on y-axis ## 3319 #Param x1 end of line segment on x-axis ## 3320 #Param y1 end of line segment on y-axis ## 3321 #Param paint stroke, blend, color, and so on, used to draw ## 3322 3323 #Example 3324 SkPaint paint; 3325 paint.setAntiAlias(true); 3326 paint.setColor(0xFF9a67be); 3327 paint.setStrokeWidth(20); 3328 canvas->skew(1, 0); 3329 canvas->drawLine(32, 96, 32, 160, paint); 3330 canvas->skew(-2, 0); 3331 canvas->drawLine(288, 96, 288, 160, paint); 3332 ## 3333 3334 #SeeAlso drawPoint drawCircle drawRect drawPath 3335 3336 ## 3337 3338 #Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) 3339 3340 Draws line segment from p0 to p1 using Clip, Matrix, and Paint paint. 3341 In paint: Paint_Stroke_Width describes the line thickness; 3342 Paint_Stroke_Cap draws the end rounded or square; 3343 Paint_Style is ignored, as if were set to SkPaint::kStroke_Style. 3344 3345 #Param p0 start of line segment ## 3346 #Param p1 end of line segment ## 3347 #Param paint stroke, blend, color, and so on, used to draw ## 3348 3349 #Example 3350 SkPaint paint; 3351 paint.setAntiAlias(true); 3352 paint.setColor(0xFF9a67be); 3353 paint.setStrokeWidth(20); 3354 canvas->skew(1, 0); 3355 canvas->drawLine({32, 96}, {32, 160}, paint); 3356 canvas->skew(-2, 0); 3357 canvas->drawLine({288, 96}, {288, 160}, paint); 3358 ## 3359 3360 #SeeAlso drawPoint drawCircle drawRect drawPath 3361 3362 ## 3363 3364 # ------------------------------------------------------------------------------ 3365 3366 #Method void drawRect(const SkRect& rect, const SkPaint& paint) 3367 3368 #Line # draws Rect using Clip, Matrix, and Paint ## 3369 Draw Rect rect using Clip, Matrix, and Paint paint. 3370 In paint: Paint_Style determines if rectangle is stroked or filled; 3371 if stroked, Paint_Stroke_Width describes the line thickness, and 3372 Paint_Stroke_Join draws the corners rounded or square. 3373 3374 #Param rect rectangle to draw ## 3375 #Param paint stroke or fill, blend, color, and so on, used to draw ## 3376 3377 #Example 3378 void draw(SkCanvas* canvas) { 3379 SkPoint rectPts[] = { {64, 48}, {192, 160} }; 3380 SkPaint paint; 3381 paint.setAntiAlias(true); 3382 paint.setStyle(SkPaint::kStroke_Style); 3383 paint.setStrokeWidth(20); 3384 paint.setStrokeJoin(SkPaint::kRound_Join); 3385 SkMatrix rotator; 3386 rotator.setRotate(30, 128, 128); 3387 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) { 3388 paint.setColor(color); 3389 SkRect rect; 3390 rect.set(rectPts[0], rectPts[1]); 3391 canvas->drawRect(rect, paint); 3392 rotator.mapPoints(rectPts, 2); 3393 } 3394 } 3395 ## 3396 3397 #SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine 3398 3399 ## 3400 3401 # ------------------------------------------------------------------------------ 3402 3403 #Method void drawIRect(const SkIRect& rect, const SkPaint& paint) 3404 3405 #Line # draws IRect using Clip, Matrix, and Paint ## 3406 Draw IRect rect using Clip, Matrix, and Paint paint. 3407 In paint: Paint_Style determines if rectangle is stroked or filled; 3408 if stroked, Paint_Stroke_Width describes the line thickness, and 3409 Paint_Stroke_Join draws the corners rounded or square. 3410 3411 #Param rect rectangle to draw ## 3412 #Param paint stroke or fill, blend, color, and so on, used to draw ## 3413 3414 #Example 3415 SkIRect rect = { 64, 48, 192, 160 }; 3416 SkPaint paint; 3417 paint.setAntiAlias(true); 3418 paint.setStyle(SkPaint::kStroke_Style); 3419 paint.setStrokeWidth(20); 3420 paint.setStrokeJoin(SkPaint::kRound_Join); 3421 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) { 3422 paint.setColor(color); 3423 canvas->drawIRect(rect, paint); 3424 canvas->rotate(30, 128, 128); 3425 } 3426 ## 3427 3428 #SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine 3429 3430 ## 3431 3432 # ------------------------------------------------------------------------------ 3433 3434 #Method void drawRegion(const SkRegion& region, const SkPaint& paint) 3435 3436 #Line # draws Region using Clip, Matrix, and Paint ## 3437 Draw Region region using Clip, Matrix, and Paint paint. 3438 In paint: Paint_Style determines if rectangle is stroked or filled; 3439 if stroked, Paint_Stroke_Width describes the line thickness, and 3440 Paint_Stroke_Join draws the corners rounded or square. 3441 3442 #Param region region to draw ## 3443 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3444 3445 #Example 3446 void draw(SkCanvas* canvas) { 3447 SkRegion region; 3448 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op); 3449 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op); 3450 SkPaint paint; 3451 paint.setAntiAlias(true); 3452 paint.setStyle(SkPaint::kStroke_Style); 3453 paint.setStrokeWidth(20); 3454 paint.setStrokeJoin(SkPaint::kRound_Join); 3455 canvas->drawRegion(region, paint); 3456 } 3457 ## 3458 3459 #SeeAlso drawRect drawIRect drawPath 3460 3461 ## 3462 3463 # ------------------------------------------------------------------------------ 3464 3465 #Method void drawOval(const SkRect& oval, const SkPaint& paint) 3466 3467 #Line # draws Oval using Clip, Matrix, and Paint ## 3468 Draw Oval oval using Clip, Matrix, and Paint. 3469 In paint: Paint_Style determines if Oval is stroked or filled; 3470 if stroked, Paint_Stroke_Width describes the line thickness. 3471 3472 #Param oval Rect bounds of Oval ## 3473 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3474 3475 #Example 3476 void draw(SkCanvas* canvas) { 3477 canvas->clear(0xFF3f5f9f); 3478 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0); 3479 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) }; 3480 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } }; 3481 SkScalar pos[] = { 0.2f, 1.0f }; 3482 SkRect bounds = SkRect::MakeWH(80, 70); 3483 SkPaint paint; 3484 paint.setAntiAlias(true); 3485 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors), 3486 SkShader::kClamp_TileMode)); 3487 canvas->drawOval(bounds , paint); 3488 } 3489 ## 3490 3491 #SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect 3492 3493 ## 3494 3495 # ------------------------------------------------------------------------------ 3496 3497 #Method void drawRRect(const SkRRect& rrect, const SkPaint& paint) 3498 3499 #Line # draws Round_Rect using Clip, Matrix, and Paint ## 3500 Draw Round_Rect rrect using Clip, Matrix, and Paint paint. 3501 In paint: Paint_Style determines if rrect is stroked or filled; 3502 if stroked, Paint_Stroke_Width describes the line thickness. 3503 3504 rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or 3505 may have any combination of positive non-square radii for the four corners. 3506 3507 #Param rrect Round_Rect with up to eight corner radii to draw ## 3508 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3509 3510 #Example 3511 void draw(SkCanvas* canvas) { 3512 SkPaint paint; 3513 paint.setAntiAlias(true); 3514 SkRect outer = {30, 40, 210, 220}; 3515 SkRect radii = {30, 50, 70, 90 }; 3516 SkRRect rRect; 3517 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom); 3518 canvas->drawRRect(rRect, paint); 3519 paint.setColor(SK_ColorWHITE); 3520 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop, 3521 outer.fLeft + radii.fLeft, outer.fBottom, paint); 3522 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop, 3523 outer.fRight - radii.fRight, outer.fBottom, paint); 3524 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop, 3525 outer.fRight, outer.fTop + radii.fTop, paint); 3526 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom, 3527 outer.fRight, outer.fBottom - radii.fBottom, paint); 3528 } 3529 ## 3530 3531 #SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath 3532 3533 ## 3534 3535 # ------------------------------------------------------------------------------ 3536 3537 #Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) 3538 3539 #Line # draws double Round_Rect stroked or filled ## 3540 Draw Round_Rect outer and inner 3541 using Clip, Matrix, and Paint paint. 3542 outer must contain inner or the drawing is undefined. 3543 In paint: Paint_Style determines if Round_Rect is stroked or filled; 3544 if stroked, Paint_Stroke_Width describes the line thickness. 3545 If stroked and Round_Rect corner has zero length radii, Paint_Stroke_Join can 3546 draw corners rounded or square. 3547 3548 GPU-backed platforms optimize drawing when both outer and inner are 3549 concave and outer contains inner. These platforms may not be able to draw 3550 Path built with identical data as fast. 3551 3552 #Param outer Round_Rect outer bounds to draw ## 3553 #Param inner Round_Rect inner bounds to draw ## 3554 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3555 3556 #Example 3557 void draw(SkCanvas* canvas) { 3558 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200}); 3559 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160}); 3560 SkPaint paint; 3561 canvas->drawDRRect(outer, inner, paint); 3562 } 3563 ## 3564 3565 #Example 3566 #Description 3567 Outer Rect has no corner radii, but stroke join is rounded. 3568 Inner Round_Rect has corner radii; outset stroke increases radii of corners. 3569 Stroke join does not affect inner Round_Rect since it has no sharp corners. 3570 ## 3571 void draw(SkCanvas* canvas) { 3572 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200}); 3573 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10); 3574 SkPaint paint; 3575 paint.setAntiAlias(true); 3576 paint.setStyle(SkPaint::kStroke_Style); 3577 paint.setStrokeWidth(20); 3578 paint.setStrokeJoin(SkPaint::kRound_Join); 3579 canvas->drawDRRect(outer, inner, paint); 3580 paint.setStrokeWidth(1); 3581 paint.setColor(SK_ColorWHITE); 3582 canvas->drawDRRect(outer, inner, paint); 3583 } 3584 ## 3585 3586 #SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath 3587 3588 ## 3589 3590 # ------------------------------------------------------------------------------ 3591 3592 #Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) 3593 3594 #Line # draws Circle using Clip, Matrix, and Paint ## 3595 Draw Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint. 3596 If radius is zero or less, nothing is drawn. 3597 In paint: Paint_Style determines if Circle is stroked or filled; 3598 if stroked, Paint_Stroke_Width describes the line thickness. 3599 3600 #Param cx Circle center on the x-axis ## 3601 #Param cy Circle center on the y-axis ## 3602 #Param radius half the diameter of Circle ## 3603 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3604 3605 #Example 3606 void draw(SkCanvas* canvas) { 3607 SkPaint paint; 3608 paint.setAntiAlias(true); 3609 canvas->drawCircle(128, 128, 90, paint); 3610 paint.setColor(SK_ColorWHITE); 3611 canvas->drawCircle(86, 86, 20, paint); 3612 canvas->drawCircle(160, 76, 20, paint); 3613 canvas->drawCircle(140, 150, 35, paint); 3614 } 3615 ## 3616 3617 #SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine 3618 3619 ## 3620 3621 #Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) 3622 3623 Draw Circle at center with radius using Clip, Matrix, and Paint paint. 3624 If radius is zero or less, nothing is drawn. 3625 In paint: Paint_Style determines if Circle is stroked or filled; 3626 if stroked, Paint_Stroke_Width describes the line thickness. 3627 3628 #Param center Circle center ## 3629 #Param radius half the diameter of Circle ## 3630 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3631 3632 #Example 3633 void draw(SkCanvas* canvas) { 3634 SkPaint paint; 3635 paint.setAntiAlias(true); 3636 canvas->drawCircle(128, 128, 90, paint); 3637 paint.setColor(SK_ColorWHITE); 3638 canvas->drawCircle({86, 86}, 20, paint); 3639 canvas->drawCircle({160, 76}, 20, paint); 3640 canvas->drawCircle({140, 150}, 35, paint); 3641 } 3642 ## 3643 3644 #SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine 3645 3646 ## 3647 3648 # ------------------------------------------------------------------------------ 3649 3650 #Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 3651 bool useCenter, const SkPaint& paint) 3652 #Line # draws Arc using Clip, Matrix, and Paint ## 3653 3654 Draw Arc using Clip, Matrix, and Paint paint. 3655 3656 Arc is part of Oval bounded by oval, sweeping from startAngle to startAngle plus 3657 sweepAngle. startAngle and sweepAngle are in degrees. 3658 3659 startAngle of zero places start point at the right middle edge of oval. 3660 A positive sweepAngle places Arc end point clockwise from start point; 3661 a negative sweepAngle places Arc end point counterclockwise from start point. 3662 sweepAngle may exceed 360 degrees, a full circle. 3663 If useCenter is true, draw a wedge that includes lines from oval 3664 center to Arc end points. If useCenter is false, draw Arc between end points. 3665 3666 If Rect oval is empty or sweepAngle is zero, nothing is drawn. 3667 3668 #Param oval Rect bounds of Oval containing Arc to draw ## 3669 #Param startAngle angle in degrees where Arc begins ## 3670 #Param sweepAngle sweep angle in degrees; positive is clockwise ## 3671 #Param useCenter if true, include the center of the oval ## 3672 #Param paint Paint stroke or fill, blend, color, and so on, used to draw ## 3673 3674 #Example 3675 void draw(SkCanvas* canvas) { 3676 SkPaint paint; 3677 paint.setAntiAlias(true); 3678 SkRect oval = { 4, 4, 60, 60}; 3679 for (auto useCenter : { false, true } ) { 3680 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) { 3681 paint.setStyle(style); 3682 for (auto degrees : { 45, 90, 180, 360} ) { 3683 canvas->drawArc(oval, 0, degrees , useCenter, paint); 3684 canvas->translate(64, 0); 3685 } 3686 canvas->translate(-256, 64); 3687 } 3688 } 3689 } 3690 ## 3691 3692 #Example 3693 #Height 64 3694 void draw(SkCanvas* canvas) { 3695 SkPaint paint; 3696 paint.setAntiAlias(true); 3697 paint.setStyle(SkPaint::kStroke_Style); 3698 paint.setStrokeWidth(4); 3699 SkRect oval = { 4, 4, 60, 60}; 3700 float intervals[] = { 5, 5 }; 3701 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f)); 3702 for (auto degrees : { 270, 360, 540, 720 } ) { 3703 canvas->drawArc(oval, 0, degrees, false, paint); 3704 canvas->translate(64, 0); 3705 } 3706 } 3707 ## 3708 3709 #SeeAlso SkPath::arcTo drawCircle drawOval drawPath 3710 3711 ## 3712 3713 # ------------------------------------------------------------------------------ 3714 3715 #Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint) 3716 3717 #Line # draws Round_Rect using Clip, Matrix, and Paint ## 3718 Draw Round_Rect bounded by Rect rect, with corner radii (rx, ry) using Clip, 3719 Matrix, and Paint paint. 3720 3721 In paint: Paint_Style determines if Round_Rect is stroked or filled; 3722 if stroked, Paint_Stroke_Width describes the line thickness. 3723 If rx or ry are less than zero, they are treated as if they are zero. 3724 If rx plus ry exceeds rect width or rect height, radii are scaled down to fit. 3725 If rx and ry are zero, Round_Rect is drawn as Rect and if stroked is affected by 3726 Paint_Stroke_Join. 3727 3728 #Param rect Rect bounds of Round_Rect to draw ## 3729 #Param rx axis length in x of oval describing rounded corners ## 3730 #Param ry axis length in y of oval describing rounded corners ## 3731 #Param paint stroke, blend, color, and so on, used to draw ## 3732 3733 #Example 3734 #Description 3735 Top row has a zero radius a generates a rectangle. 3736 Second row radii sum to less than sides. 3737 Third row radii sum equals sides. 3738 Fourth row radii sum exceeds sides; radii are scaled to fit. 3739 ## 3740 void draw(SkCanvas* canvas) { 3741 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} }; 3742 SkPaint paint; 3743 paint.setStrokeWidth(15); 3744 paint.setStrokeJoin(SkPaint::kRound_Join); 3745 paint.setAntiAlias(true); 3746 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) { 3747 paint.setStyle(style ); 3748 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) { 3749 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint); 3750 canvas->translate(0, 60); 3751 } 3752 canvas->translate(80, -240); 3753 } 3754 } 3755 ## 3756 3757 #SeeAlso DrawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint 3758 3759 ## 3760 3761 # ------------------------------------------------------------------------------ 3762 3763 #Method void drawPath(const SkPath& path, const SkPaint& paint) 3764 3765 #Line # draws Path using Clip, Matrix, and Paint ## 3766 Draw Path path using Clip, Matrix, and Paint paint. 3767 Path contains an array of Path_Contour, each of which may be open or closed. 3768 3769 In paint: Paint_Style determines if Round_Rect is stroked or filled: 3770 if filled, Path_Fill_Type determines whether Path_Contour describes inside or 3771 outside of fill; if stroked, Paint_Stroke_Width describes the line thickness, 3772 Paint_Stroke_Cap describes line ends, and Paint_Stroke_Join describes how 3773 corners are drawn. 3774 3775 #Param path Path to draw ## 3776 #Param paint stroke, blend, color, and so on, used to draw ## 3777 3778 #Example 3779 #Description 3780 Top rows draw stroked path with combinations of joins and caps. The open contour 3781 is affected by caps; the closed contour is affected by joins. 3782 Bottom row draws fill the same for open and closed contour. 3783 First bottom column shows winding fills overlap. 3784 Second bottom column shows even odd fills exclude overlap. 3785 Third bottom column shows inverse winding fills area outside both contours. 3786 ## 3787 void draw(SkCanvas* canvas) { 3788 SkPath path; 3789 path.moveTo(20, 20); 3790 path.quadTo(60, 20, 60, 60); 3791 path.close(); 3792 path.moveTo(60, 20); 3793 path.quadTo(60, 60, 20, 60); 3794 SkPaint paint; 3795 paint.setStrokeWidth(10); 3796 paint.setAntiAlias(true); 3797 paint.setStyle(SkPaint::kStroke_Style); 3798 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) { 3799 paint.setStrokeJoin(join); 3800 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) { 3801 paint.setStrokeCap(cap); 3802 canvas->drawPath(path, paint); 3803 canvas->translate(80, 0); 3804 } 3805 canvas->translate(-240, 60); 3806 } 3807 paint.setStyle(SkPaint::kFill_Style); 3808 for (auto fill : { SkPath::kWinding_FillType, 3809 SkPath::kEvenOdd_FillType, 3810 SkPath::kInverseWinding_FillType } ) { 3811 path.setFillType(fill); 3812 canvas->save(); 3813 canvas->clipRect({0, 10, 80, 70}); 3814 canvas->drawPath(path, paint); 3815 canvas->restore(); 3816 canvas->translate(80, 0); 3817 } 3818 } 3819 ## 3820 3821 #SeeAlso SkPath drawLine drawArc drawRect drawPoints 3822 3823 ## 3824 3825 # ------------------------------------------------------------------------------ 3826 #Subtopic Draw_Image 3827 #Line # draws Image to Canvas ## 3828 3829 drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or 3830 a smart pointer as a convenience. The pairs of calls are otherwise identical. 3831 3832 #Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr) 3833 3834 #In Draw_Image 3835 #Line # draws Image at (x, y) position ## 3836 Draw Image image, with its top-left corner at (left, top), 3837 using Clip, Matrix, and optional Paint paint. 3838 3839 If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, 3840 and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 3841 If paint contains Mask_Filter, generate mask from image bounds. If generated 3842 mask extends beyond image bounds, replicate image edge colors, just as Shader 3843 made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the 3844 image edge color when it samples outside of its bounds. 3845 3846 #Param image uncompressed rectangular map of pixels ## 3847 #Param left left side of image ## 3848 #Param top top side of image ## 3849 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3850 and so on; or nullptr 3851 ## 3852 3853 #Example 3854 #Height 64 3855 #Image 4 3856 void draw(SkCanvas* canvas) { 3857 // sk_sp<SkImage> image; 3858 SkImage* imagePtr = image.get(); 3859 canvas->drawImage(imagePtr, 0, 0); 3860 SkPaint paint; 3861 canvas->drawImage(imagePtr, 80, 0, &paint); 3862 paint.setAlpha(0x80); 3863 canvas->drawImage(imagePtr, 160, 0, &paint); 3864 } 3865 ## 3866 3867 #SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter 3868 3869 ## 3870 3871 # ------------------------------------------------------------------------------ 3872 3873 #Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top, 3874 const SkPaint* paint = nullptr) 3875 #In Draw_Image 3876 3877 Draw Image image, with its top-left corner at (left, top), 3878 using Clip, Matrix, and optional Paint paint. 3879 3880 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 3881 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 3882 If paint contains Mask_Filter, generate mask from image bounds. If generated 3883 mask extends beyond image bounds, replicate image edge colors, just as Shader 3884 made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the 3885 image edge color when it samples outside of its bounds. 3886 3887 #Param image uncompressed rectangular map of pixels ## 3888 #Param left left side of image ## 3889 #Param top pop side of image ## 3890 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3891 and so on; or nullptr 3892 ## 3893 3894 #Example 3895 #Height 64 3896 #Image 4 3897 void draw(SkCanvas* canvas) { 3898 // sk_sp<SkImage> image; 3899 canvas->drawImage(image, 0, 0); 3900 SkPaint paint; 3901 canvas->drawImage(image, 80, 0, &paint); 3902 paint.setAlpha(0x80); 3903 canvas->drawImage(image, 160, 0, &paint); 3904 } 3905 ## 3906 3907 #SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter 3908 3909 ## 3910 3911 # ------------------------------------------------------------------------------ 3912 3913 #Enum SrcRectConstraint 3914 #Line # sets drawImageRect options ## 3915 3916 #Code 3917 enum SrcRectConstraint { 3918 kStrict_SrcRectConstraint, 3919 kFast_SrcRectConstraint, 3920 }; 3921 ## 3922 3923 SrcRectConstraint controls the behavior at the edge of source Rect, 3924 provided to drawImageRect, trading off speed for precision. 3925 3926 Image_Filter in Paint may sample multiple pixels in the image. Source Rect 3927 restricts the bounds of pixels that may be read. Image_Filter may slow down if 3928 it cannot read outside the bounds, when sampling near the edge of source Rect. 3929 SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels 3930 outside source Rect. 3931 3932 #Const kStrict_SrcRectConstraint 3933 Requires Image_Filter to respect source Rect, 3934 sampling only inside of its bounds, possibly with a performance penalty. 3935 ## 3936 3937 #Const kFast_SrcRectConstraint 3938 Permits Image_Filter to sample outside of source Rect 3939 by half the width of Image_Filter, permitting it to run faster but with 3940 error at the image edges. 3941 ## 3942 3943 #Example 3944 #Height 64 3945 #Description 3946 redBorder contains a black and white checkerboard bordered by red. 3947 redBorder is drawn scaled by 16 on the left. 3948 The middle and right bitmaps are filtered checkerboards. 3949 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white. 3950 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners. 3951 ## 3952 void draw(SkCanvas* canvas) { 3953 SkBitmap redBorder; 3954 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4)); 3955 SkCanvas checkRed(redBorder); 3956 checkRed.clear(SK_ColorRED); 3957 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE }, 3958 { SK_ColorWHITE, SK_ColorBLACK } }; 3959 checkRed.writePixels( 3960 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1); 3961 canvas->scale(16, 16); 3962 canvas->drawBitmap(redBorder, 0, 0, nullptr); 3963 canvas->resetMatrix(); 3964 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder); 3965 SkPaint lowPaint; 3966 lowPaint.setFilterQuality(kLow_SkFilterQuality); 3967 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint, 3968 SkCanvas::kFast_SrcRectConstraint } ) { 3969 canvas->translate(80, 0); 3970 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3), 3971 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint); 3972 } 3973 } 3974 ## 3975 3976 #SeeAlso drawImageRect drawImage SkPaint::setImageFilter 3977 3978 ## 3979 3980 # ------------------------------------------------------------------------------ 3981 3982 #Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, 3983 const SkPaint* paint, 3984 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3985 #In Draw_Image 3986 #Line # draws Image, source Rect to destination Rect ## 3987 3988 Draw Rect src of Image image, scaled and translated to fill Rect dst. 3989 Additionally transform draw using Clip, Matrix, and optional Paint paint. 3990 3991 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 3992 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 3993 If paint contains Mask_Filter, generate mask from image bounds. 3994 3995 If generated mask extends beyond image bounds, replicate image edge colors, just 3996 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 3997 replicates the image edge color when it samples outside of its bounds. 3998 3999 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4000 sample within src; set to kFast_SrcRectConstraint allows sampling outside to 4001 improve performance. 4002 4003 #Param image Image containing pixels, dimensions, and format ## 4004 #Param src source Rect of image to draw from ## 4005 #Param dst destination Rect of image to draw to ## 4006 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4007 and so on; or nullptr 4008 ## 4009 #Param constraint filter strictly within src or draw faster ## 4010 4011 #Example 4012 #Height 64 4013 #Description 4014 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within 4015 its bounds; there is no bleeding with kFast_SrcRectConstraint. 4016 the middle and right bitmaps draw with kLow_SkFilterQuality; with 4017 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and 4018 with kFast_SrcRectConstraint red bleeds on the edges. 4019 ## 4020 void draw(SkCanvas* canvas) { 4021 uint32_t pixels[][4] = { 4022 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 }, 4023 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 }, 4024 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 }, 4025 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } }; 4026 SkBitmap redBorder; 4027 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4), 4028 (void*) pixels, sizeof(pixels[0])); 4029 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder); 4030 SkPaint lowPaint; 4031 for (auto constraint : { 4032 SkCanvas::kFast_SrcRectConstraint, 4033 SkCanvas::kStrict_SrcRectConstraint, 4034 SkCanvas::kFast_SrcRectConstraint } ) { 4035 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3), 4036 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint); 4037 lowPaint.setFilterQuality(kLow_SkFilterQuality); 4038 canvas->translate(80, 0); 4039 } 4040 } 4041 ## 4042 4043 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 4044 4045 ## 4046 4047 # ------------------------------------------------------------------------------ 4048 4049 #Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst, 4050 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4051 #In Draw_Image 4052 4053 Draw IRect isrc of Image image, scaled and translated to fill Rect dst. 4054 Note that isrc is on integer pixel boundaries; dst may include fractional 4055 boundaries. Additionally transform draw using Clip, Matrix, and optional Paint 4056 paint. 4057 4058 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4059 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4060 If paint contains Mask_Filter, generate mask from image bounds. 4061 4062 If generated mask extends beyond image bounds, replicate image edge colors, just 4063 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4064 replicates the image edge color when it samples outside of its bounds. 4065 4066 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4067 sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to 4068 improve performance. 4069 4070 #Param image Image containing pixels, dimensions, and format ## 4071 #Param isrc source IRect of image to draw from ## 4072 #Param dst destination Rect of image to draw to ## 4073 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4074 and so on; or nullptr 4075 ## 4076 #Param constraint filter strictly within isrc or draw faster ## 4077 4078 #Example 4079 #Image 4 4080 void draw(SkCanvas* canvas) { 4081 // sk_sp<SkImage> image; 4082 for (auto i : { 1, 2, 4, 8 } ) { 4083 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100), 4084 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr); 4085 } 4086 } 4087 ## 4088 4089 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 4090 4091 ## 4092 4093 # ------------------------------------------------------------------------------ 4094 4095 #Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint, 4096 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4097 #In Draw_Image 4098 4099 Draw Image image, scaled and translated to fill Rect dst, using Clip, Matrix, 4100 and optional Paint paint. 4101 4102 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4103 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4104 If paint contains Mask_Filter, generate mask from image bounds. 4105 4106 If generated mask extends beyond image bounds, replicate image edge colors, just 4107 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4108 replicates the image edge color when it samples outside of its bounds. 4109 4110 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4111 sample within image; set to kFast_SrcRectConstraint allows sampling outside to 4112 improve performance. 4113 4114 #Param image Image containing pixels, dimensions, and format ## 4115 #Param dst destination Rect of image to draw to ## 4116 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4117 and so on; or nullptr 4118 ## 4119 #Param constraint filter strictly within image or draw faster ## 4120 4121 #Example 4122 #Image 4 4123 void draw(SkCanvas* canvas) { 4124 // sk_sp<SkImage> image; 4125 for (auto i : { 20, 40, 80, 160 } ) { 4126 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr); 4127 } 4128 } 4129 ## 4130 4131 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 4132 4133 ## 4134 4135 # ------------------------------------------------------------------------------ 4136 4137 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst, 4138 const SkPaint* paint, 4139 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4140 #In Draw_Image 4141 4142 Draw Rect src of Image image, scaled and translated to fill Rect dst. 4143 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4144 4145 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4146 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4147 If paint contains Mask_Filter, generate mask from image bounds. 4148 4149 If generated mask extends beyond image bounds, replicate image edge colors, just 4150 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4151 replicates the image edge color when it samples outside of its bounds. 4152 4153 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4154 sample within src; set to kFast_SrcRectConstraint allows sampling outside to 4155 improve performance. 4156 4157 #Param image Image containing pixels, dimensions, and format ## 4158 #Param src source Rect of image to draw from ## 4159 #Param dst destination Rect of image to draw to ## 4160 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4161 and so on; or nullptr 4162 ## 4163 #Param constraint filter strictly within src or draw faster ## 4164 4165 #Example 4166 #Height 64 4167 #Description 4168 Canvas scales and translates; transformation from src to dst also scales. 4169 The two matrices are concatenated to create the final transformation. 4170 ## 4171 void draw(SkCanvas* canvas) { 4172 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE }, 4173 { SK_ColorWHITE, SK_ColorBLACK } }; 4174 SkBitmap bitmap; 4175 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 4176 (void*) pixels, sizeof(pixels[0])); 4177 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 4178 SkPaint paint; 4179 canvas->scale(4, 4); 4180 for (auto alpha : { 50, 100, 150, 255 } ) { 4181 paint.setAlpha(alpha); 4182 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint); 4183 canvas->translate(8, 0); 4184 } 4185 } 4186 ## 4187 4188 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 4189 4190 ## 4191 4192 # ------------------------------------------------------------------------------ 4193 4194 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst, 4195 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4196 #In Draw_Image 4197 4198 Draw IRect isrc of Image image, scaled and translated to fill Rect dst. 4199 isrc is on integer pixel boundaries; dst may include fractional boundaries. 4200 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4201 4202 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4203 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4204 If paint contains Mask_Filter, generate mask from image bounds. 4205 4206 If generated mask extends beyond image bounds, replicate image edge colors, just 4207 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4208 replicates the image edge color when it samples outside of its bounds. 4209 4210 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4211 sample within image; set to kFast_SrcRectConstraint allows sampling outside to 4212 improve performance. 4213 4214 #Param image Image containing pixels, dimensions, and format ## 4215 #Param isrc source IRect of image to draw from ## 4216 #Param dst destination Rect of image to draw to ## 4217 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4218 and so on; or nullptr 4219 ## 4220 #Param constraint filter strictly within image or draw faster ## 4221 4222 #Example 4223 #Height 64 4224 void draw(SkCanvas* canvas) { 4225 uint32_t pixels[][2] = { { 0x00000000, 0x55555555}, 4226 { 0xAAAAAAAA, 0xFFFFFFFF} }; 4227 SkBitmap bitmap; 4228 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 4229 (void*) pixels, sizeof(pixels[0])); 4230 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 4231 SkPaint paint; 4232 canvas->scale(4, 4); 4233 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 4234 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus)); 4235 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint); 4236 canvas->translate(8, 0); 4237 } 4238 } 4239 ## 4240 4241 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 4242 4243 ## 4244 4245 # ------------------------------------------------------------------------------ 4246 4247 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint, 4248 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4249 #In Draw_Image 4250 4251 Draw Image image, scaled and translated to fill Rect dst, 4252 using Clip, Matrix, and optional Paint paint. 4253 4254 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4255 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4256 If paint contains Mask_Filter, generate mask from image bounds. 4257 4258 If generated mask extends beyond image bounds, replicate image edge colors, just 4259 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4260 replicates the image edge color when it samples outside of its bounds. 4261 4262 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4263 sample within image; set to kFast_SrcRectConstraint allows sampling outside to 4264 improve performance. 4265 4266 #Param image Image containing pixels, dimensions, and format ## 4267 #Param dst destination Rect of image to draw to ## 4268 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4269 and so on; or nullptr 4270 ## 4271 #Param constraint filter strictly within image or draw faster ## 4272 4273 #Example 4274 #Height 64 4275 void draw(SkCanvas* canvas) { 4276 uint32_t pixels[][2] = { { 0x00000000, 0x55550000}, 4277 { 0xAAAA0000, 0xFFFF0000} }; 4278 SkBitmap bitmap; 4279 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 4280 (void*) pixels, sizeof(pixels[0])); 4281 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 4282 SkPaint paint; 4283 canvas->scale(4, 4); 4284 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 4285 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus)); 4286 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint); 4287 canvas->translate(8, 0); 4288 } 4289 } 4290 ## 4291 4292 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 4293 4294 ## 4295 4296 # ------------------------------------------------------------------------------ 4297 4298 #Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 4299 const SkPaint* paint = nullptr) 4300 #In Draw_Image 4301 #Line # draws Nine_Patch Image ## 4302 4303 Draw Image image stretched proportionally to fit into Rect dst. 4304 IRect center divides the image into nine sections: four sides, four corners, and 4305 the center. Corners are unmodified or scaled down proportionately if their sides 4306 are larger than dst; center and four sides are scaled to fit remaining space, if any. 4307 4308 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4309 4310 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4311 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4312 If paint contains Mask_Filter, generate mask from image bounds. 4313 4314 If generated mask extends beyond image bounds, replicate image edge colors, just 4315 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4316 replicates the image edge color when it samples outside of its bounds. 4317 4318 #Param image Image containing pixels, dimensions, and format ## 4319 #Param center IRect edge of image corners and sides ## 4320 #Param dst destination Rect of image to draw to ## 4321 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4322 and so on; or nullptr 4323 ## 4324 4325 #Example 4326 #Height 128 4327 #Description 4328 The leftmost image is smaller than center; only corners are drawn, all scaled to fit. 4329 The second image equals the size of center; only corners are drawn without scaling. 4330 The remaining images are larger than center. All corners draw without scaling. 4331 The sides and center are scaled if needed to take up the remaining space. 4332 ## 4333 void draw(SkCanvas* canvas) { 4334 SkIRect center = { 20, 10, 50, 40 }; 4335 SkBitmap bitmap; 4336 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 4337 SkCanvas bitCanvas(bitmap); 4338 SkPaint paint; 4339 SkColor gray = 0xFF000000; 4340 int left = 0; 4341 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 4342 int top = 0; 4343 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 4344 paint.setColor(gray); 4345 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 4346 gray += 0x001f1f1f; 4347 top = bottom; 4348 } 4349 left = right; 4350 } 4351 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 4352 SkImage* imagePtr = image.get(); 4353 for (auto dest: { 20, 30, 40, 60, 90 } ) { 4354 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr); 4355 canvas->translate(dest + 4, 0); 4356 } 4357 } 4358 ## 4359 4360 #SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect 4361 4362 ## 4363 4364 # ------------------------------------------------------------------------------ 4365 4366 #Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst, 4367 const SkPaint* paint = nullptr) 4368 #In Draw_Image 4369 4370 Draw Image image stretched proportionally to fit into Rect dst. 4371 IRect center divides the image into nine sections: four sides, four corners, and 4372 the center. Corners are not scaled, or scaled down proportionately if their sides 4373 are larger than dst; center and four sides are scaled to fit remaining space, if any. 4374 4375 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4376 4377 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4378 Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader. 4379 If paint contains Mask_Filter, generate mask from image bounds. 4380 4381 If generated mask extends beyond image bounds, replicate image edge colors, just 4382 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 4383 replicates the image edge color when it samples outside of its bounds. 4384 4385 #Param image Image containing pixels, dimensions, and format ## 4386 #Param center IRect edge of image corners and sides ## 4387 #Param dst destination Rect of image to draw to ## 4388 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4389 and so on; or nullptr 4390 ## 4391 4392 #Example 4393 #Height 128 4394 #Description 4395 The two leftmost images has four corners and sides to the left and right of center. 4396 The leftmost image scales the width of corners proportionately to fit. 4397 The third and fourth image corners are not scaled; the sides and center are scaled to 4398 fill the remaining space. 4399 The rightmost image has four corners scaled vertically to fit, and uses sides above 4400 and below center to fill the remaining space. 4401 ## 4402 void draw(SkCanvas* canvas) { 4403 SkIRect center = { 20, 10, 50, 40 }; 4404 SkBitmap bitmap; 4405 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 4406 SkCanvas bitCanvas(bitmap); 4407 SkPaint paint; 4408 SkColor gray = 0xFF000000; 4409 int left = 0; 4410 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 4411 int top = 0; 4412 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 4413 paint.setColor(gray); 4414 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 4415 gray += 0x001f1f1f; 4416 top = bottom; 4417 } 4418 left = right; 4419 } 4420 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 4421 for (auto dest: { 20, 30, 40, 60, 90 } ) { 4422 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr); 4423 canvas->translate(dest + 4, 0); 4424 } 4425 } 4426 ## 4427 4428 #SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect 4429 4430 ## 4431 4432 # ------------------------------------------------------------------------------ 4433 4434 #Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, 4435 const SkPaint* paint = nullptr) 4436 #In Draw_Image 4437 #Line # draws Bitmap at (x, y) position ## 4438 4439 Draw Bitmap bitmap, with its top-left corner at (left, top), 4440 using Clip, Matrix, and optional Paint paint. 4441 4442 If Paint paint is not nullptr, apply Color_Filter, Color_Alpha, Image_Filter, 4443 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4444 If paint contains Mask_Filter, generate mask from bitmap bounds. 4445 4446 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4447 just as Shader made from SkShader::MakeBitmapShader with 4448 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4449 outside of its bounds. 4450 4451 #Param bitmap Bitmap containing pixels, dimensions, and format ## 4452 #Param left left side of bitmap ## 4453 #Param top top side of bitmap ## 4454 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4455 and so on; or nullptr 4456 ## 4457 4458 #Example 4459 #Height 64 4460 void draw(SkCanvas* canvas) { 4461 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, 4462 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 4463 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, 4464 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF}, 4465 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 4466 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00}, 4467 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00}, 4468 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} }; 4469 SkBitmap bitmap; 4470 bitmap.installPixels(SkImageInfo::MakeA8(8, 8), 4471 (void*) pixels, sizeof(pixels[0])); 4472 SkPaint paint; 4473 canvas->scale(4, 4); 4474 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) { 4475 paint.setColor(color); 4476 canvas->drawBitmap(bitmap, 0, 0, &paint); 4477 canvas->translate(12, 0); 4478 } 4479 } 4480 ## 4481 4482 #SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels 4483 4484 ## 4485 4486 # ------------------------------------------------------------------------------ 4487 4488 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst, 4489 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4490 #In Draw_Image 4491 #Line # draws Bitmap, source Rect to destination Rect ## 4492 4493 Draw Rect src of Bitmap bitmap, scaled and translated to fill Rect dst. 4494 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4495 4496 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4497 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4498 If paint contains Mask_Filter, generate mask from bitmap bounds. 4499 4500 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4501 just as Shader made from SkShader::MakeBitmapShader with 4502 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4503 outside of its bounds. 4504 4505 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4506 sample within src; set to kFast_SrcRectConstraint allows sampling outside to 4507 improve performance. 4508 4509 #Param bitmap Bitmap containing pixels, dimensions, and format ## 4510 #Param src source Rect of image to draw from ## 4511 #Param dst destination Rect of image to draw to ## 4512 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4513 and so on; or nullptr 4514 ## 4515 #Param constraint filter strictly within src or draw faster ## 4516 4517 #Example 4518 #Height 64 4519 void draw(SkCanvas* canvas) { 4520 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, 4521 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 4522 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, 4523 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF}, 4524 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 4525 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00}, 4526 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, 4527 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} }; 4528 SkBitmap bitmap; 4529 bitmap.installPixels(SkImageInfo::MakeA8(8, 8), 4530 (void*) pixels, sizeof(pixels[0])); 4531 SkPaint paint; 4532 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 6)); 4533 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) { 4534 paint.setColor(color); 4535 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint); 4536 canvas->translate(48, 0); 4537 } 4538 } 4539 ## 4540 4541 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine 4542 4543 ## 4544 4545 # ------------------------------------------------------------------------------ 4546 4547 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst, 4548 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4549 #In Draw_Image 4550 4551 Draw IRect isrc of Bitmap bitmap, scaled and translated to fill Rect dst. 4552 isrc is on integer pixel boundaries; dst may include fractional boundaries. 4553 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4554 4555 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4556 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4557 If paint contains Mask_Filter, generate mask from bitmap bounds. 4558 4559 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4560 just as Shader made from SkShader::MakeBitmapShader with 4561 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4562 outside of its bounds. 4563 4564 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4565 sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to 4566 improve performance. 4567 4568 #Param bitmap Bitmap containing pixels, dimensions, and format ## 4569 #Param isrc source IRect of image to draw from ## 4570 #Param dst destination Rect of image to draw to ## 4571 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4572 and so on; or nullptr 4573 ## 4574 #Param constraint sample strictly within isrc, or draw faster ## 4575 4576 #Example 4577 #Height 64 4578 void draw(SkCanvas* canvas) { 4579 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 4580 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, 4581 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF}, 4582 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF}, 4583 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF}, 4584 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF}, 4585 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, 4586 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} }; 4587 SkBitmap bitmap; 4588 bitmap.installPixels(SkImageInfo::MakeA8(8, 8), 4589 (void*) pixels, sizeof(pixels[0])); 4590 SkPaint paint; 4591 paint.setFilterQuality(kHigh_SkFilterQuality); 4592 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) { 4593 paint.setColor(color); 4594 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint); 4595 canvas->translate(48.25f, 0); 4596 } 4597 } 4598 ## 4599 4600 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine 4601 4602 ## 4603 4604 # ------------------------------------------------------------------------------ 4605 4606 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, 4607 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 4608 #In Draw_Image 4609 4610 Draw Bitmap bitmap, scaled and translated to fill Rect dst. 4611 bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries. 4612 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4613 4614 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4615 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4616 If paint contains Mask_Filter, generate mask from bitmap bounds. 4617 4618 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4619 just as Shader made from SkShader::MakeBitmapShader with 4620 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4621 outside of its bounds. 4622 4623 constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to 4624 sample within bitmap; set to kFast_SrcRectConstraint allows sampling outside to 4625 improve performance. 4626 4627 #Param bitmap Bitmap containing pixels, dimensions, and format ## 4628 #Param dst destination Rect of image to draw to ## 4629 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4630 and so on; or nullptr 4631 ## 4632 #Param constraint filter strictly within bitmap or draw faster ## 4633 4634 #Example 4635 #Height 64 4636 void draw(SkCanvas* canvas) { 4637 uint32_t pixels[][2] = { { 0x00000000, 0x55550000}, 4638 { 0xAAAA0000, 0xFFFF0000} }; 4639 SkBitmap bitmap; 4640 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 4641 (void*) pixels, sizeof(pixels[0])); 4642 SkPaint paint; 4643 canvas->scale(4, 4); 4644 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 4645 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus)); 4646 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint); 4647 canvas->translate(8, 0); 4648 } 4649 } 4650 ## 4651 4652 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine 4653 4654 ## 4655 4656 # ------------------------------------------------------------------------------ 4657 4658 #Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 4659 const SkPaint* paint = nullptr) 4660 #In Draw_Image 4661 #Line # draws Nine_Patch Bitmap ## 4662 4663 Draw Bitmap bitmap stretched proportionally to fit into Rect dst. 4664 IRect center divides the bitmap into nine sections: four sides, four corners, 4665 and the center. Corners are not scaled, or scaled down proportionately if their 4666 sides are larger than dst; center and four sides are scaled to fit remaining 4667 space, if any. 4668 4669 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4670 4671 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4672 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4673 If paint contains Mask_Filter, generate mask from bitmap bounds. 4674 4675 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4676 just as Shader made from SkShader::MakeBitmapShader with 4677 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4678 outside of its bounds. 4679 4680 #Param bitmap Bitmap containing pixels, dimensions, and format ## 4681 #Param center IRect edge of image corners and sides ## 4682 #Param dst destination Rect of image to draw to ## 4683 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4684 and so on; or nullptr 4685 ## 4686 4687 #Example 4688 #Height 128 4689 #Description 4690 The two leftmost bitmap draws has four corners and sides to the left and right of center. 4691 The leftmost bitmap draw scales the width of corners proportionately to fit. 4692 The third and fourth draw corners are not scaled; the sides and center are scaled to 4693 fill the remaining space. 4694 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above 4695 and below center to fill the remaining space. 4696 ## 4697 void draw(SkCanvas* canvas) { 4698 SkIRect center = { 20, 10, 50, 40 }; 4699 SkBitmap bitmap; 4700 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 4701 SkCanvas bitCanvas(bitmap); 4702 SkPaint paint; 4703 SkColor gray = 0xFF000000; 4704 int left = 0; 4705 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 4706 int top = 0; 4707 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 4708 paint.setColor(gray); 4709 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 4710 gray += 0x001f1f1f; 4711 top = bottom; 4712 } 4713 left = right; 4714 } 4715 for (auto dest: { 20, 30, 40, 60, 90 } ) { 4716 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr); 4717 canvas->translate(dest + 4, 0); 4718 } 4719 } 4720 ## 4721 4722 #SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect 4723 4724 ## 4725 4726 # ------------------------------------------------------------------------------ 4727 #Struct Lattice 4728 #Line # divides Bitmap or Image into a rectangular grid ## 4729 #Code 4730 struct Lattice { 4731 enum RectType ... 4732 4733 const int* fXDivs; 4734 const int* fYDivs; 4735 const RectType* fRectTypes; 4736 int fXCount; 4737 int fYCount; 4738 const SkIRect* fBounds; 4739 const SkColor* fColors; 4740 }; 4741 ## 4742 4743 Lattice divides Bitmap or Image into a rectangular grid. 4744 Grid entries on even columns and even rows are fixed; these entries are 4745 always drawn at their original size if the destination is large enough. 4746 If the destination side is too small to hold the fixed entries, all fixed 4747 entries are proportionately scaled down to fit. 4748 The grid entries not on even columns and rows are scaled to fit the 4749 remaining space, if any. 4750 4751 #Enum RectType 4752 #Code 4753 enum RectType : uint8_t { 4754 kDefault = 0, 4755 kTransparent, 4756 kFixedColor, 4757 }; 4758 ## 4759 4760 Optional setting per rectangular grid entry to make it transparent, 4761 or to fill the grid entry with a color. 4762 4763 #Const kDefault 0 4764 Draws Bitmap into lattice rectangle. 4765 ## 4766 4767 #Const kTransparent 1 4768 Skips lattice rectangle by making it transparent. 4769 ## 4770 4771 #Const kFixedColor 2 4772 Draws one of fColors into lattice rectangle. 4773 ## 4774 ## 4775 4776 #Member const int* fXDivs 4777 Array of x-coordinates that divide the bitmap vertically. 4778 Array entries must be unique, increasing, greater than or equal to 4779 fBounds left edge, and less than fBounds right edge. 4780 Set the first element to fBounds left to collapse the left column of 4781 fixed grid entries. 4782 ## 4783 4784 #Member const int* fYDivs 4785 Array of y-coordinates that divide the bitmap horizontally. 4786 Array entries must be unique, increasing, greater than or equal to 4787 fBounds top edge, and less than fBounds bottom edge. 4788 Set the first element to fBounds top to collapse the top row of fixed 4789 grid entries. 4790 ## 4791 4792 #Member const RectType* fRectTypes 4793 Optional array of fill types, one per rectangular grid entry: 4794 array length must be 4795 #Formula 4796 (fXCount + 1) * (fYCount + 1) 4797 ## 4798 . 4799 4800 Each RectType is one of: kDefault, kTransparent, kFixedColor. 4801 4802 Array entries correspond to the rectangular grid entries, ascending 4803 left to right and then top to bottom. 4804 ## 4805 4806 #Member int fXCount 4807 Number of entries in fXDivs array; one less than the number of 4808 horizontal divisions. 4809 ## 4810 4811 #Member int fYCount 4812 Number of entries in fYDivs array; one less than the number of vertical 4813 divisions. 4814 ## 4815 4816 #Member const SkIRect* fBounds 4817 Optional subset IRect source to draw from. 4818 If nullptr, source bounds is dimensions of Bitmap or Image. 4819 ## 4820 4821 #Member const SkColor* fColors 4822 Optional array of colors, one per rectangular grid entry. 4823 Array length must be 4824 #Formula 4825 (fXCount + 1) * (fYCount + 1) 4826 ## 4827 . 4828 4829 Array entries correspond to the rectangular grid entries, ascending 4830 left to right, then top to bottom. 4831 ## 4832 4833 #Struct Lattice ## 4834 4835 #Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst, 4836 const SkPaint* paint = nullptr) 4837 #In Draw_Image 4838 #Line # draws proportionally stretched Bitmap ## 4839 4840 Draw Bitmap bitmap stretched proportionally to fit into Rect dst. 4841 4842 Lattice lattice divides bitmap into a rectangular grid. 4843 Each intersection of an even-numbered row and column is fixed; like the corners 4844 of drawBitmapNine, fixed lattice elements never scale larger than their initial 4845 size and shrink proportionately when all fixed elements exceed the bitmap 4846 dimension. All other grid elements scale to fill the available space, if any. 4847 4848 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4849 4850 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4851 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4852 If paint contains Mask_Filter, generate mask from bitmap bounds. 4853 4854 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4855 just as Shader made from SkShader::MakeBitmapShader with 4856 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4857 outside of its bounds. 4858 4859 #Param bitmap Bitmap containing pixels, dimensions, and format ## 4860 #Param lattice division of bitmap into fixed and variable rectangles ## 4861 #Param dst destination Rect of image to draw to ## 4862 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4863 and so on; or nullptr 4864 ## 4865 4866 #Example 4867 #Height 128 4868 #Description 4869 The two leftmost bitmap draws has four corners and sides to the left and right of center. 4870 The leftmost bitmap draw scales the width of corners proportionately to fit. 4871 The third and fourth draw corners are not scaled; the sides are scaled to 4872 fill the remaining space; the center is transparent. 4873 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above 4874 and below center to fill the remaining space. 4875 ## 4876 void draw(SkCanvas* canvas) { 4877 SkIRect center = { 20, 10, 50, 40 }; 4878 SkBitmap bitmap; 4879 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 4880 SkCanvas bitCanvas(bitmap); 4881 SkPaint paint; 4882 SkColor gray = 0xFF000000; 4883 int left = 0; 4884 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 4885 int top = 0; 4886 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 4887 paint.setColor(gray); 4888 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 4889 gray += 0x001f1f1f; 4890 top = bottom; 4891 } 4892 left = right; 4893 } 4894 const int xDivs[] = { center.fLeft, center.fRight }; 4895 const int yDivs[] = { center.fTop, center.fBottom }; 4896 SkCanvas::Lattice::RectType fillTypes[3][3]; 4897 memset(fillTypes, 0, sizeof(fillTypes)); 4898 fillTypes[1][1] = SkCanvas::Lattice::kTransparent; 4899 SkColor dummy[9]; // temporary pending bug fix 4900 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs), 4901 SK_ARRAY_COUNT(yDivs), nullptr, dummy }; 4902 for (auto dest: { 20, 30, 40, 60, 90 } ) { 4903 canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr); 4904 canvas->translate(dest + 4, 0); 4905 } 4906 } 4907 ## 4908 4909 #SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice 4910 4911 ## 4912 4913 # ------------------------------------------------------------------------------ 4914 4915 #Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 4916 const SkPaint* paint = nullptr) 4917 #In Draw_Image 4918 #Line # draws proportionally stretched Image ## 4919 4920 Draw Image image stretched proportionally to fit into Rect dst. 4921 4922 Lattice lattice divides image into a rectangular grid. 4923 Each intersection of an even-numbered row and column is fixed; like the corners 4924 of drawBitmapNine, fixed lattice elements never scale larger than their initial 4925 size and shrink proportionately when all fixed elements exceed the bitmap 4926 dimension. All other grid elements scale to fill the available space, if any. 4927 4928 Additionally transform draw using Clip, Matrix, and optional Paint paint. 4929 4930 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 4931 Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader. 4932 If paint contains Mask_Filter, generate mask from bitmap bounds. 4933 4934 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 4935 just as Shader made from SkShader::MakeBitmapShader with 4936 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 4937 outside of its bounds. 4938 4939 #Param image Image containing pixels, dimensions, and format ## 4940 #Param lattice division of bitmap into fixed and variable rectangles ## 4941 #Param dst destination Rect of image to draw to ## 4942 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 4943 and so on; or nullptr 4944 ## 4945 4946 #Example 4947 #Height 128 4948 #Description 4949 The leftmost image is smaller than center; only corners are drawn, all scaled to fit. 4950 The second image equals the size of center; only corners are drawn without scaling. 4951 The remaining images are larger than center. All corners draw without scaling. The sides 4952 are scaled if needed to take up the remaining space; the center is transparent. 4953 ## 4954 void draw(SkCanvas* canvas) { 4955 SkIRect center = { 20, 10, 50, 40 }; 4956 SkBitmap bitmap; 4957 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 4958 SkCanvas bitCanvas(bitmap); 4959 SkPaint paint; 4960 SkColor gray = 0xFF000000; 4961 int left = 0; 4962 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 4963 int top = 0; 4964 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 4965 paint.setColor(gray); 4966 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 4967 gray += 0x001f1f1f; 4968 top = bottom; 4969 } 4970 left = right; 4971 } 4972 const int xDivs[] = { center.fLeft, center.fRight }; 4973 const int yDivs[] = { center.fTop, center.fBottom }; 4974 SkCanvas::Lattice::RectType fillTypes[3][3]; 4975 memset(fillTypes, 0, sizeof(fillTypes)); 4976 fillTypes[1][1] = SkCanvas::Lattice::kTransparent; 4977 SkColor dummy[9]; // temporary pending bug fix 4978 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs), 4979 SK_ARRAY_COUNT(yDivs), nullptr, dummy }; 4980 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 4981 SkImage* imagePtr = image.get(); 4982 for (auto dest: { 20, 30, 40, 60, 90 } ) { 4983 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr); 4984 canvas->translate(dest + 4, 0); 4985 } 4986 } 4987 ## 4988 4989 #SeeAlso drawBitmapLattice drawImage drawImageNine Lattice 4990 4991 ## 4992 4993 #Subtopic Draw_Image ## 4994 4995 # ------------------------------------------------------------------------------ 4996 4997 #Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 4998 const SkPaint& paint) 4999 #Line # draws text at (x, y), using font advance ## 5000 5001 Draw text, with origin at (x, y), using Clip, Matrix, and Paint paint. 5002 5003 text meaning depends on Paint_Text_Encoding; by default, text is encoded as 5004 UTF-8. 5005 5006 x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default 5007 text draws left to right, positioning the first glyph left side bearing at x 5008 and its baseline at y. Text size is affected by Matrix and Paint_Text_Size. 5009 5010 All elements of paint: Path_Effect, Mask_Filter, Shader, 5011 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5012 filled 12 point black Glyphs. 5013 5014 #Param text character code points or Glyphs drawn ## 5015 #Param byteLength byte length of text array ## 5016 #Param x start of text on x-axis ## 5017 #Param y start of text on y-axis ## 5018 #Param paint text size, blend, color, and so on, used to draw ## 5019 5020 #Example 5021 #Height 200 5022 #Description 5023 The same text is drawn varying Paint_Text_Size and varying 5024 Matrix. 5025 ## 5026 void draw(SkCanvas* canvas) { 5027 SkPaint paint; 5028 paint.setAntiAlias(true); 5029 float textSizes[] = { 12, 18, 24, 36 }; 5030 for (auto size: textSizes ) { 5031 paint.setTextSize(size); 5032 canvas->drawText("Aa", 2, 10, 20, paint); 5033 canvas->translate(0, size * 2); 5034 } 5035 paint.reset(); 5036 paint.setAntiAlias(true); 5037 float yPos = 20; 5038 for (auto size: textSizes ) { 5039 float scale = size / 12.f; 5040 canvas->resetMatrix(); 5041 canvas->translate(100, 0); 5042 canvas->scale(scale, scale); 5043 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint); 5044 yPos += size * 2; 5045 } 5046 } 5047 ## 5048 5049 #SeeAlso drawString drawPosText drawPosTextH drawTextBlob drawTextOnPath drawTextRSXform 5050 5051 ## 5052 5053 #Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint) 5054 5055 #Line # draws null terminated string at (x, y) using font advance ## 5056 Draw null terminated string, with origin at (x, y), using Clip, Matrix, and 5057 Paint paint. 5058 5059 string meaning depends on Paint_Text_Encoding; by default, strings are encoded 5060 as UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired 5061 results, since zero bytes may be embedded in the string. 5062 5063 x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default 5064 string draws left to right, positioning the first glyph left side bearing at x 5065 and its baseline at y. Text size is affected by Matrix and Paint_Text_Size. 5066 5067 All elements of paint: Path_Effect, Mask_Filter, Shader, 5068 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5069 filled 12 point black Glyphs. 5070 5071 #Param string character code points or Glyphs drawn, 5072 ending with a char value of zero 5073 ## 5074 #Param x start of string on x-axis ## 5075 #Param y start of string on y-axis ## 5076 #Param paint text size, blend, color, and so on, used to draw ## 5077 5078 #Example 5079 SkPaint paint; 5080 canvas->drawString("a small hello", 20, 20, paint); 5081 ## 5082 5083 #SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextOnPath drawTextRSXform 5084 5085 ## 5086 5087 #Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint) 5088 5089 Draw null terminated string, with origin at (x, y), using Clip, Matrix, and 5090 Paint paint. 5091 5092 string meaning depends on Paint_Text_Encoding; by default, strings are encoded 5093 as UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired 5094 results, since zero bytes may be embedded in the string. 5095 5096 x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default 5097 string draws left to right, positioning the first glyph left side bearing at x 5098 and its baseline at y. Text size is affected by Matrix and Paint_Text_Size. 5099 5100 All elements of paint: Path_Effect, Mask_Filter, Shader, 5101 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5102 filled 12 point black Glyphs. 5103 5104 #Param string character code points or Glyphs drawn, 5105 ending with a char value of zero 5106 ## 5107 #Param x start of string on x-axis ## 5108 #Param y start of string on y-axis ## 5109 #Param paint text size, blend, color, and so on, used to draw ## 5110 5111 #Example 5112 SkPaint paint; 5113 SkString string("a small hello"); 5114 canvas->drawString(string, 20, 20, paint); 5115 ## 5116 5117 #SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextOnPath drawTextRSXform 5118 5119 ## 5120 5121 # ------------------------------------------------------------------------------ 5122 5123 #Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 5124 const SkPaint& paint) 5125 #Line # draws text at array of (x, y) positions ## 5126 5127 Draw each glyph in text with the origin in pos array, using Clip, Matrix, and 5128 Paint paint. The number of entries in pos array must match the number of Glyphs 5129 described by byteLength of text. 5130 5131 text meaning depends on Paint_Text_Encoding; by default, text is encoded as 5132 UTF-8. pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text; 5133 by default each glyph left side bearing is positioned at x and its 5134 baseline is positioned at y. Text size is affected by Matrix and 5135 Paint_Text_Size. 5136 5137 All elements of paint: Path_Effect, Mask_Filter, Shader, 5138 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5139 filled 12 point black Glyphs. 5140 5141 Layout engines such as Harfbuzz typically position each glyph 5142 rather than using the font advance widths. 5143 5144 #Param text character code points or Glyphs drawn ## 5145 #Param byteLength byte length of text array ## 5146 #Param pos array of glyph origins ## 5147 #Param paint text size, blend, color, and so on, used to draw ## 5148 5149 #Example 5150 #Height 120 5151 void draw(SkCanvas* canvas) { 5152 const char hello[] = "HeLLo!"; 5153 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85}, 5154 {172, 100} }; 5155 SkPaint paint; 5156 paint.setTextSize(60); 5157 canvas->drawPosText(hello, strlen(hello), pos, paint); 5158 } 5159 ## 5160 5161 #SeeAlso drawText drawPosTextH drawTextBlob drawTextOnPath drawTextRSXform 5162 5163 ## 5164 5165 # ------------------------------------------------------------------------------ 5166 5167 #Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, 5168 const SkPaint& paint) 5169 #Line # draws text at x positions with common baseline ## 5170 5171 Draw each glyph in text with its (x, y) origin composed from xpos array and 5172 constY, using Clip, Matrix, and Paint paint. The number of entries in xpos array 5173 must match the number of Glyphs described by byteLength of text. 5174 5175 text meaning depends on Paint_Text_Encoding; by default, text is encoded as 5176 UTF-8. xpos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text; 5177 by default each glyph left side bearing is positioned at an xpos element and 5178 its baseline is positioned at constY. Text size is affected by Matrix and 5179 Paint_Text_Size. 5180 5181 All elements of paint: Path_Effect, Mask_Filter, Shader, 5182 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5183 filled 12 point black Glyphs. 5184 5185 Layout engines such as Harfbuzz typically position each glyph 5186 rather than using the font advance widths if all Glyphs share the same 5187 baseline. 5188 5189 #Param text character code points or Glyphs drawn ## 5190 #Param byteLength byte length of text array ## 5191 #Param xpos array of x positions, used to position each glyph ## 5192 #Param constY shared y coordinate for all of x positions ## 5193 #Param paint text size, blend, color, and so on, used to draw ## 5194 5195 #Example 5196 #Height 40 5197 void draw(SkCanvas* canvas) { 5198 SkScalar xpos[] = { 20, 40, 80, 160 }; 5199 SkPaint paint; 5200 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint); 5201 } 5202 ## 5203 5204 #SeeAlso drawText drawPosText drawTextBlob drawTextOnPath drawTextRSXform 5205 5206 ## 5207 5208 # ------------------------------------------------------------------------------ 5209 5210 #Method void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset, 5211 SkScalar vOffset, const SkPaint& paint) 5212 #Line # draws text following Path with offsets ## 5213 5214 Draw text on Path path, using Clip, Matrix, and Paint paint. 5215 5216 Origin of text is at distance hOffset along the path, offset by a perpendicular 5217 vector of length vOffset. If the path section corresponding the glyph advance is 5218 curved, the glyph is drawn curved to match; control points in the glyph are 5219 mapped to projected points parallel to the path. If the text advance is larger 5220 than the path length, the excess text is clipped. 5221 5222 text meaning depends on Paint_Text_Encoding; by default, text is encoded as 5223 UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by 5224 default text positions the first glyph left side bearing at origin x and its 5225 baseline at origin y. Text size is affected by Matrix and Paint_Text_Size. 5226 5227 All elements of paint: Path_Effect, Mask_Filter, Shader, 5228 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5229 filled 12 point black Glyphs. 5230 5231 #Param text character code points or Glyphs drawn ## 5232 #Param byteLength byte length of text array ## 5233 #Param path Path providing text baseline ## 5234 #Param hOffset distance along path to offset origin ## 5235 #Param vOffset offset of text above (if negative) or below (if positive) the path ## 5236 #Param paint text size, blend, color, and so on, used to draw ## 5237 5238 #Example 5239 void draw(SkCanvas* canvas) { 5240 const char aero[] = "correo a" "\xC3" "\xA9" "reo"; 5241 const size_t len = sizeof(aero) - 1; 5242 SkPath path; 5243 path.addOval({43-26, 43-26, 43+26, 43+26}, SkPath::kCW_Direction, 3); 5244 SkPaint paint; 5245 paint.setTextSize(24); 5246 for (auto offset : { 0, 10, 20 } ) { 5247 canvas->drawTextOnPathHV(aero, len, path, 0, -offset, paint); 5248 canvas->translate(70 + offset, 70 + offset); 5249 } 5250 } 5251 ## 5252 5253 #SeeAlso drawTextOnPath drawText drawPosTextH drawTextBlob drawTextRSXform 5254 5255 ## 5256 5257 # ------------------------------------------------------------------------------ 5258 5259 #Method void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 5260 const SkMatrix* matrix, const SkPaint& paint) 5261 #Line # draws text following Path contour ## 5262 5263 Draw text on Path path, using Clip, Matrix, and Paint paint. 5264 5265 Origin of text is at beginning of path offset by matrix, if provided, before it 5266 is mapped to path. If the path section corresponding the glyph advance is 5267 curved, the glyph is drawn curved to match; control points in the glyph are 5268 mapped to projected points parallel to the path. If the text advance is larger 5269 than the path length, the excess text is clipped. 5270 5271 text meaning depends on Paint_Text_Encoding; by default, text is encoded as 5272 UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by 5273 default text positions the first glyph left side bearing at origin x and its 5274 baseline at origin y. Text size is affected by Matrix and Paint_Text_Size. 5275 5276 All elements of paint: Path_Effect, Mask_Filter, Shader, 5277 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5278 filled 12 point black Glyphs. 5279 5280 #Param text character code points or Glyphs drawn ## 5281 #Param byteLength byte length of text array ## 5282 #Param path Path providing text baseline ## 5283 #Param matrix transform of Glyphs before mapping to path; may be nullptr 5284 to use identity Matrix 5285 ## 5286 #Param paint text size, blend, color, and so on, used to draw ## 5287 5288 #Example 5289 void draw(SkCanvas* canvas) { 5290 const char roller[] = "rollercoaster"; 5291 const size_t len = sizeof(roller) - 1; 5292 SkPath path; 5293 path.cubicTo(40, -80, 120, 80, 160, -40); 5294 SkPaint paint; 5295 paint.setTextSize(32); 5296 paint.setStyle(SkPaint::kStroke_Style); 5297 SkMatrix matrix; 5298 matrix.setIdentity(); 5299 for (int i = 0; i < 3; ++i) { 5300 canvas->translate(25, 60); 5301 canvas->drawPath(path, paint); 5302 canvas->drawTextOnPath(roller, len, path, &matrix, paint); 5303 matrix.preTranslate(0, 10); 5304 } 5305 } 5306 ## 5307 5308 #SeeAlso drawTextOnPathHV drawText drawPosTextH drawTextBlob drawTextRSXform 5309 5310 ## 5311 5312 # ------------------------------------------------------------------------------ 5313 5314 #Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], 5315 const SkRect* cullRect, const SkPaint& paint) 5316 #Line # draws text with array of RSXform ## 5317 5318 Draw text, transforming each glyph by the corresponding SkRSXform, 5319 using Clip, Matrix, and Paint paint. 5320 5321 RSXform array specifies a separate square scale, rotation, and translation for 5322 each glyph. 5323 5324 Optional Rect cullRect is a conservative bounds of text, taking into account 5325 RSXform and paint. If cullRect is outside of Clip, canvas can skip drawing. 5326 5327 All elements of paint: Path_Effect, Mask_Filter, Shader, 5328 Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws 5329 filled 12 point black Glyphs. 5330 5331 #Param text character code points or Glyphs drawn ## 5332 #Param byteLength byte length of text array ## 5333 #Param xform RSXform rotates, scales, and translates each glyph individually ## 5334 #Param cullRect Rect bounds of text for efficient clipping; or nullptr ## 5335 #Param paint text size, blend, color, and so on, used to draw ## 5336 5337 #Example 5338 void draw(SkCanvas* canvas) { 5339 const int iterations = 26; 5340 SkRSXform transforms[iterations]; 5341 char alphabet[iterations]; 5342 SkScalar angle = 0; 5343 SkScalar scale = 1; 5344 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) { 5345 const SkScalar s = SkScalarSin(angle) * scale; 5346 const SkScalar c = SkScalarCos(angle) * scale; 5347 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16); 5348 angle += .45; 5349 scale += .2; 5350 alphabet[i] = 'A' + i; 5351 } 5352 SkPaint paint; 5353 paint.setTextAlign(SkPaint::kCenter_Align); 5354 canvas->translate(110, 138); 5355 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint); 5356 } 5357 ## 5358 5359 #SeeAlso drawTextOnPath drawTextOnPathHV drawText drawPosText drawTextBlob 5360 5361 ## 5362 5363 # ------------------------------------------------------------------------------ 5364 5365 #Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) 5366 5367 #Line # draws text with arrays of positions and Paint ## 5368 Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint. 5369 5370 blob contains Glyphs, their positions, and paint attributes specific to text: 5371 Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X, 5372 Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold, 5373 Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text, 5374 Subpixel_Text, and Paint_Vertical_Text. 5375 5376 Paint_Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding. 5377 5378 Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter, 5379 Image_Filter, and Draw_Looper; apply to blob. 5380 5381 #Param blob Glyphs, positions, and their paints' text size, typeface, and so on ## 5382 #Param x horizontal offset applied to blob ## 5383 #Param y vertical offset applied to blob ## 5384 #Param paint blend, color, stroking, and so on, used to draw ## 5385 5386 #Example 5387 #Height 120 5388 void draw(SkCanvas* canvas) { 5389 SkTextBlobBuilder textBlobBuilder; 5390 const char bunny[] = "/(^x^)\\"; 5391 const int len = sizeof(bunny) - 1; 5392 uint16_t glyphs[len]; 5393 SkPaint paint; 5394 paint.textToGlyphs(bunny, len, glyphs); 5395 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 5396 int runs[] = { 3, 1, 3 }; 5397 SkPoint textPos = { 20, 100 }; 5398 int glyphIndex = 0; 5399 for (auto runLen : runs) { 5400 paint.setTextSize(1 == runLen ? 20 : 50); 5401 const SkTextBlobBuilder::RunBuffer& run = 5402 textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY); 5403 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen); 5404 textPos.fX += paint.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, nullptr); 5405 glyphIndex += runLen; 5406 } 5407 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 5408 paint.reset(); 5409 canvas->drawTextBlob(blob.get(), 0, 0, paint); 5410 } 5411 ## 5412 5413 #SeeAlso drawText drawPosText drawPosTextH 5414 5415 ## 5416 5417 # ------------------------------------------------------------------------------ 5418 5419 #Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) 5420 5421 Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint. 5422 5423 blob contains Glyphs, their positions, and paint attributes specific to text: 5424 Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X, 5425 Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold, 5426 Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text, 5427 Subpixel_Text, and Paint_Vertical_Text. 5428 5429 Paint_Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding. 5430 5431 Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter, 5432 Image_Filter, and Draw_Looper; apply to blob. 5433 5434 #Param blob Glyphs, positions, and their paints' text size, typeface, and so on ## 5435 #Param x horizontal offset applied to blob ## 5436 #Param y vertical offset applied to blob ## 5437 #Param paint blend, color, stroking, and so on, used to draw ## 5438 5439 #Example 5440 #Height 120 5441 #Description 5442 Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob. 5443 Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob. 5444 ## 5445 void draw(SkCanvas* canvas) { 5446 SkTextBlobBuilder textBlobBuilder; 5447 SkPaint paint; 5448 paint.setTextSize(50); 5449 paint.setColor(SK_ColorRED); 5450 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 5451 const SkTextBlobBuilder::RunBuffer& run = 5452 textBlobBuilder.allocRun(paint, 1, 20, 100); 5453 run.glyphs[0] = 20; 5454 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 5455 paint.setTextSize(10); 5456 paint.setColor(SK_ColorBLUE); 5457 canvas->drawTextBlob(blob.get(), 0, 0, paint); 5458 } 5459 ## 5460 5461 #SeeAlso drawText drawPosText drawPosTextH 5462 5463 ## 5464 5465 # ------------------------------------------------------------------------------ 5466 5467 #Method void drawPicture(const SkPicture* picture) 5468 5469 #Line # draws Picture using Clip and Matrix ## 5470 Draw Picture picture, using Clip and Matrix. 5471 Clip and Matrix are unchanged by picture contents, as if 5472 save() was called before and restore() was called after drawPicture. 5473 5474 Picture records a series of draw commands for later playback. 5475 5476 #Param picture recorded drawing commands to play ## 5477 5478 #Example 5479 void draw(SkCanvas* canvas) { 5480 SkPictureRecorder recorder; 5481 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 5482 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 5483 SkPaint paint; 5484 paint.setColor(color); 5485 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 5486 recordingCanvas->translate(10, 10); 5487 recordingCanvas->scale(1.2f, 1.4f); 5488 } 5489 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 5490 const SkPicture* playbackPtr = playback.get(); 5491 canvas->drawPicture(playback); 5492 canvas->scale(2, 2); 5493 canvas->translate(50, 0); 5494 canvas->drawPicture(playback); 5495 } 5496 ## 5497 5498 #SeeAlso drawDrawable SkPicture SkPicture::playback 5499 5500 ## 5501 5502 # ------------------------------------------------------------------------------ 5503 5504 #Method void drawPicture(const sk_sp<SkPicture>& picture) 5505 5506 Draw Picture picture, using Clip and Matrix. 5507 Clip and Matrix are unchanged by picture contents, as if 5508 save() was called before and restore() was called after drawPicture. 5509 5510 Picture records a series of draw commands for later playback. 5511 5512 #Param picture recorded drawing commands to play ## 5513 5514 #Example 5515 void draw(SkCanvas* canvas) { 5516 SkPictureRecorder recorder; 5517 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 5518 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 5519 SkPaint paint; 5520 paint.setColor(color); 5521 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 5522 recordingCanvas->translate(10, 10); 5523 recordingCanvas->scale(1.2f, 1.4f); 5524 } 5525 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 5526 canvas->drawPicture(playback); 5527 canvas->scale(2, 2); 5528 canvas->translate(50, 0); 5529 canvas->drawPicture(playback); 5530 } 5531 ## 5532 5533 #SeeAlso drawDrawable SkPicture SkPicture::playback 5534 5535 ## 5536 5537 # ------------------------------------------------------------------------------ 5538 5539 #Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) 5540 5541 Draw Picture picture, using Clip and Matrix; transforming picture with 5542 Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter, 5543 Image_Filter, and Blend_Mode, if provided. 5544 5545 matrix transformation is equivalent to: save(), concat(), drawPicture, restore(). 5546 paint use is equivalent to: saveLayer, drawPicture, restore(). 5547 5548 #Param picture recorded drawing commands to play ## 5549 #Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ## 5550 #Param paint Paint to apply transparency, filtering, and so on; may be nullptr ## 5551 5552 #Example 5553 void draw(SkCanvas* canvas) { 5554 SkPaint paint; 5555 SkPictureRecorder recorder; 5556 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 5557 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 5558 paint.setColor(color); 5559 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 5560 recordingCanvas->translate(10, 10); 5561 recordingCanvas->scale(1.2f, 1.4f); 5562 } 5563 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 5564 const SkPicture* playbackPtr = playback.get(); 5565 SkMatrix matrix; 5566 matrix.reset(); 5567 for (auto alpha : { 70, 140, 210 } ) { 5568 paint.setAlpha(alpha); 5569 canvas->drawPicture(playbackPtr, &matrix, &paint); 5570 matrix.preTranslate(70, 70); 5571 } 5572 } 5573 ## 5574 5575 #SeeAlso drawDrawable SkPicture SkPicture::playback 5576 5577 ## 5578 5579 # ------------------------------------------------------------------------------ 5580 5581 #Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) 5582 5583 Draw Picture picture, using Clip and Matrix; transforming picture with 5584 Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter, 5585 Image_Filter, and Blend_Mode, if provided. 5586 5587 matrix transformation is equivalent to: save(), concat(), drawPicture, restore(). 5588 paint use is equivalent to: saveLayer, drawPicture, restore(). 5589 5590 #Param picture recorded drawing commands to play ## 5591 #Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ## 5592 #Param paint Paint to apply transparency, filtering, and so on; may be nullptr ## 5593 5594 #Example 5595 void draw(SkCanvas* canvas) { 5596 SkPaint paint; 5597 SkPictureRecorder recorder; 5598 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 5599 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 5600 paint.setColor(color); 5601 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 5602 recordingCanvas->translate(10, 10); 5603 recordingCanvas->scale(1.2f, 1.4f); 5604 } 5605 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 5606 SkMatrix matrix; 5607 matrix.reset(); 5608 for (auto alpha : { 70, 140, 210 } ) { 5609 paint.setAlpha(alpha); 5610 canvas->drawPicture(playback, &matrix, &paint); 5611 matrix.preTranslate(70, 70); 5612 } 5613 } 5614 ## 5615 5616 #SeeAlso drawDrawable SkPicture SkPicture::playback 5617 5618 ## 5619 5620 # ------------------------------------------------------------------------------ 5621 5622 #Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) 5623 5624 #Line # draws Vertices, a triangle mesh ## 5625 Draw Vertices vertices, a triangle mesh, using Clip and Matrix. 5626 If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint 5627 contains Shader, Blend_Mode mode combines Vertices_Colors with Shader. 5628 5629 #Param vertices triangle mesh to draw ## 5630 #Param mode combines Vertices_Colors with Shader, if both are present ## 5631 #Param paint specifies the Shader, used as Vertices texture; may be nullptr ## 5632 5633 #Example 5634 void draw(SkCanvas* canvas) { 5635 SkPaint paint; 5636 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } }; 5637 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 5638 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 5639 SK_ARRAY_COUNT(points), points, nullptr, colors); 5640 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint); 5641 } 5642 ## 5643 5644 #SeeAlso drawPatch drawPicture 5645 5646 ## 5647 5648 # ------------------------------------------------------------------------------ 5649 5650 #Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint) 5651 5652 Draw Vertices vertices, a triangle mesh, using Clip and Matrix. 5653 If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint 5654 contains Shader, Blend_Mode mode combines Vertices_Colors with Shader. 5655 5656 #Param vertices triangle mesh to draw ## 5657 #Param mode combines Vertices_Colors with Shader, if both are present ## 5658 #Param paint specifies the Shader, used as Vertices texture, may be nullptr ## 5659 5660 #Example 5661 void draw(SkCanvas* canvas) { 5662 SkPaint paint; 5663 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } }; 5664 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } }; 5665 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 5666 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4, 5667 SkShader::kClamp_TileMode)); 5668 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 5669 SK_ARRAY_COUNT(points), points, texs, colors); 5670 canvas->drawVertices(vertices.get(), SkBlendMode::kDarken, paint); 5671 } 5672 ## 5673 5674 #SeeAlso drawPatch drawPicture 5675 5676 ## 5677 5678 # ------------------------------------------------------------------------------ 5679 5680 #Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 5681 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint) 5682 #Line # draws Coons_Patch ## 5683 5684 Draws a Coons_Patch: the interpolation of four cubics with shared corners, 5685 associating a color, and optionally a texture coordinate, with each corner. 5686 5687 Coons_Patch uses Clip and Matrix, paint Shader, Color_Filter, 5688 Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated 5689 as Coons_Patch texture; Blend_Mode mode combines Color colors and Shader if 5690 both are provided. 5691 5692 Point array cubics specifies four Cubics starting at the top-left corner, 5693 in clockwise order, sharing every fourth point. The last Cubic ends at the 5694 first point. 5695 5696 Color array color associates colors with corners in top-left, top-right, 5697 bottom-right, bottom-left order. 5698 5699 If paint contains Shader, Point array texCoords maps Shader as texture to 5700 corners in top-left, top-right, bottom-right, bottom-left order. 5701 5702 #Param cubics Path_Cubic array, sharing common points ## 5703 #Param colors Color array, one for each corner ## 5704 #Param texCoords Point array of texture coordinates, mapping Shader to corners; 5705 may be nullptr 5706 #Param ## 5707 #Param mode Blend_Mode for colors, and for Shader if paint has one ## 5708 #Param paint Shader, Color_Filter, Blend_Mode, used to draw ## 5709 5710 #Example 5711 #Image 5 5712 void draw(SkCanvas* canvas) { 5713 // SkBitmap source = cmbkygk; 5714 SkPaint paint; 5715 paint.setFilterQuality(kLow_SkFilterQuality); 5716 paint.setAntiAlias(true); 5717 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 }, 5718 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 }, 5719 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 }, 5720 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ }; 5721 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff }; 5722 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} }; 5723 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode, 5724 SkShader::kClamp_TileMode, nullptr)); 5725 canvas->scale(15, 15); 5726 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) { 5727 canvas->drawPatch(cubics, colors, texCoords, blend, paint); 5728 canvas->translate(4, 4); 5729 } 5730 } 5731 ## 5732 5733 #ToDo can patch use image filter? ## 5734 #SeeAlso SeeAlso drawVertices drawPicture 5735 5736 ## 5737 5738 # ------------------------------------------------------------------------------ 5739 5740 #Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 5741 const SkPoint texCoords[4], const SkPaint& paint) 5742 5743 Draws Cubic Coons_Patch: the interpolation of four cubics with shared corners, 5744 associating a color, and optionally a texture coordinate, with each corner. 5745 5746 Coons_Patch uses Clip and Matrix, paint Shader, Color_Filter, 5747 Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated 5748 as Coons_Patch texture; Blend_Mode mode combines Color colors and Shader if 5749 both are provided. 5750 5751 Point array cubics specifies four Cubics starting at the top-left corner, 5752 in clockwise order, sharing every fourth point. The last Cubic ends at the 5753 first point. 5754 5755 Color array color associates colors with corners in top-left, top-right, 5756 bottom-right, bottom-left order. 5757 5758 If paint contains Shader, Point array texCoords maps Shader as texture to 5759 corners in top-left, top-right, bottom-right, bottom-left order. 5760 5761 #Param cubics Path_Cubic array, sharing common points ## 5762 #Param colors Color array, one for each corner ## 5763 #Param texCoords Point array of texture coordinates, mapping Shader to corners; 5764 may be nullptr 5765 #Param ## 5766 #Param paint Shader, Color_Filter, Blend_Mode, used to draw ## 5767 5768 #Example 5769 void draw(SkCanvas* canvas) { 5770 SkPaint paint; 5771 paint.setAntiAlias(true); 5772 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 }, 5773 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 }, 5774 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 }, 5775 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ }; 5776 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 5777 canvas->scale(30, 30); 5778 canvas->drawPatch(cubics, colors, nullptr, paint); 5779 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f}, 5780 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f}, 5781 {0.5f,3.2f} }; 5782 paint.setTextSize(18.f / 30); 5783 paint.setTextAlign(SkPaint::kCenter_Align); 5784 for (int i = 0; i< 10; ++i) { 5785 char digit = '0' + i; 5786 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint); 5787 } 5788 canvas->drawString("10", text[10].fX, text[10].fY, paint); 5789 canvas->drawString("11", text[11].fX, text[11].fY, paint); 5790 paint.setStyle(SkPaint::kStroke_Style); 5791 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint); 5792 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint); 5793 } 5794 ## 5795 5796 #Example 5797 #Image 6 5798 void draw(SkCanvas* canvas) { 5799 // SkBitmap source = checkerboard; 5800 SkPaint paint; 5801 paint.setFilterQuality(kLow_SkFilterQuality); 5802 paint.setAntiAlias(true); 5803 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 }, 5804 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 }, 5805 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 }, 5806 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ }; 5807 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } }; 5808 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode, 5809 SkShader::kClamp_TileMode, nullptr)); 5810 canvas->scale(30, 30); 5811 canvas->drawPatch(cubics, nullptr, texCoords, paint); 5812 } 5813 ## 5814 5815 #ToDo can patch use image filter? ## 5816 #SeeAlso SeeAlso drawVertices drawPicture 5817 5818 ## 5819 5820 # ------------------------------------------------------------------------------ 5821 5822 #Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 5823 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect, 5824 const SkPaint* paint) 5825 #Line # draws sprites using Clip, Matrix, and Paint ## 5826 5827 Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint. 5828 paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode 5829 to draw, if present. For each entry in the array, Rect tex locates sprite in 5830 atlas, and RSXform xform transforms it into destination space. 5831 5832 xform, text, and colors if present, must contain count entries. 5833 Optional colors are applied for each sprite using Blend_Mode. 5834 Optional cullRect is a conservative bounds of all transformed sprites. 5835 If cullRect is outside of Clip, canvas can skip drawing. 5836 5837 #Param atlas Image containing sprites ## 5838 #Param xform RSXform mappings for sprites in atlas ## 5839 #Param tex Rect locations of sprites in atlas ## 5840 #Param colors one per sprite, blended with sprite using Blend_Mode; may be nullptr ## 5841 #Param count number of sprites to draw ## 5842 #Param mode Blend_Mode combining colors and sprites ## 5843 #Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ## 5844 #Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ## 5845 5846 #Example 5847 #Image 3 5848 void draw(SkCanvas* canvas) { 5849 // SkBitmap source = mandrill; 5850 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } }; 5851 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; 5852 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf }; 5853 const SkImage* imagePtr = image.get(); 5854 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr); 5855 } 5856 ## 5857 5858 #SeeAlso drawBitmap drawImage 5859 5860 ## 5861 5862 # ------------------------------------------------------------------------------ 5863 5864 #Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[], 5865 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect, 5866 const SkPaint* paint) 5867 5868 Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint. 5869 paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode 5870 to draw, if present. For each entry in the array, Rect tex locates sprite in 5871 atlas, and RSXform xform transforms it into destination space. 5872 5873 xform, text, and colors if present, must contain count entries. 5874 Optional colors is applied for each sprite using Blend_Mode. 5875 Optional cullRect is a conservative bounds of all transformed sprites. 5876 If cullRect is outside of Clip, canvas can skip drawing. 5877 5878 #Param atlas Image containing sprites ## 5879 #Param xform RSXform mappings for sprites in atlas ## 5880 #Param tex Rect locations of sprites in atlas ## 5881 #Param colors one per sprite, blended with sprite using Blend_Mode; may be nullptr ## 5882 #Param count number of sprites to draw ## 5883 #Param mode Blend_Mode combining colors and sprites ## 5884 #Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ## 5885 #Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ## 5886 5887 #Example 5888 #Image 3 5889 void draw(SkCanvas* canvas) { 5890 // SkBitmap source = mandrill; 5891 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } }; 5892 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; 5893 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf }; 5894 SkPaint paint; 5895 paint.setAlpha(127); 5896 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint); 5897 } 5898 ## 5899 5900 #ToDo bug in example on cpu side, gpu looks ok ## 5901 5902 #SeeAlso drawBitmap drawImage 5903 5904 ## 5905 5906 # ------------------------------------------------------------------------------ 5907 5908 #Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count, 5909 const SkRect* cullRect, const SkPaint* paint) 5910 5911 Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint. 5912 paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode 5913 to draw, if present. For each entry in the array, Rect tex locates sprite in 5914 atlas, and RSXform xform transforms it into destination space. 5915 5916 xform and text must contain count entries. 5917 Optional cullRect is a conservative bounds of all transformed sprites. 5918 If cullRect is outside of Clip, canvas can skip drawing. 5919 5920 #Param atlas Image containing sprites ## 5921 #Param xform RSXform mappings for sprites in atlas ## 5922 #Param tex Rect locations of sprites in atlas ## 5923 #Param count number of sprites to draw ## 5924 #Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ## 5925 #Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ## 5926 5927 #Example 5928 #Image 3 5929 void draw(SkCanvas* canvas) { 5930 // sk_sp<SkImage> image = mandrill; 5931 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } }; 5932 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; 5933 const SkImage* imagePtr = image.get(); 5934 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr); 5935 } 5936 ## 5937 5938 #SeeAlso drawBitmap drawImage 5939 5940 ## 5941 5942 # ------------------------------------------------------------------------------ 5943 5944 #Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[], 5945 int count, const SkRect* cullRect, const SkPaint* paint) 5946 5947 Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint. 5948 paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode 5949 to draw, if present. For each entry in the array, Rect tex locates sprite in 5950 atlas, and RSXform xform transforms it into destination space. 5951 5952 xform and text must contain count entries. 5953 Optional cullRect is a conservative bounds of all transformed sprites. 5954 If cullRect is outside of Clip, canvas can skip drawing. 5955 5956 #Param atlas Image containing sprites ## 5957 #Param xform RSXform mappings for sprites in atlas ## 5958 #Param tex Rect locations of sprites in atlas ## 5959 #Param count number of sprites to draw ## 5960 #Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ## 5961 #Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ## 5962 5963 #Example 5964 #Image 3 5965 void draw(SkCanvas* canvas) { 5966 // sk_sp<SkImage> image = mandrill; 5967 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } }; 5968 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } }; 5969 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr); 5970 } 5971 ## 5972 5973 #SeeAlso drawBitmap drawImage 5974 5975 ## 5976 5977 # ------------------------------------------------------------------------------ 5978 5979 #Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr) 5980 5981 #Line # draws Drawable, encapsulated drawing commands ## 5982 Draw Drawable drawable using Clip and Matrix, concatenated with 5983 optional matrix. 5984 5985 If Canvas has an asynchronous implementation, as is the case 5986 when it is recording into Picture, then drawable will be referenced, 5987 so that SkDrawable::draw() can be called when the operation is finalized. To force 5988 immediate drawing, call SkDrawable::draw() instead. 5989 5990 #Param drawable custom struct encapsulating drawing commands ## 5991 #Param matrix transformation applied to drawing; may be nullptr ## 5992 5993 #Example 5994 #Height 100 5995 #Function 5996 struct MyDrawable : public SkDrawable { 5997 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); } 5998 5999 void onDraw(SkCanvas* canvas) override { 6000 SkPath path; 6001 path.conicTo(10, 90, 50, 90, 0.9f); 6002 SkPaint paint; 6003 paint.setColor(SK_ColorBLUE); 6004 canvas->drawRect(path.getBounds(), paint); 6005 paint.setAntiAlias(true); 6006 paint.setColor(SK_ColorWHITE); 6007 canvas->drawPath(path, paint); 6008 } 6009 }; 6010 6011 #Function ## 6012 void draw(SkCanvas* canvas) { 6013 sk_sp<SkDrawable> drawable(new MyDrawable); 6014 SkMatrix matrix; 6015 matrix.setTranslate(10, 10); 6016 canvas->drawDrawable(drawable.get(), &matrix); 6017 } 6018 ## 6019 6020 #SeeAlso SkDrawable drawPicture 6021 6022 ## 6023 6024 # ------------------------------------------------------------------------------ 6025 6026 #Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y) 6027 6028 Draw Drawable drawable using Clip and Matrix, offset by (x, y). 6029 6030 If Canvas has an asynchronous implementation, as is the case 6031 when it is recording into Picture, then drawable will be referenced, 6032 so that SkDrawable::draw() can be called when the operation is finalized. To force 6033 immediate drawing, call SkDrawable::draw() instead. 6034 6035 #Param drawable custom struct encapsulating drawing commands ## 6036 #Param x offset into Canvas writable pixels in x ## 6037 #Param y offset into Canvas writable pixels in y ## 6038 6039 #Example 6040 #Height 100 6041 #Function 6042 struct MyDrawable : public SkDrawable { 6043 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); } 6044 6045 void onDraw(SkCanvas* canvas) override { 6046 SkPath path; 6047 path.conicTo(10, 90, 50, 90, 0.9f); 6048 SkPaint paint; 6049 paint.setColor(SK_ColorBLUE); 6050 canvas->drawRect(path.getBounds(), paint); 6051 paint.setAntiAlias(true); 6052 paint.setColor(SK_ColorWHITE); 6053 canvas->drawPath(path, paint); 6054 } 6055 }; 6056 6057 #Function ## 6058 void draw(SkCanvas* canvas) { 6059 sk_sp<SkDrawable> drawable(new MyDrawable); 6060 canvas->drawDrawable(drawable.get(), 10, 10); 6061 } 6062 ## 6063 6064 #SeeAlso SkDrawable drawPicture 6065 6066 ## 6067 6068 # ------------------------------------------------------------------------------ 6069 6070 #Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value) 6071 6072 #Line # associates a Rect with a key-value pair ## 6073 Associate Rect on Canvas when an annotation; a key-value pair, where the key is 6074 a null-terminated utf8 string, and optional value is stored as Data. 6075 6076 Only some canvas implementations, such as recording to Picture, or drawing to 6077 Document_PDF, use annotations. 6078 6079 #Param rect Rect extent of canvas to annotate ## 6080 #Param key string used for lookup ## 6081 #Param value data holding value stored in annotation ## 6082 6083 #Example 6084 #Height 1 6085 const char text[] = "Click this link!"; 6086 SkRect bounds; 6087 SkPaint paint; 6088 paint.setTextSize(40); 6089 (void)paint.measureText(text, strlen(text), &bounds); 6090 const char url[] = "https://www.google.com/"; 6091 sk_sp<SkData> urlData(SkData::MakeWithCString(url)); 6092 canvas->drawAnnotation(bounds, "url_key", urlData.get()); 6093 ## 6094 6095 #SeeAlso SkPicture SkDocument 6096 6097 ## 6098 6099 # ------------------------------------------------------------------------------ 6100 6101 #Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) 6102 6103 Associate Rect on Canvas when an annotation; a key-value pair, where the key is 6104 a null-terminated utf8 string, and optional value is stored as Data. 6105 6106 Only some canvas implementations, such as recording to Picture, or drawing to 6107 Document_PDF, use annotations. 6108 6109 #Param rect Rect extent of canvas to annotate ## 6110 #Param key string used for lookup ## 6111 #Param value data holding value stored in annotation ## 6112 6113 #Example 6114 #Height 1 6115 const char text[] = "Click this link!"; 6116 SkRect bounds; 6117 SkPaint paint; 6118 paint.setTextSize(40); 6119 (void)paint.measureText(text, strlen(text), &bounds); 6120 const char url[] = "https://www.google.com/"; 6121 sk_sp<SkData> urlData(SkData::MakeWithCString(url)); 6122 canvas->drawAnnotation(bounds, "url_key", urlData.get()); 6123 ## 6124 6125 #SeeAlso SkPicture SkDocument 6126 6127 ## 6128 6129 #Method SkDrawFilter* getDrawFilter() const 6130 6131 #Line # legacy; to be deprecated ## 6132 Legacy call to be deprecated. 6133 6134 #Deprecated 6135 ## 6136 6137 ## 6138 6139 #Method virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) 6140 6141 #Line # legacy; to be deprecated ## 6142 Legacy call to be deprecated. 6143 6144 #Deprecated 6145 ## 6146 6147 ## 6148 6149 # ------------------------------------------------------------------------------ 6150 6151 #Method virtual bool isClipEmpty() const 6152 6153 #Line # returns if Clip is empty ## 6154 Returns true if Clip is empty; that is, nothing will draw. 6155 6156 May do work when called; it should not be called 6157 more often than needed. However, once called, subsequent calls perform no 6158 work until Clip changes. 6159 6160 #Return true if Clip is empty ## 6161 6162 #Example 6163 void draw(SkCanvas* canvas) { 6164 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not"); 6165 SkPath path; 6166 canvas->clipPath(path); 6167 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not"); 6168 } 6169 #StdOut 6170 clip is not empty 6171 clip is empty 6172 ## 6173 ## 6174 6175 #SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds 6176 6177 ## 6178 6179 # ------------------------------------------------------------------------------ 6180 6181 #Method virtual bool isClipRect() const 6182 6183 #Line # returns if Clip is Rect and not empty ## 6184 Returns true if Clip is Rect and not empty. 6185 Returns false if the clip is empty, or if it is not Rect. 6186 6187 #Return true if Clip is Rect and not empty ## 6188 6189 #Example 6190 void draw(SkCanvas* canvas) { 6191 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not"); 6192 canvas->clipRect({0, 0, 0, 0}); 6193 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not"); 6194 } 6195 #StdOut 6196 clip is rect 6197 clip is not rect 6198 ## 6199 ## 6200 6201 #SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds 6202 6203 ## 6204 6205 #Class SkCanvas ## 6206 6207 #Topic Canvas ## 6208