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