1 #Topic Canvas 2 #Alias Canvas_Reference ## 3 4 #Class SkCanvas 5 6 #Code 7 #Populate 8 ## 9 10 Canvas provides an interface for drawing, and how the drawing is clipped and transformed. 11 Canvas contains a stack of Matrix and Clip values. 12 13 Canvas and Paint together provide the state to draw into Surface or Device. 14 Each Canvas draw call transforms the geometry of the object by the concatenation of all 15 Matrix values in the stack. The transformed geometry is clipped by the intersection 16 of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing 17 state such as Color, Typeface, text size, stroke width, Shader and so on. 18 19 To draw to a pixel-based destination, create Raster_Surface or GPU_Surface. 20 Request Canvas from Surface to obtain the interface to draw. 21 Canvas generated by Raster_Surface draws to memory visible to the CPU. 22 Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU. 23 24 To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder. 25 Document based Canvas and other Canvas subclasses reference Device describing the 26 destination. 27 28 Canvas can be constructed to draw to Bitmap without first creating Raster_Surface. 29 This approach may be deprecated in the future. 30 31 Canvas may be created directly when no Surface is required; some Canvas methods 32 implicitly create Raster_Surface. 33 34 # ------------------------------------------------------------------------------ 35 36 #Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels, 37 size_t rowBytes, 38 const SkSurfaceProps* props = nullptr) 39 #In Constructors 40 #Line # creates from SkImageInfo and Pixel_Storage ## 41 #Populate 42 43 #Example 44 #Description 45 Allocates a three by three bitmap, clears it to white, and draws a black pixel 46 in the center. 47 ## 48 void draw(SkCanvas* ) { 49 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied 50 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row 51 const size_t size = info.computeMinByteSize(); // bytes used by all rows 52 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels 53 SkPMColor* pixels = storage.get(); // get pointer to allocated storage 54 // create a SkCanvas backed by a raster device, and delete it when the 55 // function goes out of scope. 56 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes); 57 canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order 58 canvas->flush(); // ensure that pixels are cleared 59 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary 60 SkPaint paint; // by default, draws black 61 canvas->drawPoint(1, 1, paint); // draw in the center 62 canvas->flush(); // ensure that point was drawn 63 for (int y = 0; y < info.height(); ++y) { 64 for (int x = 0; x < info.width(); ++x) { 65 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); 66 } 67 SkDebugf("\n"); 68 } 69 } 70 #StdOut 71 --- 72 -x- 73 --- 74 ## 75 ## 76 77 #SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect 78 79 ## 80 81 # ------------------------------------------------------------------------------ 82 83 #Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels, 84 size_t rowBytes) 85 #In Constructors 86 #Line # creates from image data and Pixel_Storage ## 87 #Populate 88 89 #Example 90 #Description 91 Allocates a three by three bitmap, clears it to white, and draws a black pixel 92 in the center. 93 ## 94 void draw(SkCanvas* ) { 95 const int width = 3; 96 const int height = 3; 97 SkPMColor pixels[height][width]; // allocate a 3 by 3 Premultiplied bitmap on the stack 98 // create a SkCanvas backed by a raster device, and delete it when the 99 // function goes out of scope. 100 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32( 101 width, 102 height, 103 pixels[0], // top-left of the bitmap 104 sizeof(pixels[0])); // byte width of the each row 105 // write a Premultiplied value for white into all pixels in the bitmap 106 canvas->clear(SK_ColorWHITE); 107 SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary 108 SkPaint paint; // by default, draws black 109 canvas->drawPoint(1, 1, paint); // draw in the center 110 canvas->flush(); // ensure that pixels is ready to be read 111 for (int y = 0; y < height; ++y) { 112 for (int x = 0; x < width; ++x) { 113 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x'); 114 } 115 SkDebugf("\n"); 116 } 117 } 118 #StdOut 119 --- 120 -x- 121 --- 122 ## 123 ## 124 125 #SeeAlso MakeRasterDirect SkSurface::MakeRasterDirect SkImageInfo::MakeN32Premul 126 127 ## 128 129 # ------------------------------------------------------------------------------ 130 131 #Method SkCanvas() 132 133 #Line # creates with no Surface, no dimensions ## 134 #Populate 135 136 #Example 137 138 #Description 139 Passes a placeholder to a function that requires one. 140 ## 141 142 #Function 143 static void check_for_rotated_ctm(const SkCanvas* canvas) { 144 const SkMatrix& matrix = canvas->getTotalMatrix(); 145 SkDebugf("rect stays rect is %s\n", matrix.rectStaysRect() ? "true" : "false"); 146 } 147 148 ## 149 void draw(SkCanvas* canvas) { 150 check_for_rotated_ctm(canvas); 151 canvas->rotate(30); 152 check_for_rotated_ctm(canvas); 153 154 SkCanvas defaultCanvas; 155 check_for_rotated_ctm(&defaultCanvas); 156 } 157 158 #StdOut 159 rect stays rect is true 160 rect stays rect is false 161 rect stays rect is true 162 ## 163 ## 164 165 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 166 167 ## 168 169 # ------------------------------------------------------------------------------ 170 171 #Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr) 172 173 #Line # creates with no Surface, set dimensions, Surface_Properties ## 174 #Populate 175 176 #Example 177 SkCanvas canvas(10, 20); // 10 units wide, 20 units high 178 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device 179 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not"); 180 181 #StdOut 182 canvas is empty 183 ## 184 ## 185 186 #SeeAlso MakeRasterDirect SkSurfaceProps SkPixelGeometry SkCreateColorSpaceXformCanvas 187 188 ## 189 190 # ------------------------------------------------------------------------------ 191 192 #Method explicit SkCanvas(const SkBitmap& bitmap) 193 194 #Line # uses existing Bitmap ## 195 #Populate 196 197 #Example 198 #Description 199 The actual output depends on the installed fonts. 200 ## 201 SkBitmap bitmap; 202 // create a bitmap 5 wide and 11 high 203 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11)); 204 SkCanvas canvas(bitmap); 205 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order 206 SkPixmap pixmap; // provides guaranteed access to the drawn pixels 207 if (!canvas.peekPixels(&pixmap)) { 208 SkDebugf("peekPixels should never fail.\n"); 209 } 210 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap 211 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary 212 SkPaint paint; // by default, draws black, 12 point text 213 canvas.drawString("!", 1, 10, SkFont(), paint); // 1 char at baseline (1, 10) 214 for (int y = 0; y < bitmap.height(); ++y) { 215 for (int x = 0; x < bitmap.width(); ++x) { 216 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); 217 } 218 SkDebugf("\n"); 219 } 220 221 #StdOut 222 ----- 223 ---x- 224 ---x- 225 ---x- 226 ---x- 227 ---x- 228 ---x- 229 ----- 230 ---x- 231 ---x- 232 ----- 233 #StdOut ## 234 ## 235 236 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 237 238 ## 239 240 # ------------------------------------------------------------------------------ 241 242 #Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) 243 244 #Line # uses existing Bitmap and Surface_Properties ## 245 #Populate 246 247 #Example 248 #Description 249 The actual output depends on the installed fonts. 250 ## 251 SkBitmap bitmap; 252 // create a bitmap 5 wide and 11 high 253 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11)); 254 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); 255 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order 256 SkPixmap pixmap; // provides guaranteed access to the drawn pixels 257 if (!canvas.peekPixels(&pixmap)) { 258 SkDebugf("peekPixels should never fail.\n"); 259 } 260 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap 261 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary 262 SkPaint paint; // by default, draws black, 12 point text 263 canvas.drawString("!", 1, 10, SkFont(), paint); // 1 char at baseline (1, 10) 264 for (int y = 0; y < bitmap.height(); ++y) { 265 for (int x = 0; x < bitmap.width(); ++x) { 266 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); 267 } 268 SkDebugf("\n"); 269 } 270 271 #StdOut 272 ----- 273 ---x- 274 ---x- 275 ---x- 276 ---x- 277 ---x- 278 ---x- 279 ----- 280 ---x- 281 ---x- 282 ----- 283 #StdOut ## 284 ## 285 286 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas 287 288 ## 289 290 # ------------------------------------------------------------------------------ 291 292 #Method virtual ~SkCanvas() 293 294 #Line # draws saved Layers, frees resources ## 295 #Populate 296 297 #Example 298 #Description 299 Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional 300 drawing surface that blends with the bitmap. When Layer goes out of 301 scope, Layer destructor is called. The saved Layer is restored, drawing 302 transparent letters. 303 ## 304 void draw(SkCanvas* canvas) { 305 SkBitmap bitmap; 306 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200)); 307 { 308 SkCanvas offscreen(bitmap); 309 SkPaint paint; 310 SkFont font(nullptr, 100); 311 offscreen.drawString("ABC", 20, 160, font, paint); 312 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192); 313 offscreen.saveLayerAlpha(&layerBounds, 128); 314 offscreen.clear(SK_ColorWHITE); 315 offscreen.drawString("DEF", 20, 160, font, paint); 316 } 317 canvas->drawBitmap(bitmap, 0, 0, nullptr); 318 } 319 ## 320 321 #SeeAlso State_Stack 322 323 ## 324 325 # ------------------------------------------------------------------------------ 326 #Subtopic Property 327 #Line # metrics and attributes ## 328 ## 329 330 #Method SkMetaData& getMetaData() 331 #In Property 332 #In Utility 333 #Line # associates additional data with the canvas ## 334 #Populate 335 336 #Example 337 const char* kHelloMetaData = "HelloMetaData"; 338 SkCanvas canvas; 339 SkMetaData& metaData = canvas.getMetaData(); 340 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData)); 341 metaData.setString(kHelloMetaData, "Hello!"); 342 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData)); 343 metaData.removeString(kHelloMetaData); 344 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData)); 345 346 #StdOut 347 before: (null) 348 during: Hello! 349 after: (null) 350 #StdOut ## 351 ## 352 353 #SeeAlso SkMetaData 354 355 ## 356 357 # ------------------------------------------------------------------------------ 358 359 #Method SkImageInfo imageInfo() const 360 #In Property 361 #Line # returns Image_Info for Canvas ## 362 #Populate 363 364 #Example 365 SkCanvas emptyCanvas; 366 SkImageInfo canvasInfo = emptyCanvas.imageInfo(); 367 SkImageInfo emptyInfo; 368 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!'); 369 370 #StdOut 371 emptyInfo == canvasInfo 372 ## 373 ## 374 375 #SeeAlso SkImageInfo MakeRasterDirect makeSurface 376 377 ## 378 379 # ------------------------------------------------------------------------------ 380 381 #Method bool getProps(SkSurfaceProps* props) const 382 #In Property 383 #Line # copies Surface_Properties if available ## 384 #Populate 385 386 #Example 387 SkBitmap bitmap; 388 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry)); 389 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); 390 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry())); 391 if (!canvas.getProps(&surfaceProps)) { 392 SkDebugf("getProps failed unexpectedly.\n"); 393 } 394 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry())); 395 396 #StdOut 397 isRGB:0 398 isRGB:1 399 #StdOut ## 400 ## 401 402 #SeeAlso SkSurfaceProps makeSurface 403 404 ## 405 406 # ------------------------------------------------------------------------------ 407 #Subtopic Utility 408 #Line # rarely called management functions ## 409 ## 410 411 #Method void flush() 412 #In Utility 413 #Line # triggers execution of all pending draw operations ## 414 #Populate 415 416 #NoExample 417 ## 418 419 #SeeAlso peekPixels SkSurface::flush GrContext::flush GrContext::abandonContext 420 421 ## 422 423 # ------------------------------------------------------------------------------ 424 425 #Method virtual SkISize getBaseLayerSize() const 426 #In Property 427 #Line # returns size of base Layer in global coordinates ## 428 #Populate 429 430 #Example 431 SkBitmap bitmap; 432 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30)); 433 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); 434 canvas.clipRect(SkRect::MakeWH(10, 40)); 435 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds(); 436 if (clipDeviceBounds.isEmpty()) { 437 SkDebugf("Empty clip bounds is unexpected!\n"); 438 } 439 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height()); 440 SkISize baseLayerSize = canvas.getBaseLayerSize(); 441 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height()); 442 443 #StdOut 444 clip=10,30 445 size=20,30 446 ## 447 ## 448 449 #ToDo is this the same as the width and height of surface? ## 450 451 #SeeAlso getDeviceClipBounds 452 453 ## 454 455 # ------------------------------------------------------------------------------ 456 457 #Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr) 458 #In Constructors 459 #Line # creates Surface matching SkImageInfo and SkSurfaceProps ## 460 #Populate 461 462 #Example 463 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6); 464 SkCanvas* smallCanvas = surface->getCanvas(); 465 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4); 466 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo); 467 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!'); 468 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height()); 469 470 #StdOut 471 compatible != nullptr 472 size = 3, 4 473 ## 474 ## 475 476 #SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps 477 478 ## 479 480 # ------------------------------------------------------------------------------ 481 482 #Method virtual GrContext* getGrContext() 483 #In Property 484 #Line # returns GPU_Context of the GPU_Surface ## 485 #Populate 486 487 #Example 488 void draw(SkCanvas* canvas) { 489 if (canvas->getGrContext()) { 490 canvas->clear(SK_ColorRED); 491 } else { 492 canvas->clear(SK_ColorBLUE); 493 } 494 } 495 ## 496 497 #ToDo fiddle should show both CPU and GPU out ## 498 499 #SeeAlso GrContext 500 501 ## 502 503 # ------------------------------------------------------------------------------ 504 505 #Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr) 506 #In Utility 507 #In Property 508 #Line # returns writable pixel access if available ## 509 #Populate 510 511 #Example 512 void draw(SkCanvas* canvas) { 513 if (canvas->accessTopLayerPixels(nullptr, nullptr)) { 514 canvas->clear(SK_ColorRED); 515 } else { 516 canvas->clear(SK_ColorBLUE); 517 } 518 } 519 ## 520 521 #Example 522 #Description 523 Draws "ABC" on the device. Then draws "DEF" in Layer, and reads 524 Layer to add a large dotted "DEF". Finally blends Layer with the 525 device. 526 527 The Layer and blended result appear on the CPU and GPU but the large dotted 528 "DEF" appear only on the CPU. 529 ## 530 void draw(SkCanvas* canvas) { 531 SkPaint paint; 532 SkFont font(nullptr, 100); 533 canvas->drawString("ABC", 20, 160, font, paint); 534 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192); 535 canvas->saveLayerAlpha(&layerBounds, 128); 536 canvas->clear(SK_ColorWHITE); 537 canvas->drawString("DEF", 20, 160, font, paint); 538 SkImageInfo imageInfo; 539 size_t rowBytes; 540 SkIPoint origin; 541 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin); 542 if (access) { 543 int h = imageInfo.height(); 544 int v = imageInfo.width(); 545 int rowWords = rowBytes / sizeof(uint32_t); 546 for (int y = 0; y < h; ++y) { 547 int newY = (y - h / 2) * 2 + h / 2; 548 if (newY < 0 || newY >= h) { 549 continue; 550 } 551 for (int x = 0; x < v; ++x) { 552 int newX = (x - v / 2) * 2 + v / 2; 553 if (newX < 0 || newX >= v) { 554 continue; 555 } 556 if (access[y * rowWords + x] == SK_ColorBLACK) { 557 access[newY * rowWords + newX] = SK_ColorGRAY; 558 } 559 } 560 } 561 562 } 563 canvas->restore(); 564 } 565 ## 566 567 #ToDo there are no callers of this that I can find. Deprecate? ## 568 #ToDo fiddle should show both CPU and GPU out ## 569 570 #SeeAlso SkImageInfo SkPixmap 571 572 ## 573 574 # ------------------------------------------------------------------------------ 575 576 #Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const 577 #In Utility 578 #In Property 579 #Line # returns context that tracks Clip and Matrix ## 580 #Populate 581 582 #Example 583 #Description 584 #ToDo ## 585 ## 586 #Function 587 static void DeleteCallback(void*, void* context) { 588 delete (char*) context; 589 } 590 591 class CustomAllocator : public SkRasterHandleAllocator { 592 public: 593 bool allocHandle(const SkImageInfo& info, Rec* rec) override { 594 char* context = new char[4]{'s', 'k', 'i', 'a'}; 595 rec->fReleaseProc = DeleteCallback; 596 rec->fReleaseCtx = context; 597 rec->fHandle = context; 598 rec->fPixels = context; 599 rec->fRowBytes = 4; 600 return true; 601 } 602 603 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override { 604 // apply canvas matrix and clip to custom environment 605 } 606 }; 607 608 ## 609 void draw(SkCanvas* canvas) { 610 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); 611 std::unique_ptr<SkCanvas> c2 = 612 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>( 613 new CustomAllocator()), info); 614 char* context = (char*) c2->accessTopRasterHandle(); 615 SkDebugf("context = %.4s\n", context); 616 617 } 618 #StdOut 619 context = skia 620 ## 621 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ## 622 ## 623 624 #SeeAlso SkRasterHandleAllocator 625 626 ## 627 628 # ------------------------------------------------------------------------------ 629 #Subtopic Pixels 630 #Line # read and write pixel values ## 631 ## 632 633 #Method bool peekPixels(SkPixmap* pixmap) 634 #In Pixels 635 #Line # returns if Canvas has direct access to its pixels ## 636 #Populate 637 638 #Example 639 SkPixmap pixmap; 640 if (canvas->peekPixels(&pixmap)) { 641 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height()); 642 } 643 #StdOut 644 width=256 height=256 645 ## 646 ## 647 648 #SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels 649 650 ## 651 652 # ------------------------------------------------------------------------------ 653 654 #Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 655 int srcX, int srcY) 656 #In Pixels 657 #Line # copies and converts rectangle of pixels from Canvas ## 658 659 Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are 660 ignored. 661 662 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 663 Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()). 664 Copies each readable pixel intersecting both rectangles, without scaling, 665 converting to dstInfo.colorType() and dstInfo.alphaType() if required. 666 667 Pixels are readable when Device is raster, or backed by a GPU. 668 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 669 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 670 class like SkDebugCanvas. 671 672 The destination pixel storage must be allocated by the caller. 673 674 Pixel values are converted only if Color_Type and Alpha_Type 675 do not match. Only pixels within both source and destination rectangles 676 are copied. dstPixels contents outside Rect intersection are unchanged. 677 678 Pass negative values for srcX or srcY to offset pixels across or down destination. 679 680 Does not copy, and returns false if: 681 682 #List 683 # Source and destination rectangles do not intersect. ## 684 # Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ## 685 # Canvas pixels are not readable; for instance, Canvas is document-based. ## 686 # dstRowBytes is too small to contain one row of pixels. ## 687 ## 688 689 #Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ## 690 #Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ## 691 #Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ## 692 #Param srcX offset into readable pixels on x-axis; may be negative ## 693 #Param srcY offset into readable pixels on y-axis; may be negative ## 694 695 #Return true if pixels were copied ## 696 697 #Example 698 #Width 64 699 #Height 64 700 #Description 701 A black circle drawn on a blue background provides an image to copy. 702 readPixels copies one quarter of the canvas into each of the four corners. 703 The copied quarter circles overdraw the original circle. 704 ## 705 canvas->clear(SK_ColorBLUE); 706 SkPaint paint; 707 canvas->drawCircle(32, 32, 28, paint); 708 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType); 709 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height())); 710 sk_bzero(data->writable_data(), info.minRowBytes() * info.height()); 711 for (int x : { 32, -32 } ) { 712 for (int y : { 32, -32 } ) { 713 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y); 714 } 715 } 716 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes()); 717 canvas->drawImage(image, 0, 0); 718 ## 719 720 #Example 721 #Description 722 Canvas returned by Raster_Surface has Premultiplied pixel values. 723 clear() takes Unpremultiplied input with Color_Alpha equal 0x80 724 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha 725 to generate Premultiplied value 0x802B5580. readPixels converts pixel back 726 to Unpremultiplied value 0x8056A9FF, introducing error. 727 ## 728 canvas->clear(0x8055aaff); 729 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) { 730 uint32_t pixel = 0; 731 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType); 732 if (canvas->readPixels(info, &pixel, 4, 0, 0)) { 733 SkDebugf("pixel = %08x\n", pixel); 734 } 735 } 736 737 #StdOut 738 pixel = 802b5580 739 pixel = 8056a9ff 740 ## 741 ## 742 743 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels 744 745 ## 746 747 # ------------------------------------------------------------------------------ 748 749 #Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY) 750 751 Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are 752 ignored. 753 754 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 755 Destination Rect corners are (0, 0) and (pixmap.width(), pixmap.height()). 756 Copies each readable pixel intersecting both rectangles, without scaling, 757 converting to pixmap.colorType() and pixmap.alphaType() if required. 758 759 Pixels are readable when Device is raster, or backed by a GPU. 760 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 761 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 762 class like SkDebugCanvas. 763 764 Caller must allocate pixel storage in pixmap if needed. 765 766 Pixel values are converted only if Color_Type and Alpha_Type 767 do not match. Only pixels within both source and destination Rects 768 are copied. pixmap pixels contents outside Rect intersection are unchanged. 769 770 Pass negative values for srcX or srcY to offset pixels across or down pixmap. 771 772 Does not copy, and returns false if: 773 774 #List 775 # Source and destination rectangles do not intersect. ## 776 # Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ## 777 # Canvas pixels are not readable; for instance, Canvas is document-based. ## 778 # Pixmap pixels could not be allocated. ## 779 # pixmap.rowBytes() is too small to contain one row of pixels. ## 780 ## 781 782 #Param pixmap storage for pixels copied from Canvas ## 783 #Param srcX offset into readable pixels on x-axis; may be negative ## 784 #Param srcY offset into readable pixels on y-axis; may be negative ## 785 786 #Return true if pixels were copied ## 787 788 #Example 789 #Description 790 clear() takes Unpremultiplied input with Color_Alpha equal 0x80 791 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha 792 to generate Premultiplied value 0x802B5580. 793 ## 794 void draw(SkCanvas* canvas) { 795 canvas->clear(0x8055aaff); 796 uint32_t pixels[1] = { 0 }; 797 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4); 798 canvas->readPixels(pixmap, 0, 0); 799 SkDebugf("pixel = %08x\n", pixels[0]); 800 } 801 #StdOut 802 pixel = 802b5580 803 ## 804 ## 805 806 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels 807 808 ## 809 810 # ------------------------------------------------------------------------------ 811 812 #Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY) 813 814 Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are 815 ignored. 816 817 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()). 818 Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()). 819 Copies each readable pixel intersecting both rectangles, without scaling, 820 converting to bitmap.colorType() and bitmap.alphaType() if required. 821 822 Pixels are readable when Device is raster, or backed by a GPU. 823 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage, 824 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 825 class like SkDebugCanvas. 826 827 Caller must allocate pixel storage in bitmap if needed. 828 829 Bitmap values are converted only if Color_Type and Alpha_Type 830 do not match. Only pixels within both source and destination rectangles 831 are copied. Bitmap pixels outside Rect intersection are unchanged. 832 833 Pass negative values for srcX or srcY to offset pixels across or down bitmap. 834 835 Does not copy, and returns false if: 836 837 #List 838 # Source and destination rectangles do not intersect. ## 839 # Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ## 840 # Canvas pixels are not readable; for instance, Canvas is document-based. ## 841 # bitmap pixels could not be allocated. ## 842 # bitmap.rowBytes() is too small to contain one row of pixels. ## 843 ## 844 845 #Param bitmap storage for pixels copied from Canvas ## 846 #Param srcX offset into readable pixels on x-axis; may be negative ## 847 #Param srcY offset into readable pixels on y-axis; may be negative ## 848 849 #Return true if pixels were copied ## 850 851 #Example 852 #Description 853 clear() takes Unpremultiplied input with Color_Alpha equal 0x80 854 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha 855 to generate Premultiplied value 0x802B5580. 856 ## 857 void draw(SkCanvas* canvas) { 858 canvas->clear(0x8055aaff); 859 SkBitmap bitmap; 860 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1)); 861 canvas->readPixels(bitmap, 0, 0); 862 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]); 863 } 864 #StdOut 865 pixel = 802b5580 866 ## 867 ## 868 869 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels 870 871 ## 872 873 # ------------------------------------------------------------------------------ 874 875 #Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y) 876 #In Pixels 877 #Line # copies and converts rectangle of pixels to Canvas ## 878 Copies Rect from pixels to Canvas. Matrix and Clip are ignored. 879 Source Rect corners are (0, 0) and (info.width(), info.height()). 880 Destination Rect corners are (x, y) and 881 (imageInfo().width(), imageInfo().height()). 882 883 Copies each readable pixel intersecting both rectangles, without scaling, 884 converting to imageInfo().colorType() and imageInfo().alphaType() if required. 885 886 Pixels are writable when Device is raster, or backed by a GPU. 887 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage, 888 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 889 class like SkDebugCanvas. 890 891 Pixel values are converted only if Color_Type and Alpha_Type 892 do not match. Only pixels within both source and destination rectangles 893 are copied. Canvas pixels outside Rect intersection are unchanged. 894 895 Pass negative values for x or y to offset pixels to the left or 896 above Canvas pixels. 897 898 Does not copy, and returns false if: 899 900 #List 901 # Source and destination rectangles do not intersect. ## 902 # pixels could not be converted to Canvas imageInfo().colorType() or 903 imageInfo().alphaType(). ## 904 # Canvas pixels are not writable; for instance, Canvas is document-based. ## 905 # rowBytes is too small to contain one row of pixels. ## 906 ## 907 908 #Param info width, height, Color_Type, and Alpha_Type of pixels ## 909 #Param pixels pixels to copy, of size info.height() times rowBytes, or larger ## 910 #Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ## 911 #Param x offset into Canvas writable pixels on x-axis; may be negative ## 912 #Param y offset into Canvas writable pixels on y-axis; may be negative ## 913 914 #Return true if pixels were written to Canvas ## 915 916 #Example 917 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType); 918 for (int y = 0; y < 256; ++y) { 919 uint32_t pixels[256]; 920 for (int x = 0; x < 256; ++x) { 921 pixels[x] = SkColorSetARGB(x, x + y, x, x - y); 922 } 923 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y); 924 } 925 ## 926 927 #SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels 928 929 ## 930 931 # ------------------------------------------------------------------------------ 932 933 #Method bool writePixels(const SkBitmap& bitmap, int x, int y) 934 935 Copies Rect from pixels to Canvas. Matrix and Clip are ignored. 936 Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()). 937 938 Destination Rect corners are (x, y) and 939 (imageInfo().width(), imageInfo().height()). 940 941 Copies each readable pixel intersecting both rectangles, without scaling, 942 converting to imageInfo().colorType() and imageInfo().alphaType() if required. 943 944 Pixels are writable when Device is raster, or backed by a GPU. 945 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage, 946 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility 947 class like SkDebugCanvas. 948 949 Pixel values are converted only if Color_Type and Alpha_Type 950 do not match. Only pixels within both source and destination rectangles 951 are copied. Canvas pixels outside Rect intersection are unchanged. 952 953 Pass negative values for x or y to offset pixels to the left or 954 above Canvas pixels. 955 956 Does not copy, and returns false if: 957 958 #List 959 # Source and destination rectangles do not intersect. ## 960 # bitmap does not have allocated pixels. ## 961 # bitmap pixels could not be converted to Canvas imageInfo().colorType() or 962 imageInfo().alphaType(). ## 963 # Canvas pixels are not writable; for instance, Canvas is document based. ## 964 # bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ## 965 ## 966 967 #Param bitmap contains pixels copied to Canvas ## 968 #Param x offset into Canvas writable pixels in x; may be negative ## 969 #Param y offset into Canvas writable pixels in y; may be negative ## 970 971 #Return true if pixels were written to Canvas ## 972 973 #Example 974 void draw(SkCanvas* canvas) { 975 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2); 976 SkBitmap bitmap; 977 bitmap.setInfo(imageInfo); 978 uint32_t pixels[4]; 979 bitmap.setPixels(pixels); 980 for (int y = 0; y < 256; y += 2) { 981 for (int x = 0; x < 256; x += 2) { 982 pixels[0] = SkColorSetRGB(x, y, x | y); 983 pixels[1] = SkColorSetRGB(x ^ y, y, x); 984 pixels[2] = SkColorSetRGB(x, x & y, y); 985 pixels[3] = SkColorSetRGB(~x, ~y, x); 986 canvas->writePixels(bitmap, x, y); 987 } 988 } 989 } 990 ## 991 992 #SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels 993 994 ## 995 996 # ------------------------------------------------------------------------------ 997 #Subtopic State_Stack 998 #Line # stack of state for hierarchical drawing ## 999 1000 Canvas maintains a stack of state that allows hierarchical drawing, commonly used 1001 to implement windows and views. The initial state has an identity matrix and and 1002 an infinite clip. Even with a wide-open clip, drawing is constrained by the 1003 bounds of the Canvas Surface or Device. 1004 1005 Canvas savable state consists of Clip and Matrix. 1006 Clip describes the area that may be drawn to. 1007 Matrix transforms the geometry. 1008 1009 save(), saveLayer, and saveLayerAlpha 1010 save state and return the depth of the stack. 1011 1012 restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved. 1013 1014 Each state on the stack intersects Clip with the previous Clip, 1015 and concatenates Matrix with the previous Matrix. 1016 The intersected Clip makes the drawing area the same or smaller; 1017 the concatenated Matrix may move the origin and potentially scale or rotate 1018 the coordinate space. 1019 1020 Canvas does not require balancing the state stack but it is a good idea 1021 to do so. Calling save() without restore() will eventually cause Skia to fail; 1022 mismatched save() and restore() create hard to find bugs. 1023 1024 It is not possible to use state to draw outside of the clip defined by the 1025 previous state. 1026 1027 #Example 1028 #Description 1029 Draw to ever smaller clips; then restore drawing to full canvas. 1030 Note that the second clipRect is not permitted to enlarge Clip. 1031 ## 1032 #Height 160 1033 void draw(SkCanvas* canvas) { 1034 SkPaint paint; 1035 canvas->save(); // records stack depth to restore 1036 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip 1037 canvas->clear(SK_ColorRED); // draws to limit of clip 1038 canvas->save(); // records stack depth to restore 1039 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored 1040 canvas->clear(SK_ColorBLUE); // draws to smaller clip 1041 canvas->restore(); // enlarges clip 1042 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn 1043 canvas->restore(); // enlarges clip 1044 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn 1045 } 1046 ## 1047 1048 Each Clip uses the current Matrix for its coordinates. 1049 1050 #Example 1051 #Description 1052 While clipRect is given the same rectangle twice, Matrix makes the second 1053 clipRect draw at half the size of the first. 1054 ## 1055 #Height 128 1056 void draw(SkCanvas* canvas) { 1057 canvas->clipRect(SkRect::MakeWH(100, 100)); 1058 canvas->clear(SK_ColorRED); 1059 canvas->scale(.5, .5); 1060 canvas->clipRect(SkRect::MakeWH(100, 100)); 1061 canvas->clear(SK_ColorBLUE); 1062 } 1063 ## 1064 1065 #SeeAlso save saveLayer saveLayerAlpha restore() restoreToCount 1066 1067 #Method int save() 1068 1069 #In State_Stack 1070 #Line # saves Clip and Matrix on stack ## 1071 #Populate 1072 1073 #Example 1074 #Description 1075 The black square is translated 50 pixels down and to the right. 1076 Restoring Canvas state removes translate() from Canvas stack; 1077 the red square is not translated, and is drawn at the origin. 1078 ## 1079 #Height 100 1080 void draw(SkCanvas* canvas) { 1081 SkPaint paint; 1082 SkRect rect = { 0, 0, 25, 25 }; 1083 canvas->drawRect(rect, paint); 1084 canvas->save(); 1085 canvas->translate(50, 50); 1086 canvas->drawRect(rect, paint); 1087 canvas->restore(); 1088 paint.setColor(SK_ColorRED); 1089 canvas->drawRect(rect, paint); 1090 } 1091 ## 1092 1093 #SeeAlso saveLayer saveLayerAlpha restore restoreToCount 1094 1095 ## 1096 1097 # ------------------------------------------------------------------------------ 1098 1099 #Method void restore() 1100 1101 #In State_Stack 1102 #Line # restores changes to Clip and Matrix, pops save stack ## 1103 #Populate 1104 1105 #Example 1106 void draw(SkCanvas* canvas) { 1107 SkCanvas simple; 1108 SkDebugf("depth = %d\n", simple.getSaveCount()); 1109 simple.restore(); 1110 SkDebugf("depth = %d\n", simple.getSaveCount()); 1111 } 1112 ## 1113 1114 #SeeAlso save saveLayer saveLayerAlpha restoreToCount 1115 1116 ## 1117 1118 # ------------------------------------------------------------------------------ 1119 1120 #Method int getSaveCount() const 1121 1122 #In State_Stack 1123 #Line # returns depth of stack containing Clip and Matrix ## 1124 #Populate 1125 1126 #Example 1127 void draw(SkCanvas* canvas) { 1128 SkCanvas simple; 1129 SkDebugf("depth = %d\n", simple.getSaveCount()); 1130 simple.save(); 1131 SkDebugf("depth = %d\n", simple.getSaveCount()); 1132 simple.restore(); 1133 SkDebugf("depth = %d\n", simple.getSaveCount()); 1134 } 1135 #StdOut 1136 depth = 1 1137 depth = 2 1138 depth = 1 1139 ## 1140 ## 1141 1142 #SeeAlso save restore restoreToCount 1143 1144 ## 1145 1146 # ------------------------------------------------------------------------------ 1147 1148 #Method void restoreToCount(int saveCount) 1149 1150 #In State_Stack 1151 #Line # restores changes to Clip and Matrix to given depth ## 1152 #Populate 1153 1154 #Example 1155 void draw(SkCanvas* canvas) { 1156 SkDebugf("depth = %d\n", canvas->getSaveCount()); 1157 canvas->save(); 1158 canvas->save(); 1159 SkDebugf("depth = %d\n", canvas->getSaveCount()); 1160 canvas->restoreToCount(0); 1161 SkDebugf("depth = %d\n", canvas->getSaveCount()); 1162 } 1163 #StdOut 1164 depth = 1 1165 depth = 3 1166 depth = 1 1167 ## 1168 ## 1169 1170 #SeeAlso restore getSaveCount save 1171 1172 ## 1173 1174 #Subtopic State_Stack ## 1175 1176 # ------------------------------------------------------------------------------ 1177 1178 #Subtopic Layer 1179 #Substitute layer 1180 #Alias Layers 1181 #Substitute layers 1182 ## 1183 #Line # temporary Bitmap to draw into ## 1184 1185 Layer allocates a temporary Bitmap to draw into. When the drawing is 1186 complete, the Bitmap is drawn into the Canvas. 1187 1188 Layer is saved in a stack along with other saved state. When state with a Layer 1189 is restored, the Bitmap is drawn into the previous Layer. 1190 1191 Layer may be initialized with the contents of the previous Layer. When Layer is 1192 restored, its Bitmap can be modified by Paint passed to Layer to apply 1193 Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode. 1194 1195 #Method int saveLayer(const SkRect* bounds, const SkPaint* paint) 1196 1197 #In Layer 1198 #Line # saves Clip and Matrix on stack; creates Layer ## 1199 #Populate 1200 1201 #Example 1202 #Description 1203 Rectangles are blurred by Image_Filter when restore() draws Layer to main 1204 Canvas. 1205 ## 1206 #Height 128 1207 #Function 1208 ###$ 1209 #include "SkBlurImageFilter.h" 1210 $$$# 1211 ## 1212 1213 void draw(SkCanvas* canvas) { 1214 SkPaint paint, blur; 1215 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr)); 1216 canvas->saveLayer(nullptr, &blur); 1217 SkRect rect = { 25, 25, 50, 50}; 1218 canvas->drawRect(rect, paint); 1219 canvas->translate(50, 50); 1220 paint.setColor(SK_ColorRED); 1221 canvas->drawRect(rect, paint); 1222 canvas->restore(); 1223 } 1224 ## 1225 1226 #SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec 1227 1228 ## 1229 1230 #Method int saveLayer(const SkRect& bounds, const SkPaint* paint) 1231 1232 #In Layer 1233 #Populate 1234 1235 #Example 1236 #Description 1237 Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas. 1238 The red rectangle is clipped; it does not fully fit on Layer. 1239 Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides. 1240 ## 1241 #Height 128 1242 #Function 1243 ###$ 1244 #include "SkBlurImageFilter.h" 1245 $$$# 1246 ## 1247 1248 void draw(SkCanvas* canvas) { 1249 SkPaint paint, blur; 1250 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr)); 1251 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur); 1252 SkRect rect = { 25, 25, 50, 50}; 1253 canvas->drawRect(rect, paint); 1254 canvas->translate(50, 50); 1255 paint.setColor(SK_ColorRED); 1256 canvas->drawRect(rect, paint); 1257 canvas->restore(); 1258 } 1259 ## 1260 1261 #SeeAlso save restore saveLayerAlpha SaveLayerRec 1262 1263 ## 1264 1265 #Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) 1266 1267 #In Layer 1268 #Line # saves Clip and Matrix on stack; creates Layer; sets opacity ## 1269 #Populate 1270 1271 #Example 1272 SkPaint paint; 1273 paint.setColor(SK_ColorRED); 1274 canvas->drawCircle(50, 50, 50, paint); 1275 canvas->saveLayerAlpha(nullptr, 128); 1276 paint.setColor(SK_ColorBLUE); 1277 canvas->drawCircle(100, 50, 50, paint); 1278 paint.setColor(SK_ColorGREEN); 1279 paint.setAlpha(128); 1280 canvas->drawCircle(75, 90, 50, paint); 1281 canvas->restore(); 1282 ## 1283 1284 #SeeAlso save restore saveLayer SaveLayerRec 1285 1286 ## 1287 1288 #Enum SaveLayerFlagsSet 1289 #Line # sets SaveLayerRec options ## 1290 #Code 1291 #Populate 1292 ## 1293 1294 1295 #Typedef uint32_t SaveLayerFlags 1296 #Line # options for SaveLayerRec ## 1297 ## 1298 1299 SaveLayerFlags provides options that may be used in any combination in SaveLayerRec, 1300 defining how Layer allocated by saveLayer operates. It may be set to zero or 1301 kInitWithPrevious_SaveLayerFlag. 1302 1303 #Const kInitWithPrevious_SaveLayerFlag 4 1304 #Line # initializes with previous contents ## 1305 Initializes Layer with the contents of the previous Layer. 1306 ## 1307 1308 #Example 1309 #Height 160 1310 #Description 1311 Canvas Layer captures red and blue circles scaled up by four. 1312 scalePaint blends Layer back with transparency. 1313 ## 1314 void draw(SkCanvas* canvas) { 1315 SkPaint redPaint, bluePaint, scalePaint; 1316 redPaint.setColor(SK_ColorRED); 1317 canvas->drawCircle(21, 21, 8, redPaint); 1318 bluePaint.setColor(SK_ColorBLUE); 1319 canvas->drawCircle(31, 21, 8, bluePaint); 1320 SkMatrix matrix; 1321 matrix.setScale(4, 4); 1322 scalePaint.setAlpha(0x40); 1323 scalePaint.setImageFilter( 1324 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr)); 1325 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint, 1326 SkCanvas::kInitWithPrevious_SaveLayerFlag); 1327 canvas->saveLayer(saveLayerRec); 1328 canvas->restore(); 1329 } 1330 ## 1331 1332 #SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec 1333 1334 #Enum ## 1335 1336 #Subtopic SaveLayerRec 1337 #Line # contains the state used to create the Layer ## 1338 1339 #Struct SaveLayerRec 1340 #Line # contains the state used to create the Layer ## 1341 1342 #Code 1343 #Populate 1344 ## 1345 1346 SaveLayerRec contains the state used to create the Layer. 1347 1348 #Member const SkRect* fBounds 1349 #Line # hints at Layer size limit ## 1350 fBounds is used as a hint to limit the size of Layer; may be nullptr. 1351 fBounds suggests but does not define Layer size. To clip drawing to 1352 a specific rectangle, use clipRect. 1353 ## 1354 1355 #Member const SkPaint* fPaint 1356 #Line # modifies overlay ## 1357 fPaint modifies how Layer overlays the prior Layer; may be nullptr. 1358 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and 1359 Mask_Filter affect Layer draw. 1360 ## 1361 1362 #Member const SkImageFilter* fBackdrop 1363 #Line # applies Image_Filter to prior Layer ## 1364 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer; 1365 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the 1366 prior Layer without an Image_Filter. 1367 ## 1368 1369 #Member const SkImage* fClipMask 1370 #Line # clips Layer with Mask_Alpha ## 1371 restore() clips Layer by the Color_Alpha channel of fClipMask when 1372 Layer is copied to Device. fClipMask may be nullptr. . 1373 ## 1374 1375 #Member const SkMatrix* fClipMatrix 1376 #Line # transforms Mask_Alpha used to clip ## 1377 fClipMatrix transforms fClipMask before it clips Layer. If 1378 fClipMask describes a translucent gradient, it may be scaled and rotated 1379 without introducing artifacts. fClipMatrix may be nullptr. 1380 ## 1381 1382 #Member SaveLayerFlags fSaveLayerFlags 1383 #Line # creates with prior Layer contents ## 1384 fSaveLayerFlags are used to create Layer without transparency, 1385 and to create Layer with the ontents of the previous Layer. 1386 ## 1387 1388 #Example 1389 #Height 160 1390 #Description 1391 Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled 1392 up by four. After drawing another red circle without scaling on top, the Layer is 1393 transferred to the main canvas. 1394 ## 1395 void draw(SkCanvas* canvas) { 1396 SkPaint redPaint, bluePaint; 1397 redPaint.setAntiAlias(true); 1398 redPaint.setColor(SK_ColorRED); 1399 canvas->drawCircle(21, 21, 8, redPaint); 1400 bluePaint.setColor(SK_ColorBLUE); 1401 canvas->drawCircle(31, 21, 8, bluePaint); 1402 SkMatrix matrix; 1403 matrix.setScale(4, 4); 1404 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr); 1405 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0); 1406 canvas->saveLayer(saveLayerRec); 1407 canvas->drawCircle(125, 85, 8, redPaint); 1408 canvas->restore(); 1409 } 1410 ## 1411 1412 #Subtopic Constructors 1413 ## 1414 1415 #Method SaveLayerRec() 1416 #Line # constructs SaveLayerRec ## 1417 #Populate 1418 1419 #Example 1420 SkCanvas::SaveLayerRec rec1; 1421 rec1.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag; 1422 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kInitWithPrevious_SaveLayerFlag); 1423 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds 1424 && rec1.fPaint == rec2.fPaint 1425 && rec1.fBackdrop == rec2.fBackdrop 1426 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!'); 1427 #StdOut 1428 rec1 == rec2 1429 ## 1430 ## 1431 1432 #SeeAlso save restore saveLayer saveLayerAlpha 1433 1434 ## 1435 1436 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0) 1437 #Populate 1438 1439 #Example 1440 SkCanvas::SaveLayerRec rec1; 1441 SkCanvas::SaveLayerRec rec2(nullptr, nullptr); 1442 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds 1443 && rec1.fPaint == rec2.fPaint 1444 && rec1.fBackdrop == rec2.fBackdrop 1445 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!'); 1446 #StdOut 1447 rec1 == rec2 1448 ## 1449 ## 1450 1451 #SeeAlso save restore saveLayer saveLayerAlpha 1452 1453 ## 1454 1455 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, 1456 SaveLayerFlags saveLayerFlags) 1457 #Populate 1458 1459 #Example 1460 SkCanvas::SaveLayerRec rec1; 1461 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0); 1462 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds 1463 && rec1.fPaint == rec2.fPaint 1464 && rec1.fBackdrop == rec2.fBackdrop 1465 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!'); 1466 #StdOut 1467 rec1 == rec2 1468 ## 1469 ## 1470 1471 #SeeAlso save restore saveLayer saveLayerAlpha 1472 1473 ## 1474 1475 #Struct ## 1476 1477 #Subtopic ## 1478 1479 #Method int saveLayer(const SaveLayerRec& layerRec) 1480 1481 #In Layer 1482 #Populate 1483 1484 #Example 1485 #Description 1486 The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag. 1487 Next it punches a hole in Layer and restore with SkBlendMode::kPlus. 1488 Where Layer was cleared, the original image will draw unchanged. 1489 Outside of the circle the mandrill is brightened. 1490 ## 1491 #Image 3 1492 // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png"); 1493 canvas->drawImage(image, 0, 0, nullptr); 1494 SkCanvas::SaveLayerRec rec; 1495 SkPaint paint; 1496 paint.setBlendMode(SkBlendMode::kPlus); 1497 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag; 1498 rec.fPaint = &paint; 1499 canvas->saveLayer(rec); 1500 paint.setBlendMode(SkBlendMode::kClear); 1501 canvas->drawCircle(128, 128, 96, paint); 1502 canvas->restore(); 1503 ## 1504 1505 #ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ## 1506 1507 #SeeAlso save restore saveLayer saveLayerAlpha 1508 1509 ## 1510 1511 #Subtopic Layer ## 1512 1513 # ------------------------------------------------------------------------------ 1514 #Subtopic Matrix 1515 #Line # coordinate transformation ## 1516 1517 #Method void translate(SkScalar dx, SkScalar dy) 1518 1519 #In Matrix 1520 #Line # translates Matrix ## 1521 #Populate 1522 1523 #Example 1524 #Height 128 1525 #Description 1526 scale() followed by translate() produces different results from translate() followed 1527 by scale(). 1528 1529 The blue stroke follows translate of (50, 50); a black 1530 fill follows scale of (2, 1/2.f). After restoring the clip, which resets 1531 Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill 1532 follows translate of (50, 50). 1533 ## 1534 void draw(SkCanvas* canvas) { 1535 SkPaint filledPaint; 1536 SkPaint outlinePaint; 1537 outlinePaint.setStyle(SkPaint::kStroke_Style); 1538 outlinePaint.setColor(SK_ColorBLUE); 1539 canvas->save(); 1540 canvas->translate(50, 50); 1541 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28) 1542 canvas->scale(2, 1/2.f); 1543 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2)) 1544 canvas->restore(); 1545 filledPaint.setColor(SK_ColorGRAY); 1546 outlinePaint.setColor(SK_ColorRED); 1547 canvas->scale(2, 1/2.f); 1548 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2) 1549 canvas->translate(50, 50); 1550 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2) 1551 } 1552 ## 1553 1554 #SeeAlso concat() scale() skew() rotate() setMatrix 1555 1556 ## 1557 1558 # ------------------------------------------------------------------------------ 1559 1560 #Method void scale(SkScalar sx, SkScalar sy) 1561 1562 #In Matrix 1563 #Line # scales Matrix ## 1564 #Populate 1565 1566 #Example 1567 #Height 160 1568 void draw(SkCanvas* canvas) { 1569 SkPaint paint; 1570 SkRect rect = { 10, 20, 60, 120 }; 1571 canvas->translate(20, 20); 1572 canvas->drawRect(rect, paint); 1573 canvas->scale(2, .5f); 1574 paint.setColor(SK_ColorGRAY); 1575 canvas->drawRect(rect, paint); 1576 } 1577 ## 1578 1579 #SeeAlso concat() translate() skew() rotate() setMatrix 1580 1581 ## 1582 1583 # ------------------------------------------------------------------------------ 1584 1585 #Method void rotate(SkScalar degrees) 1586 1587 #In Matrix 1588 #Line # rotates Matrix ## 1589 #Populate 1590 1591 #Example 1592 #Description 1593 Draw clock hands at time 5:10. The hour hand and minute hand point up and 1594 are rotated clockwise. 1595 ## 1596 void draw(SkCanvas* canvas) { 1597 SkPaint paint; 1598 paint.setStyle(SkPaint::kStroke_Style); 1599 canvas->translate(128, 128); 1600 canvas->drawCircle(0, 0, 60, paint); 1601 canvas->save(); 1602 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees 1603 canvas->drawLine(0, 0, 0, -50, paint); 1604 canvas->restore(); 1605 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees 1606 canvas->drawLine(0, 0, 0, -30, paint); 1607 } 1608 ## 1609 1610 #SeeAlso concat() translate() skew() scale() setMatrix 1611 1612 ## 1613 1614 # ------------------------------------------------------------------------------ 1615 1616 #Method void rotate(SkScalar degrees, SkScalar px, SkScalar py) 1617 1618 #In Matrix 1619 #Populate 1620 1621 #Example 1622 #Height 192 1623 void draw(SkCanvas* canvas) { 1624 SkPaint paint; 1625 SkFont font(nullptr, 96); 1626 canvas->drawString("A1", 130, 100, font, paint); 1627 canvas->rotate(180, 130, 100); 1628 canvas->drawString("A1", 130, 100, font, paint); 1629 } 1630 ## 1631 1632 #SeeAlso concat() translate() skew() scale() setMatrix 1633 1634 ## 1635 1636 # ------------------------------------------------------------------------------ 1637 1638 #Method void skew(SkScalar sx, SkScalar sy) 1639 1640 #In Matrix 1641 #Line # skews Matrix ## 1642 #Populate 1643 1644 #Example 1645 #Description 1646 Black text mimics an oblique text style by using a negative skew on x-axis 1647 that shifts the geometry to the right as the y-axis values decrease. 1648 Red text uses a positive skew on y-axis to shift the geometry down 1649 as the x-axis values increase. 1650 Blue text combines sx and sy skew to rotate and scale. 1651 ## 1652 SkPaint paint; 1653 SkFont font(nullptr, 128); 1654 canvas->translate(30, 130); 1655 canvas->save(); 1656 canvas->skew(-.5, 0); 1657 canvas->drawString("A1", 0, 0, font, paint); 1658 canvas->restore(); 1659 canvas->save(); 1660 canvas->skew(0, .5); 1661 paint.setColor(SK_ColorRED); 1662 canvas->drawString("A1", 0, 0, font, paint); 1663 canvas->restore(); 1664 canvas->skew(-.5, .5); 1665 paint.setColor(SK_ColorBLUE); 1666 canvas->drawString("A1", 0, 0, font, paint); 1667 ## 1668 1669 #SeeAlso concat() translate() rotate() scale() setMatrix 1670 1671 ## 1672 1673 # ------------------------------------------------------------------------------ 1674 1675 #Method void concat(const SkMatrix& matrix) 1676 1677 #In Matrix 1678 #Line # multiplies Matrix by Matrix ## 1679 #Populate 1680 1681 #Example 1682 void draw(SkCanvas* canvas) { 1683 SkPaint paint; 1684 SkFont font(nullptr, 80); 1685 font.setScaleX(.3); 1686 SkMatrix matrix; 1687 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }}; 1688 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit); 1689 canvas->drawRect(rect[0], paint); 1690 canvas->drawRect(rect[1], paint); 1691 paint.setColor(SK_ColorWHITE); 1692 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint); 1693 canvas->concat(matrix); 1694 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint); 1695 } 1696 ## 1697 1698 #SeeAlso translate() rotate() scale() skew() setMatrix 1699 1700 ## 1701 1702 # ------------------------------------------------------------------------------ 1703 1704 #Method void setMatrix(const SkMatrix& matrix) 1705 1706 #In Matrix 1707 #Line # sets Matrix ## 1708 #Populate 1709 1710 #Example 1711 #Height 128 1712 void draw(SkCanvas* canvas) { 1713 SkPaint paint; 1714 SkFont font; 1715 canvas->scale(4, 6); 1716 canvas->drawString("truth", 2, 10, font, paint); 1717 SkMatrix matrix; 1718 matrix.setScale(2.8f, 6); 1719 canvas->setMatrix(matrix); 1720 canvas->drawString("consequences", 2, 20, font, paint); 1721 } 1722 ## 1723 1724 #SeeAlso resetMatrix concat() translate() rotate() scale() skew() 1725 1726 ## 1727 1728 # ------------------------------------------------------------------------------ 1729 1730 #Method void resetMatrix() 1731 1732 #In Matrix 1733 #Line # resets Matrix to identity ## 1734 #Populate 1735 1736 #Example 1737 #Height 128 1738 void draw(SkCanvas* canvas) { 1739 SkPaint paint; 1740 SkFont font; 1741 canvas->scale(4, 6); 1742 canvas->drawString("truth", 2, 10, font, paint); 1743 canvas->resetMatrix(); 1744 canvas->scale(2.8f, 6); 1745 canvas->drawString("consequences", 2, 20, font, paint); 1746 } 1747 ## 1748 1749 #SeeAlso setMatrix concat() translate() rotate() scale() skew() 1750 1751 ## 1752 1753 # ------------------------------------------------------------------------------ 1754 1755 #Method const SkMatrix& getTotalMatrix() const 1756 1757 #In Matrix 1758 #Line # returns Matrix ## 1759 #Populate 1760 1761 #Example 1762 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false"); 1763 #StdOut 1764 isIdentity true 1765 ## 1766 ## 1767 1768 #SeeAlso setMatrix resetMatrix concat() 1769 1770 ## 1771 1772 #Subtopic Matrix ## 1773 1774 # ------------------------------------------------------------------------------ 1775 #Subtopic Clip 1776 #Line # stack of clipping Paths ## 1777 1778 Clip is built from a stack of clipping paths. Each Path in the 1779 stack can be constructed from one or more Path_Contour elements. The 1780 Path_Contour may be composed of any number of Path_Verb segments. Each 1781 Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed 1782 by Path_Contour. 1783 1784 Clip stack of Path elements successfully restrict the Path area. Each 1785 Path is transformed by Matrix, then intersected with or subtracted from the 1786 prior Clip to form the replacement Clip. Use SkClipOp::kDifference 1787 to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path 1788 with Clip. 1789 1790 A clipping Path may be Anti_Aliased; if Path, after transformation, is 1791 composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels 1792 to either be inside or outside the clip. The fastest drawing has a Aliased, 1793 rectangular clip. 1794 1795 If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring 1796 that drawing blend partially with the destination along the edge. A rotated 1797 rectangular Anti_Aliased clip looks smoother but draws slower. 1798 1799 Clip can combine with Rect and Round_Rect primitives; like 1800 Path, these are transformed by Matrix before they are combined with Clip. 1801 1802 Clip can combine with Region. Region is assumed to be in Device coordinates 1803 and is unaffected by Matrix. 1804 1805 #Example 1806 #Height 90 1807 #Description 1808 Draw a red circle with an Aliased clip and an Anti_Aliased clip. 1809 Use an image filter to zoom into the pixels drawn. 1810 The edge of the Aliased clip fully draws pixels in the red circle. 1811 The edge of the Anti_Aliased clip partially draws pixels in the red circle. 1812 ## 1813 SkPaint redPaint, scalePaint; 1814 redPaint.setAntiAlias(true); 1815 redPaint.setColor(SK_ColorRED); 1816 canvas->save(); 1817 for (bool antialias : { false, true } ) { 1818 canvas->save(); 1819 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias); 1820 canvas->drawCircle(17, 11, 8, redPaint); 1821 canvas->restore(); 1822 canvas->translate(16, 0); 1823 } 1824 canvas->restore(); 1825 SkMatrix matrix; 1826 matrix.setScale(6, 6); 1827 scalePaint.setImageFilter( 1828 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr)); 1829 SkCanvas::SaveLayerRec saveLayerRec( 1830 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag); 1831 canvas->saveLayer(saveLayerRec); 1832 canvas->restore(); 1833 ## 1834 1835 #Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias) 1836 1837 #In Clip 1838 #Line # combines Clip with Rect ## 1839 #Populate 1840 1841 #Example 1842 #Height 128 1843 void draw(SkCanvas* canvas) { 1844 canvas->rotate(10); 1845 SkPaint paint; 1846 paint.setAntiAlias(true); 1847 for (auto alias: { false, true } ) { 1848 canvas->save(); 1849 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias); 1850 canvas->drawCircle(100, 60, 60, paint); 1851 canvas->restore(); 1852 canvas->translate(80, 0); 1853 } 1854 } 1855 ## 1856 1857 #SeeAlso clipRRect clipPath clipRegion 1858 1859 ## 1860 1861 #Method void clipRect(const SkRect& rect, SkClipOp op) 1862 1863 #In Clip 1864 #Populate 1865 1866 #Example 1867 #Height 192 1868 #Width 280 1869 void draw(SkCanvas* canvas) { 1870 SkPaint paint; 1871 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) { 1872 canvas->save(); 1873 canvas->clipRect(SkRect::MakeWH(90, 120), op, false); 1874 canvas->drawCircle(100, 100, 60, paint); 1875 canvas->restore(); 1876 canvas->translate(80, 0); 1877 } 1878 } 1879 ## 1880 1881 #SeeAlso clipRRect clipPath clipRegion 1882 1883 ## 1884 1885 #Method void clipRect(const SkRect& rect, bool doAntiAlias = false) 1886 1887 #In Clip 1888 #Populate 1889 1890 #Example 1891 #Height 133 1892 #Description 1893 A circle drawn in pieces looks uniform when drawn Aliased. 1894 The same circle pieces blend with pixels more than once when Anti_Aliased, 1895 visible as a thin pair of lines through the right circle. 1896 ## 1897 void draw(SkCanvas* canvas) { 1898 canvas->clear(SK_ColorWHITE); 1899 SkPaint paint; 1900 paint.setAntiAlias(true); 1901 paint.setColor(0x8055aaff); 1902 SkRect clipRect = { 0, 0, 87.4f, 87.4f }; 1903 for (auto alias: { false, true } ) { 1904 canvas->save(); 1905 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias); 1906 canvas->drawCircle(67, 67, 60, paint); 1907 canvas->restore(); 1908 canvas->save(); 1909 canvas->clipRect(clipRect, SkClipOp::kDifference, alias); 1910 canvas->drawCircle(67, 67, 60, paint); 1911 canvas->restore(); 1912 canvas->translate(120, 0); 1913 } 1914 } 1915 ## 1916 1917 #SeeAlso clipRRect clipPath clipRegion 1918 1919 ## 1920 1921 #Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias) 1922 1923 #In Clip 1924 #Line # combines Clip with Round_Rect ## 1925 #Populate 1926 1927 #Example 1928 #Height 128 1929 void draw(SkCanvas* canvas) { 1930 canvas->clear(SK_ColorWHITE); 1931 SkPaint paint; 1932 paint.setAntiAlias(true); 1933 paint.setColor(0x8055aaff); 1934 SkRRect oval; 1935 oval.setOval({10, 20, 90, 100}); 1936 canvas->clipRRect(oval, SkClipOp::kIntersect, true); 1937 canvas->drawCircle(70, 100, 60, paint); 1938 } 1939 ## 1940 1941 #SeeAlso clipRect clipPath clipRegion 1942 1943 ## 1944 1945 #Method void clipRRect(const SkRRect& rrect, SkClipOp op) 1946 1947 #In Clip 1948 #Populate 1949 1950 #Example 1951 #Height 128 1952 void draw(SkCanvas* canvas) { 1953 SkPaint paint; 1954 paint.setColor(0x8055aaff); 1955 auto oval = SkRRect::MakeOval({10, 20, 90, 100}); 1956 canvas->clipRRect(oval, SkClipOp::kIntersect); 1957 canvas->drawCircle(70, 100, 60, paint); 1958 } 1959 ## 1960 1961 #SeeAlso clipRect clipPath clipRegion 1962 1963 ## 1964 1965 #Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) 1966 1967 #In Clip 1968 #Populate 1969 1970 #Example 1971 #Height 128 1972 void draw(SkCanvas* canvas) { 1973 SkPaint paint; 1974 paint.setAntiAlias(true); 1975 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13); 1976 canvas->clipRRect(oval, true); 1977 canvas->drawCircle(70, 100, 60, paint); 1978 } 1979 ## 1980 1981 #SeeAlso clipRect clipPath clipRegion 1982 1983 ## 1984 1985 #Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias) 1986 1987 #In Clip 1988 #Line # combines Clip with Path ## 1989 #Populate 1990 1991 #Example 1992 #Description 1993 Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference; 1994 area outside clip is subtracted from circle. 1995 1996 Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect; 1997 area inside clip is intersected with circle. 1998 ## 1999 void draw(SkCanvas* canvas) { 2000 SkPaint paint; 2001 paint.setAntiAlias(true); 2002 SkPath path; 2003 path.addRect({20, 30, 100, 110}); 2004 path.setFillType(SkPath::kInverseWinding_FillType); 2005 canvas->save(); 2006 canvas->clipPath(path, SkClipOp::kDifference, false); 2007 canvas->drawCircle(70, 100, 60, paint); 2008 canvas->restore(); 2009 canvas->translate(100, 100); 2010 path.setFillType(SkPath::kWinding_FillType); 2011 canvas->clipPath(path, SkClipOp::kIntersect, false); 2012 canvas->drawCircle(70, 100, 60, paint); 2013 } 2014 ## 2015 2016 #SeeAlso clipRect clipRRect clipRegion 2017 2018 ## 2019 2020 #Method void clipPath(const SkPath& path, SkClipOp op) 2021 2022 #In Clip 2023 #Populate 2024 2025 #Example 2026 #Description 2027 Overlapping Rects form a clip. When clip Path_Fill_Type is set to 2028 SkPath::kWinding_FillType, the overlap is included. Set to 2029 SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole. 2030 ## 2031 void draw(SkCanvas* canvas) { 2032 SkPaint paint; 2033 paint.setAntiAlias(true); 2034 SkPath path; 2035 path.addRect({20, 15, 100, 95}); 2036 path.addRect({50, 65, 130, 135}); 2037 path.setFillType(SkPath::kWinding_FillType); 2038 canvas->save(); 2039 canvas->clipPath(path, SkClipOp::kIntersect); 2040 canvas->drawCircle(70, 85, 60, paint); 2041 canvas->restore(); 2042 canvas->translate(100, 100); 2043 path.setFillType(SkPath::kEvenOdd_FillType); 2044 canvas->clipPath(path, SkClipOp::kIntersect); 2045 canvas->drawCircle(70, 85, 60, paint); 2046 } 2047 ## 2048 2049 #SeeAlso clipRect clipRRect clipRegion 2050 2051 ## 2052 2053 #Method void clipPath(const SkPath& path, bool doAntiAlias = false) 2054 2055 #In Clip 2056 #Populate 2057 2058 #Example 2059 #Height 212 2060 #Description 2061 Clip loops over itself covering its center twice. When clip Path_Fill_Type 2062 is set to SkPath::kWinding_FillType, the overlap is included. Set to 2063 SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole. 2064 ## 2065 void draw(SkCanvas* canvas) { 2066 SkPaint paint; 2067 paint.setAntiAlias(true); 2068 SkPath path; 2069 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80}, 2070 {40, 40}, {100, 40}, {100, 100}, {20, 100}}; 2071 path.addPoly(poly, SK_ARRAY_COUNT(poly), true); 2072 path.setFillType(SkPath::kWinding_FillType); 2073 canvas->save(); 2074 canvas->clipPath(path, SkClipOp::kIntersect); 2075 canvas->drawCircle(50, 50, 45, paint); 2076 canvas->restore(); 2077 canvas->translate(100, 100); 2078 path.setFillType(SkPath::kEvenOdd_FillType); 2079 canvas->clipPath(path, SkClipOp::kIntersect); 2080 canvas->drawCircle(50, 50, 45, paint); 2081 } 2082 ## 2083 2084 #SeeAlso clipRect clipRRect clipRegion 2085 2086 ## 2087 2088 # ------------------------------------------------------------------------------ 2089 2090 #Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect) 2091 2092 #In Clip 2093 #Line # combines Clip with Region ## 2094 #Populate 2095 2096 #Example 2097 #Description 2098 region is unaffected by canvas rotation; iRect is affected by canvas rotation. 2099 Both clips are Aliased; this is not noticeable on Region clip because it 2100 aligns to pixel boundaries. 2101 ## 2102 void draw(SkCanvas* canvas) { 2103 SkPaint paint; 2104 paint.setAntiAlias(true); 2105 SkIRect iRect = {30, 40, 120, 130 }; 2106 SkRegion region(iRect); 2107 canvas->rotate(10); 2108 canvas->save(); 2109 canvas->clipRegion(region, SkClipOp::kIntersect); 2110 canvas->drawCircle(50, 50, 45, paint); 2111 canvas->restore(); 2112 canvas->translate(100, 100); 2113 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect); 2114 canvas->drawCircle(50, 50, 45, paint); 2115 } 2116 ## 2117 2118 #SeeAlso clipRect clipRRect clipPath 2119 2120 ## 2121 2122 #Method bool quickReject(const SkRect& rect) const 2123 2124 #In Clip 2125 #Line # returns if Rect is outside Clip ## 2126 #Populate 2127 2128 #Example 2129 void draw(SkCanvas* canvas) { 2130 SkRect testRect = {30, 30, 120, 129 }; 2131 SkRect clipRect = {30, 130, 120, 230 }; 2132 canvas->save(); 2133 canvas->clipRect(clipRect); 2134 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false"); 2135 canvas->restore(); 2136 canvas->rotate(10); 2137 canvas->clipRect(clipRect); 2138 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false"); 2139 } 2140 #StdOut 2141 quickReject true 2142 quickReject false 2143 ## 2144 ## 2145 2146 #SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing 2147 2148 ## 2149 2150 #Method bool quickReject(const SkPath& path) const 2151 2152 #In Clip 2153 #Populate 2154 2155 #Example 2156 void draw(SkCanvas* canvas) { 2157 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} }; 2158 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; 2159 SkPath testPath, clipPath; 2160 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true); 2161 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); 2162 canvas->save(); 2163 canvas->clipPath(clipPath); 2164 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false"); 2165 canvas->restore(); 2166 canvas->rotate(10); 2167 canvas->clipPath(clipPath); 2168 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false"); 2169 #StdOut 2170 quickReject true 2171 quickReject false 2172 ## 2173 } 2174 ## 2175 2176 #SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing 2177 2178 ## 2179 2180 #Method SkRect getLocalClipBounds() const 2181 2182 #In Clip 2183 #Line # returns Clip bounds in source coordinates ## 2184 #Populate 2185 2186 #Example 2187 #Description 2188 Initial bounds is device bounds outset by 1 on all sides. 2189 Clipped bounds is clipPath bounds outset by 1 on all sides. 2190 Scaling the canvas by two on both axes scales the local bounds by 1/2 2191 on both axes. 2192 ## 2193 SkCanvas local(256, 256); 2194 canvas = &local; 2195 SkRect bounds = canvas->getLocalClipBounds(); 2196 SkDebugf("left:%g top:%g right:%g bottom:%g\n", 2197 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2198 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; 2199 SkPath clipPath; 2200 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); 2201 canvas->clipPath(clipPath); 2202 bounds = canvas->getLocalClipBounds(); 2203 SkDebugf("left:%g top:%g right:%g bottom:%g\n", 2204 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2205 canvas->scale(2, 2); 2206 bounds = canvas->getLocalClipBounds(); 2207 SkDebugf("left:%g top:%g right:%g bottom:%g\n", 2208 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2209 #StdOut 2210 left:-1 top:-1 right:257 bottom:257 2211 left:29 top:129 right:121 bottom:231 2212 left:14.5 top:64.5 right:60.5 bottom:115.5 2213 ## 2214 ## 2215 2216 # local canvas in example works around bug in fiddle ## 2217 #Bug 6524 2218 #SeeAlso getDeviceClipBounds getBaseLayerSize quickReject 2219 2220 ## 2221 2222 #Method bool getLocalClipBounds(SkRect* bounds) const 2223 2224 #In Clip 2225 #Populate 2226 2227 #Example 2228 void draw(SkCanvas* canvas) { 2229 SkCanvas local(256, 256); 2230 canvas = &local; 2231 SkRect bounds; 2232 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds) 2233 ? "false" : "true"); 2234 SkPath path; 2235 canvas->clipPath(path); 2236 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds) 2237 ? "false" : "true"); 2238 } 2239 #StdOut 2240 local bounds empty = false 2241 local bounds empty = true 2242 ## 2243 ## 2244 2245 # local canvas in example works around bug in fiddle ## 2246 #Bug 6524 2247 #SeeAlso getDeviceClipBounds getBaseLayerSize quickReject 2248 2249 ## 2250 2251 #Method SkIRect getDeviceClipBounds() const 2252 2253 #In Clip 2254 #Line # returns IRect bounds of Clip ## 2255 #Populate 2256 2257 #Example 2258 void draw(SkCanvas* canvas) { 2259 #Description 2260 Initial bounds is device bounds, not outset. 2261 Clipped bounds is clipPath bounds, not outset. 2262 Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2 2263 on both axes. 2264 ## 2265 SkCanvas device(256, 256); 2266 canvas = &device; 2267 SkIRect bounds = canvas->getDeviceClipBounds(); 2268 SkDebugf("left:%d top:%d right:%d bottom:%d\n", 2269 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2270 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; 2271 SkPath clipPath; 2272 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); 2273 canvas->save(); 2274 canvas->clipPath(clipPath); 2275 bounds = canvas->getDeviceClipBounds(); 2276 SkDebugf("left:%d top:%d right:%d bottom:%d\n", 2277 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2278 canvas->restore(); 2279 canvas->scale(1.f/2, 1.f/2); 2280 canvas->clipPath(clipPath); 2281 bounds = canvas->getDeviceClipBounds(); 2282 SkDebugf("left:%d top:%d right:%d bottom:%d\n", 2283 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 2284 #StdOut 2285 left:0 top:0 right:256 bottom:256 2286 left:30 top:130 right:120 bottom:230 2287 left:15 top:65 right:60 bottom:115 2288 ## 2289 } 2290 ## 2291 2292 #ToDo some confusion on why with an identity Matrix local and device are different ## 2293 #SeeAlso getLocalClipBounds getBaseLayerSize quickReject 2294 2295 # device canvas in example works around bug in fiddle ## 2296 #Bug 6524 2297 2298 ## 2299 2300 #Method bool getDeviceClipBounds(SkIRect* bounds) const 2301 2302 #In Clip 2303 #Populate 2304 2305 #Example 2306 void draw(SkCanvas* canvas) { 2307 SkIRect bounds; 2308 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds) 2309 ? "false" : "true"); 2310 SkPath path; 2311 canvas->clipPath(path); 2312 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds) 2313 ? "false" : "true"); 2314 } 2315 #StdOut 2316 device bounds empty = false 2317 device bounds empty = true 2318 ## 2319 ## 2320 2321 #SeeAlso getLocalClipBounds getBaseLayerSize quickReject 2322 2323 ## 2324 2325 #Subtopic Clip ## 2326 2327 # ------------------------------------------------------------------------------ 2328 #Subtopic Draw 2329 #Line # draws into Canvas ## 2330 ## 2331 2332 #Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) 2333 #In Draw 2334 #Line # fills Clip with Color and Blend_Mode ## 2335 #Populate 2336 2337 #Example 2338 canvas->drawColor(SK_ColorRED); 2339 canvas->clipRect(SkRect::MakeWH(150, 150)); 2340 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus); 2341 canvas->clipRect(SkRect::MakeWH(75, 75)); 2342 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus); 2343 ## 2344 2345 #SeeAlso clear SkBitmap::erase drawPaint 2346 2347 ## 2348 2349 # ------------------------------------------------------------------------------ 2350 2351 #Method void clear(SkColor color) 2352 #In Draw 2353 #Line # fills Clip with Color ## 2354 #Populate 2355 2356 #Example 2357 void draw(SkCanvas* canvas) { 2358 canvas->save(); 2359 canvas->clipRect(SkRect::MakeWH(256, 128)); 2360 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00)); 2361 canvas->restore(); 2362 canvas->save(); 2363 canvas->clipRect(SkRect::MakeWH(150, 192)); 2364 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00)); 2365 canvas->restore(); 2366 canvas->clipRect(SkRect::MakeWH(75, 256)); 2367 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF)); 2368 } 2369 ## 2370 2371 #SeeAlso drawColor SkBitmap::erase drawPaint 2372 2373 ## 2374 2375 # ------------------------------------------------------------------------------ 2376 2377 #Method void discard() 2378 #In Utility 2379 #Line # makes Canvas contents undefined ## 2380 #Populate 2381 2382 #NoExample 2383 ## 2384 2385 #SeeAlso flush() GrContext::abandonContext 2386 2387 ## 2388 2389 # ------------------------------------------------------------------------------ 2390 2391 #Method void drawPaint(const SkPaint& paint) 2392 #In Draw 2393 #Line # fills Clip with Paint ## 2394 #Populate 2395 2396 #Example 2397 void draw(SkCanvas* canvas) { 2398 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; 2399 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 }; 2400 SkPaint paint; 2401 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors))); 2402 canvas->drawPaint(paint); 2403 } 2404 ## 2405 2406 #SeeAlso clear drawColor SkBitmap::erase 2407 2408 ## 2409 2410 # ------------------------------------------------------------------------------ 2411 2412 #Enum PointMode 2413 #Line # sets drawPoints options ## 2414 2415 #Code 2416 #Populate 2417 ## 2418 2419 Selects if an array of points are drawn as discrete points, as lines, or as 2420 an open polygon. 2421 2422 #Const kPoints_PointMode 0 2423 #Line # draw each point separately ## 2424 ## 2425 2426 #Const kLines_PointMode 1 2427 #Line # draw each pair of points as a line segment ## 2428 ## 2429 2430 #Const kPolygon_PointMode 2 2431 #Line # draw the array of points as a open polygon ## 2432 ## 2433 2434 #Example 2435 #Description 2436 The upper left corner shows three squares when drawn as points. 2437 The upper right corner shows one line; when drawn as lines, two points are required per line. 2438 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner. 2439 The lower left corner shows two lines with a miter when path contains polygon. 2440 ## 2441 void draw(SkCanvas* canvas) { 2442 SkPaint paint; 2443 paint.setStyle(SkPaint::kStroke_Style); 2444 paint.setStrokeWidth(10); 2445 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}}; 2446 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint); 2447 canvas->translate(128, 0); 2448 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint); 2449 canvas->translate(0, 128); 2450 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint); 2451 SkPath path; 2452 path.addPoly(points, 3, false); 2453 canvas->translate(-128, 0); 2454 canvas->drawPath(path, paint); 2455 } 2456 ## 2457 2458 #SeeAlso drawLine drawPoint drawPath 2459 2460 ## 2461 2462 # ------------------------------------------------------------------------------ 2463 2464 #Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) 2465 #In Draw 2466 #Line # draws array as points, lines, polygon ## 2467 #Populate 2468 2469 #Example 2470 #Height 200 2471 #Description 2472 #List 2473 # The first column draws points. ## 2474 # The second column draws points as lines. ## 2475 # The third column draws points as a polygon. ## 2476 # The fourth column draws points as a polygonal path. ## 2477 # The first row uses a round cap and round join. ## 2478 # The second row uses a square cap and a miter join. ## 2479 # The third row uses a butt cap and a bevel join. ## 2480 ## 2481 The transparent color makes multiple line draws visible; 2482 the path is drawn all at once. 2483 ## 2484 void draw(SkCanvas* canvas) { 2485 SkPaint paint; 2486 paint.setAntiAlias(true); 2487 paint.setStyle(SkPaint::kStroke_Style); 2488 paint.setStrokeWidth(10); 2489 paint.setColor(0x80349a45); 2490 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}}; 2491 const SkPaint::Join join[] = { SkPaint::kRound_Join, 2492 SkPaint::kMiter_Join, 2493 SkPaint::kBevel_Join }; 2494 int joinIndex = 0; 2495 SkPath path; 2496 path.addPoly(points, 3, false); 2497 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) { 2498 paint.setStrokeCap(cap); 2499 paint.setStrokeJoin(join[joinIndex++]); 2500 for (const auto mode : { SkCanvas::kPoints_PointMode, 2501 SkCanvas::kLines_PointMode, 2502 SkCanvas::kPolygon_PointMode } ) { 2503 canvas->drawPoints(mode, 3, points, paint); 2504 canvas->translate(64, 0); 2505 } 2506 canvas->drawPath(path, paint); 2507 canvas->translate(-192, 64); 2508 } 2509 } 2510 ## 2511 2512 #SeeAlso drawLine drawPoint drawPath 2513 2514 ## 2515 2516 # ------------------------------------------------------------------------------ 2517 2518 #Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) 2519 #In Draw 2520 #Line # draws point at (x, y) position ## 2521 #Populate 2522 2523 #Example 2524 void draw(SkCanvas* canvas) { 2525 SkPaint paint; 2526 paint.setAntiAlias(true); 2527 paint.setColor(0x80349a45); 2528 paint.setStyle(SkPaint::kStroke_Style); 2529 paint.setStrokeWidth(100); 2530 paint.setStrokeCap(SkPaint::kRound_Cap); 2531 canvas->scale(1, 1.2f); 2532 canvas->drawPoint(64, 96, paint); 2533 canvas->scale(.6f, .8f); 2534 paint.setColor(SK_ColorWHITE); 2535 canvas->drawPoint(106, 120, paint); 2536 } 2537 ## 2538 2539 #SeeAlso drawPoints drawCircle drawRect drawLine drawPath 2540 2541 ## 2542 2543 #Method void drawPoint(SkPoint p, const SkPaint& paint) 2544 #Populate 2545 2546 #Example 2547 void draw(SkCanvas* canvas) { 2548 SkPaint paint; 2549 paint.setAntiAlias(true); 2550 paint.setColor(0x80349a45); 2551 paint.setStyle(SkPaint::kStroke_Style); 2552 paint.setStrokeWidth(100); 2553 paint.setStrokeCap(SkPaint::kSquare_Cap); 2554 canvas->scale(1, 1.2f); 2555 canvas->drawPoint({64, 96}, paint); 2556 canvas->scale(.6f, .8f); 2557 paint.setColor(SK_ColorWHITE); 2558 canvas->drawPoint(106, 120, paint); 2559 } 2560 ## 2561 2562 #SeeAlso drawPoints drawCircle drawRect drawLine drawPath 2563 2564 ## 2565 2566 # ------------------------------------------------------------------------------ 2567 2568 #Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) 2569 #In Draw 2570 #Line # draws line segment between two points ## 2571 #Populate 2572 2573 #Example 2574 SkPaint paint; 2575 paint.setAntiAlias(true); 2576 paint.setColor(0xFF9a67be); 2577 paint.setStrokeWidth(20); 2578 canvas->skew(1, 0); 2579 canvas->drawLine(32, 96, 32, 160, paint); 2580 canvas->skew(-2, 0); 2581 canvas->drawLine(288, 96, 288, 160, paint); 2582 ## 2583 2584 #SeeAlso drawPoint drawCircle drawRect drawPath 2585 2586 ## 2587 2588 #Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) 2589 #Populate 2590 2591 #Example 2592 SkPaint paint; 2593 paint.setAntiAlias(true); 2594 paint.setColor(0xFF9a67be); 2595 paint.setStrokeWidth(20); 2596 canvas->skew(1, 0); 2597 canvas->drawLine({32, 96}, {32, 160}, paint); 2598 canvas->skew(-2, 0); 2599 canvas->drawLine({288, 96}, {288, 160}, paint); 2600 ## 2601 2602 #SeeAlso drawPoint drawCircle drawRect drawPath 2603 2604 ## 2605 2606 # ------------------------------------------------------------------------------ 2607 2608 #Method void drawRect(const SkRect& rect, const SkPaint& paint) 2609 #In Draw 2610 #Line # draws Rect using Clip, Matrix, and Paint ## 2611 #Populate 2612 2613 #Example 2614 void draw(SkCanvas* canvas) { 2615 SkPoint rectPts[] = { {64, 48}, {192, 160} }; 2616 SkPaint paint; 2617 paint.setAntiAlias(true); 2618 paint.setStyle(SkPaint::kStroke_Style); 2619 paint.setStrokeWidth(20); 2620 paint.setStrokeJoin(SkPaint::kRound_Join); 2621 SkMatrix rotator; 2622 rotator.setRotate(30, 128, 128); 2623 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) { 2624 paint.setColor(color); 2625 SkRect rect; 2626 rect.set(rectPts[0], rectPts[1]); 2627 canvas->drawRect(rect, paint); 2628 rotator.mapPoints(rectPts, 2); 2629 } 2630 } 2631 ## 2632 2633 #SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine 2634 2635 ## 2636 2637 # ------------------------------------------------------------------------------ 2638 2639 #Method void drawIRect(const SkIRect& rect, const SkPaint& paint) 2640 #In Draw 2641 #Line # draws IRect using Clip, Matrix, and Paint ## 2642 #Populate 2643 2644 #Example 2645 SkIRect rect = { 64, 48, 192, 160 }; 2646 SkPaint paint; 2647 paint.setAntiAlias(true); 2648 paint.setStyle(SkPaint::kStroke_Style); 2649 paint.setStrokeWidth(20); 2650 paint.setStrokeJoin(SkPaint::kRound_Join); 2651 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) { 2652 paint.setColor(color); 2653 canvas->drawIRect(rect, paint); 2654 canvas->rotate(30, 128, 128); 2655 } 2656 ## 2657 2658 #SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine 2659 2660 ## 2661 2662 # ------------------------------------------------------------------------------ 2663 2664 #Method void drawRegion(const SkRegion& region, const SkPaint& paint) 2665 #In Draw 2666 #Line # draws Region using Clip, Matrix, and Paint ## 2667 #Populate 2668 2669 #Example 2670 void draw(SkCanvas* canvas) { 2671 SkRegion region; 2672 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op); 2673 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op); 2674 SkPaint paint; 2675 paint.setAntiAlias(true); 2676 paint.setStyle(SkPaint::kStroke_Style); 2677 paint.setStrokeWidth(20); 2678 paint.setStrokeJoin(SkPaint::kRound_Join); 2679 canvas->drawRegion(region, paint); 2680 } 2681 ## 2682 2683 #SeeAlso drawRect drawIRect drawPath 2684 2685 ## 2686 2687 # ------------------------------------------------------------------------------ 2688 2689 #Method void drawOval(const SkRect& oval, const SkPaint& paint) 2690 #In Draw 2691 #Line # draws Oval using Clip, Matrix, and Paint ## 2692 #Populate 2693 2694 #Example 2695 void draw(SkCanvas* canvas) { 2696 canvas->clear(0xFF3f5f9f); 2697 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0); 2698 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) }; 2699 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } }; 2700 SkScalar pos[] = { 0.2f, 1.0f }; 2701 SkRect bounds = SkRect::MakeWH(80, 70); 2702 SkPaint paint; 2703 paint.setAntiAlias(true); 2704 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors), 2705 SkShader::kClamp_TileMode)); 2706 canvas->drawOval(bounds , paint); 2707 } 2708 ## 2709 2710 #SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect 2711 2712 ## 2713 2714 # ------------------------------------------------------------------------------ 2715 2716 #Method void drawRRect(const SkRRect& rrect, const SkPaint& paint) 2717 #In Draw 2718 #Line # draws Round_Rect using Clip, Matrix, and Paint ## 2719 #Populate 2720 2721 #Example 2722 void draw(SkCanvas* canvas) { 2723 SkPaint paint; 2724 paint.setAntiAlias(true); 2725 SkRect outer = {30, 40, 210, 220}; 2726 SkRect radii = {30, 50, 70, 90 }; 2727 SkRRect rRect; 2728 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom); 2729 canvas->drawRRect(rRect, paint); 2730 paint.setColor(SK_ColorWHITE); 2731 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop, 2732 outer.fLeft + radii.fLeft, outer.fBottom, paint); 2733 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop, 2734 outer.fRight - radii.fRight, outer.fBottom, paint); 2735 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop, 2736 outer.fRight, outer.fTop + radii.fTop, paint); 2737 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom, 2738 outer.fRight, outer.fBottom - radii.fBottom, paint); 2739 } 2740 ## 2741 2742 #SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath 2743 2744 ## 2745 2746 # ------------------------------------------------------------------------------ 2747 2748 #Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) 2749 #In Draw 2750 #Line # draws double Round_Rect stroked or filled ## 2751 #Populate 2752 2753 #Example 2754 void draw(SkCanvas* canvas) { 2755 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200}); 2756 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160}); 2757 SkPaint paint; 2758 canvas->drawDRRect(outer, inner, paint); 2759 } 2760 ## 2761 2762 #Example 2763 #Description 2764 Outer Rect has no corner radii, but stroke join is rounded. 2765 Inner Round_Rect has corner radii; outset stroke increases radii of corners. 2766 Stroke join does not affect inner Round_Rect since it has no sharp corners. 2767 ## 2768 void draw(SkCanvas* canvas) { 2769 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200}); 2770 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10); 2771 SkPaint paint; 2772 paint.setAntiAlias(true); 2773 paint.setStyle(SkPaint::kStroke_Style); 2774 paint.setStrokeWidth(20); 2775 paint.setStrokeJoin(SkPaint::kRound_Join); 2776 canvas->drawDRRect(outer, inner, paint); 2777 paint.setStrokeWidth(1); 2778 paint.setColor(SK_ColorWHITE); 2779 canvas->drawDRRect(outer, inner, paint); 2780 } 2781 ## 2782 2783 #SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath 2784 2785 ## 2786 2787 # ------------------------------------------------------------------------------ 2788 2789 #Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) 2790 #In Draw 2791 #Line # draws Circle using Clip, Matrix, and Paint ## 2792 #Populate 2793 2794 #Example 2795 void draw(SkCanvas* canvas) { 2796 SkPaint paint; 2797 paint.setAntiAlias(true); 2798 canvas->drawCircle(128, 128, 90, paint); 2799 paint.setColor(SK_ColorWHITE); 2800 canvas->drawCircle(86, 86, 20, paint); 2801 canvas->drawCircle(160, 76, 20, paint); 2802 canvas->drawCircle(140, 150, 35, paint); 2803 } 2804 ## 2805 2806 #SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine 2807 2808 ## 2809 2810 #Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) 2811 #Populate 2812 2813 #Example 2814 void draw(SkCanvas* canvas) { 2815 SkPaint paint; 2816 paint.setAntiAlias(true); 2817 canvas->drawCircle(128, 128, 90, paint); 2818 paint.setColor(SK_ColorWHITE); 2819 canvas->drawCircle({86, 86}, 20, paint); 2820 canvas->drawCircle({160, 76}, 20, paint); 2821 canvas->drawCircle({140, 150}, 35, paint); 2822 } 2823 ## 2824 2825 #SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine 2826 2827 ## 2828 2829 # ------------------------------------------------------------------------------ 2830 2831 #Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 2832 bool useCenter, const SkPaint& paint) 2833 #In Draw 2834 #Line # draws Arc using Clip, Matrix, and Paint ## 2835 #Populate 2836 2837 #Example 2838 void draw(SkCanvas* canvas) { 2839 SkPaint paint; 2840 paint.setAntiAlias(true); 2841 SkRect oval = { 4, 4, 60, 60}; 2842 for (auto useCenter : { false, true } ) { 2843 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) { 2844 paint.setStyle(style); 2845 for (auto degrees : { 45, 90, 180, 360} ) { 2846 canvas->drawArc(oval, 0, degrees , useCenter, paint); 2847 canvas->translate(64, 0); 2848 } 2849 canvas->translate(-256, 64); 2850 } 2851 } 2852 } 2853 ## 2854 2855 #Example 2856 #Height 64 2857 void draw(SkCanvas* canvas) { 2858 SkPaint paint; 2859 paint.setAntiAlias(true); 2860 paint.setStyle(SkPaint::kStroke_Style); 2861 paint.setStrokeWidth(4); 2862 SkRect oval = { 4, 4, 60, 60}; 2863 float intervals[] = { 5, 5 }; 2864 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f)); 2865 for (auto degrees : { 270, 360, 540, 720 } ) { 2866 canvas->drawArc(oval, 0, degrees, false, paint); 2867 canvas->translate(64, 0); 2868 } 2869 } 2870 ## 2871 2872 #SeeAlso SkPath::arcTo drawCircle drawOval drawPath 2873 2874 ## 2875 2876 # ------------------------------------------------------------------------------ 2877 2878 #Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint) 2879 #In Draw 2880 #Line # draws Round_Rect using Clip, Matrix, and Paint ## 2881 #Populate 2882 2883 #Example 2884 #Description 2885 Top row has a zero radius a generates a rectangle. 2886 Second row radii sum to less than sides. 2887 Third row radii sum equals sides. 2888 Fourth row radii sum exceeds sides; radii are scaled to fit. 2889 ## 2890 void draw(SkCanvas* canvas) { 2891 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} }; 2892 SkPaint paint; 2893 paint.setStrokeWidth(15); 2894 paint.setStrokeJoin(SkPaint::kRound_Join); 2895 paint.setAntiAlias(true); 2896 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) { 2897 paint.setStyle(style ); 2898 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) { 2899 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint); 2900 canvas->translate(0, 60); 2901 } 2902 canvas->translate(80, -240); 2903 } 2904 } 2905 ## 2906 2907 #SeeAlso drawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint 2908 2909 ## 2910 2911 # ------------------------------------------------------------------------------ 2912 2913 #Method void drawPath(const SkPath& path, const SkPaint& paint) 2914 #In Draw 2915 #Line # draws Path using Clip, Matrix, and Paint ## 2916 #Populate 2917 2918 #Example 2919 #Description 2920 Top rows draw stroked path with combinations of joins and caps. The open contour 2921 is affected by caps; the closed contour is affected by joins. 2922 Bottom row draws fill the same for open and closed contour. 2923 First bottom column shows winding fills overlap. 2924 Second bottom column shows even odd fills exclude overlap. 2925 Third bottom column shows inverse winding fills area outside both contours. 2926 ## 2927 void draw(SkCanvas* canvas) { 2928 SkPath path; 2929 path.moveTo(20, 20); 2930 path.quadTo(60, 20, 60, 60); 2931 path.close(); 2932 path.moveTo(60, 20); 2933 path.quadTo(60, 60, 20, 60); 2934 SkPaint paint; 2935 paint.setStrokeWidth(10); 2936 paint.setAntiAlias(true); 2937 paint.setStyle(SkPaint::kStroke_Style); 2938 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) { 2939 paint.setStrokeJoin(join); 2940 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) { 2941 paint.setStrokeCap(cap); 2942 canvas->drawPath(path, paint); 2943 canvas->translate(80, 0); 2944 } 2945 canvas->translate(-240, 60); 2946 } 2947 paint.setStyle(SkPaint::kFill_Style); 2948 for (auto fill : { SkPath::kWinding_FillType, 2949 SkPath::kEvenOdd_FillType, 2950 SkPath::kInverseWinding_FillType } ) { 2951 path.setFillType(fill); 2952 canvas->save(); 2953 canvas->clipRect({0, 10, 80, 70}); 2954 canvas->drawPath(path, paint); 2955 canvas->restore(); 2956 canvas->translate(80, 0); 2957 } 2958 } 2959 ## 2960 2961 #SeeAlso SkPath drawLine drawArc drawRect drawPoints 2962 2963 ## 2964 2965 # ------------------------------------------------------------------------------ 2966 #Subtopic Draw_Image 2967 #Line # draws Image to Canvas ## 2968 2969 drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or 2970 a smart pointer as a convenience. The pairs of calls are otherwise identical. 2971 2972 #Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr) 2973 #In Draw_Image 2974 #In Draw 2975 #Line # draws Image at (x, y) position ## 2976 #Populate 2977 2978 #Example 2979 #Height 64 2980 #Image 4 2981 void draw(SkCanvas* canvas) { 2982 // sk_sp<SkImage> image; 2983 SkImage* imagePtr = image.get(); 2984 canvas->drawImage(imagePtr, 0, 0); 2985 SkPaint paint; 2986 canvas->drawImage(imagePtr, 80, 0, &paint); 2987 paint.setAlpha(0x80); 2988 canvas->drawImage(imagePtr, 160, 0, &paint); 2989 } 2990 ## 2991 2992 #SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter 2993 2994 ## 2995 2996 # ------------------------------------------------------------------------------ 2997 2998 #Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top, 2999 const SkPaint* paint = nullptr) 3000 #Populate 3001 3002 #Example 3003 #Height 64 3004 #Image 4 3005 void draw(SkCanvas* canvas) { 3006 // sk_sp<SkImage> image; 3007 canvas->drawImage(image, 0, 0); 3008 SkPaint paint; 3009 canvas->drawImage(image, 80, 0, &paint); 3010 paint.setAlpha(0x80); 3011 canvas->drawImage(image, 160, 0, &paint); 3012 } 3013 ## 3014 3015 #SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter 3016 3017 ## 3018 3019 # ------------------------------------------------------------------------------ 3020 3021 #Enum SrcRectConstraint 3022 #Line # sets drawImageRect options ## 3023 3024 #Code 3025 #Populate 3026 ## 3027 3028 SrcRectConstraint controls the behavior at the edge of source Rect, 3029 provided to drawImageRect, trading off speed for precision. 3030 3031 Image_Filter in Paint may sample multiple pixels in the image. Source Rect 3032 restricts the bounds of pixels that may be read. Image_Filter may slow down if 3033 it cannot read outside the bounds, when sampling near the edge of source Rect. 3034 SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels 3035 outside source Rect. 3036 3037 #Const kStrict_SrcRectConstraint 0 3038 #Line # sample only inside bounds; slower ## 3039 Requires Image_Filter to respect source Rect, 3040 sampling only inside of its bounds, possibly with a performance penalty. 3041 ## 3042 3043 #Const kFast_SrcRectConstraint 1 3044 #Line # sample outside bounds; faster ## 3045 Permits Image_Filter to sample outside of source Rect 3046 by half the width of Image_Filter, permitting it to run faster but with 3047 error at the image edges. 3048 ## 3049 3050 #Example 3051 #Height 64 3052 #Description 3053 redBorder contains a black and white checkerboard bordered by red. 3054 redBorder is drawn scaled by 16 on the left. 3055 The middle and right bitmaps are filtered checkerboards. 3056 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white. 3057 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners. 3058 ## 3059 void draw(SkCanvas* canvas) { 3060 SkBitmap redBorder; 3061 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4)); 3062 SkCanvas checkRed(redBorder); 3063 checkRed.clear(SK_ColorRED); 3064 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE }, 3065 { SK_ColorWHITE, SK_ColorBLACK } }; 3066 checkRed.writePixels( 3067 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1); 3068 canvas->scale(16, 16); 3069 canvas->drawBitmap(redBorder, 0, 0, nullptr); 3070 canvas->resetMatrix(); 3071 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder); 3072 SkPaint lowPaint; 3073 lowPaint.setFilterQuality(kLow_SkFilterQuality); 3074 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint, 3075 SkCanvas::kFast_SrcRectConstraint } ) { 3076 canvas->translate(80, 0); 3077 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3), 3078 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint); 3079 } 3080 } 3081 ## 3082 3083 #SeeAlso drawImageRect drawImage SkPaint::setImageFilter 3084 3085 ## 3086 3087 # ------------------------------------------------------------------------------ 3088 3089 #Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, 3090 const SkPaint* paint, 3091 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3092 #In Draw_Image 3093 #In Draw 3094 #Line # draws Image, source Rect to destination Rect ## 3095 #Populate 3096 3097 #Example 3098 #Height 64 3099 #Description 3100 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within 3101 its bounds; there is no bleeding with kFast_SrcRectConstraint. 3102 the middle and right bitmaps draw with kLow_SkFilterQuality; with 3103 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and 3104 with kFast_SrcRectConstraint red bleeds on the edges. 3105 ## 3106 void draw(SkCanvas* canvas) { 3107 uint32_t pixels[][4] = { 3108 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 }, 3109 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 }, 3110 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 }, 3111 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } }; 3112 SkBitmap redBorder; 3113 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4), 3114 (void*) pixels, sizeof(pixels[0])); 3115 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder); 3116 SkPaint lowPaint; 3117 for (auto constraint : { 3118 SkCanvas::kFast_SrcRectConstraint, 3119 SkCanvas::kStrict_SrcRectConstraint, 3120 SkCanvas::kFast_SrcRectConstraint } ) { 3121 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3), 3122 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint); 3123 lowPaint.setFilterQuality(kLow_SkFilterQuality); 3124 canvas->translate(80, 0); 3125 } 3126 } 3127 ## 3128 3129 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 3130 3131 ## 3132 3133 # ------------------------------------------------------------------------------ 3134 3135 #Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst, 3136 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3137 #In Draw_Image 3138 #In Draw 3139 #Populate 3140 3141 #Example 3142 #Image 4 3143 void draw(SkCanvas* canvas) { 3144 // sk_sp<SkImage> image; 3145 for (auto i : { 1, 2, 4, 8 } ) { 3146 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100), 3147 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr); 3148 } 3149 } 3150 ## 3151 3152 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 3153 3154 ## 3155 3156 # ------------------------------------------------------------------------------ 3157 3158 #Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint) 3159 #In Draw_Image 3160 #In Draw 3161 #Populate 3162 3163 #Example 3164 #Image 4 3165 void draw(SkCanvas* canvas) { 3166 // sk_sp<SkImage> image; 3167 for (auto i : { 20, 40, 80, 160 } ) { 3168 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr); 3169 } 3170 } 3171 ## 3172 3173 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 3174 3175 ## 3176 3177 # ------------------------------------------------------------------------------ 3178 3179 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst, 3180 const SkPaint* paint, 3181 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3182 #In Draw_Image 3183 #In Draw 3184 #Populate 3185 3186 #Example 3187 #Height 64 3188 #Description 3189 Canvas scales and translates; transformation from src to dst also scales. 3190 The two matrices are concatenated to create the final transformation. 3191 ## 3192 void draw(SkCanvas* canvas) { 3193 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE }, 3194 { SK_ColorWHITE, SK_ColorBLACK } }; 3195 SkBitmap bitmap; 3196 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 3197 (void*) pixels, sizeof(pixels[0])); 3198 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 3199 SkPaint paint; 3200 canvas->scale(4, 4); 3201 for (auto alpha : { 50, 100, 150, 255 } ) { 3202 paint.setAlpha(alpha); 3203 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint); 3204 canvas->translate(8, 0); 3205 } 3206 } 3207 ## 3208 3209 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 3210 3211 ## 3212 3213 # ------------------------------------------------------------------------------ 3214 3215 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst, 3216 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3217 #In Draw_Image 3218 #In Draw 3219 #Populate 3220 3221 #Example 3222 #Height 64 3223 void draw(SkCanvas* canvas) { 3224 uint32_t pixels[][2] = { { 0x00000000, 0x55555555}, 3225 { 0xAAAAAAAA, 0xFFFFFFFF} }; 3226 SkBitmap bitmap; 3227 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 3228 (void*) pixels, sizeof(pixels[0])); 3229 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 3230 SkPaint paint; 3231 canvas->scale(4, 4); 3232 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 3233 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus)); 3234 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint); 3235 canvas->translate(8, 0); 3236 } 3237 } 3238 ## 3239 3240 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 3241 3242 ## 3243 3244 # ------------------------------------------------------------------------------ 3245 3246 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint) 3247 #In Draw_Image 3248 #In Draw 3249 #Populate 3250 3251 #Example 3252 #Height 64 3253 void draw(SkCanvas* canvas) { 3254 uint32_t pixels[][2] = { { 0x00000000, 0x55550000}, 3255 { 0xAAAA0000, 0xFFFF0000} }; 3256 SkBitmap bitmap; 3257 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 3258 (void*) pixels, sizeof(pixels[0])); 3259 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 3260 SkPaint paint; 3261 canvas->scale(4, 4); 3262 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 3263 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus)); 3264 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint); 3265 canvas->translate(8, 0); 3266 } 3267 } 3268 ## 3269 3270 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine 3271 3272 ## 3273 3274 # ------------------------------------------------------------------------------ 3275 3276 #Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, 3277 const SkPaint* paint = nullptr) 3278 #In Draw_Image 3279 #In Draw 3280 #Line # draws Nine_Patch Image ## 3281 3282 Draws Image image stretched proportionally to fit into Rect dst. 3283 IRect center divides the image into nine sections: four sides, four corners, and 3284 the center. Corners are unmodified or scaled down proportionately if their sides 3285 are larger than dst; center and four sides are scaled to fit remaining space, if any. 3286 3287 Additionally transform draw using Clip, Matrix, and optional Paint paint. 3288 3289 #paint_as_used_by_draw_lattice_or_draw_nine(image)# 3290 3291 If generated mask extends beyond image bounds, replicate image edge colors, just 3292 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 3293 replicates the image edge color when it samples outside of its bounds. 3294 3295 #Param image Image containing pixels, dimensions, and format ## 3296 #Param center IRect edge of image corners and sides ## 3297 #Param dst destination Rect of image to draw to ## 3298 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3299 and so on; or nullptr 3300 ## 3301 3302 #Example 3303 #Height 128 3304 #Description 3305 The leftmost image is smaller than center; only corners are drawn, all scaled to fit. 3306 The second image equals the size of center; only corners are drawn without scaling. 3307 The remaining images are larger than center. All corners draw without scaling. 3308 The sides and center are scaled if needed to take up the remaining space. 3309 ## 3310 void draw(SkCanvas* canvas) { 3311 SkIRect center = { 20, 10, 50, 40 }; 3312 SkBitmap bitmap; 3313 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 3314 SkCanvas bitCanvas(bitmap); 3315 SkPaint paint; 3316 SkColor gray = 0xFF000000; 3317 int left = 0; 3318 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 3319 int top = 0; 3320 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 3321 paint.setColor(gray); 3322 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 3323 gray += 0x001f1f1f; 3324 top = bottom; 3325 } 3326 left = right; 3327 } 3328 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 3329 SkImage* imagePtr = image.get(); 3330 for (auto dest: { 20, 30, 40, 60, 90 } ) { 3331 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr); 3332 canvas->translate(dest + 4, 0); 3333 } 3334 } 3335 ## 3336 3337 #SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect 3338 3339 ## 3340 3341 # ------------------------------------------------------------------------------ 3342 3343 #Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst, 3344 const SkPaint* paint = nullptr) 3345 #In Draw_Image 3346 #In Draw 3347 Draws Image image stretched proportionally to fit into Rect dst. 3348 IRect center divides the image into nine sections: four sides, four corners, and 3349 the center. Corners are not scaled, or scaled down proportionately if their sides 3350 are larger than dst; center and four sides are scaled to fit remaining space, if any. 3351 3352 Additionally transform draw using Clip, Matrix, and optional Paint paint. 3353 3354 #paint_as_used_by_draw_lattice_or_draw_nine(image)# 3355 3356 If generated mask extends beyond image bounds, replicate image edge colors, just 3357 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set 3358 replicates the image edge color when it samples outside of its bounds. 3359 3360 #Param image Image containing pixels, dimensions, and format ## 3361 #Param center IRect edge of image corners and sides ## 3362 #Param dst destination Rect of image to draw to ## 3363 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3364 and so on; or nullptr 3365 ## 3366 3367 #Example 3368 #Height 128 3369 #Description 3370 The two leftmost images has four corners and sides to the left and right of center. 3371 The leftmost image scales the width of corners proportionately to fit. 3372 The third and fourth image corners are not scaled; the sides and center are scaled to 3373 fill the remaining space. 3374 The rightmost image has four corners scaled vertically to fit, and uses sides above 3375 and below center to fill the remaining space. 3376 ## 3377 void draw(SkCanvas* canvas) { 3378 SkIRect center = { 20, 10, 50, 40 }; 3379 SkBitmap bitmap; 3380 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 3381 SkCanvas bitCanvas(bitmap); 3382 SkPaint paint; 3383 SkColor gray = 0xFF000000; 3384 int left = 0; 3385 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 3386 int top = 0; 3387 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 3388 paint.setColor(gray); 3389 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 3390 gray += 0x001f1f1f; 3391 top = bottom; 3392 } 3393 left = right; 3394 } 3395 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 3396 for (auto dest: { 20, 30, 40, 60, 90 } ) { 3397 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr); 3398 canvas->translate(dest + 4, 0); 3399 } 3400 } 3401 ## 3402 3403 #SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect 3404 3405 ## 3406 3407 # ------------------------------------------------------------------------------ 3408 3409 #Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, 3410 const SkPaint* paint = nullptr) 3411 #In Draw_Image 3412 #In Draw 3413 #Line # draws Bitmap at (x, y) position ## 3414 #Populate 3415 3416 #Example 3417 #Height 64 3418 void draw(SkCanvas* canvas) { 3419 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, 3420 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 3421 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, 3422 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF}, 3423 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 3424 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00}, 3425 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00}, 3426 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} }; 3427 SkBitmap bitmap; 3428 bitmap.installPixels(SkImageInfo::MakeA8(8, 8), 3429 (void*) pixels, sizeof(pixels[0])); 3430 SkPaint paint; 3431 canvas->scale(4, 4); 3432 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) { 3433 paint.setColor(color); 3434 canvas->drawBitmap(bitmap, 0, 0, &paint); 3435 canvas->translate(12, 0); 3436 } 3437 } 3438 ## 3439 3440 #SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels 3441 3442 ## 3443 3444 # ------------------------------------------------------------------------------ 3445 3446 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst, 3447 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3448 #In Draw_Image 3449 #In Draw 3450 #Line # draws Bitmap, source Rect to destination Rect ## 3451 #Populate 3452 3453 #Example 3454 #Height 64 3455 void draw(SkCanvas* canvas) { 3456 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, 3457 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 3458 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, 3459 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF}, 3460 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 3461 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00}, 3462 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, 3463 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} }; 3464 SkBitmap bitmap; 3465 bitmap.installPixels(SkImageInfo::MakeA8(8, 8), 3466 (void*) pixels, sizeof(pixels[0])); 3467 SkPaint paint; 3468 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6)); 3469 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) { 3470 paint.setColor(color); 3471 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint); 3472 canvas->translate(48, 0); 3473 } 3474 } 3475 ## 3476 3477 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine 3478 3479 ## 3480 3481 # ------------------------------------------------------------------------------ 3482 3483 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst, 3484 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3485 #In Draw_Image 3486 #In Draw 3487 #Populate 3488 3489 #Example 3490 #Height 64 3491 void draw(SkCanvas* canvas) { 3492 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}, 3493 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, 3494 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF}, 3495 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF}, 3496 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF}, 3497 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF}, 3498 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, 3499 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} }; 3500 SkBitmap bitmap; 3501 bitmap.installPixels(SkImageInfo::MakeA8(8, 8), 3502 (void*) pixels, sizeof(pixels[0])); 3503 SkPaint paint; 3504 paint.setFilterQuality(kHigh_SkFilterQuality); 3505 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) { 3506 paint.setColor(color); 3507 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint); 3508 canvas->translate(48.25f, 0); 3509 } 3510 } 3511 ## 3512 3513 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine 3514 3515 ## 3516 3517 # ------------------------------------------------------------------------------ 3518 3519 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint, 3520 SrcRectConstraint constraint = kStrict_SrcRectConstraint) 3521 #In Draw_Image 3522 #In Draw 3523 #Populate 3524 3525 #Example 3526 #Height 64 3527 void draw(SkCanvas* canvas) { 3528 uint32_t pixels[][2] = { { 0x00000000, 0x55550000}, 3529 { 0xAAAA0000, 0xFFFF0000} }; 3530 SkBitmap bitmap; 3531 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2), 3532 (void*) pixels, sizeof(pixels[0])); 3533 SkPaint paint; 3534 canvas->scale(4, 4); 3535 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 3536 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus)); 3537 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint); 3538 canvas->translate(8, 0); 3539 } 3540 } 3541 ## 3542 3543 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine 3544 3545 ## 3546 3547 # ------------------------------------------------------------------------------ 3548 3549 #PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image) 3550 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, 3551 Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader. 3552 If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint 3553 Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all 3554 other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels. 3555 Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state. 3556 ## 3557 3558 #Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 3559 const SkPaint* paint = nullptr) 3560 #In Draw_Image 3561 #In Draw 3562 #Line # draws Nine_Patch Bitmap ## 3563 3564 Draws Bitmap bitmap stretched proportionally to fit into Rect dst. 3565 IRect center divides the bitmap into nine sections: four sides, four corners, 3566 and the center. Corners are not scaled, or scaled down proportionately if their 3567 sides are larger than dst; center and four sides are scaled to fit remaining 3568 space, if any. 3569 3570 Additionally transform draw using Clip, Matrix, and optional Paint paint. 3571 3572 #paint_as_used_by_draw_lattice_or_draw_nine(bitmap)# 3573 3574 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 3575 just as Shader made from SkShader::MakeBitmapShader with 3576 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 3577 outside of its bounds. 3578 3579 #Param bitmap Bitmap containing pixels, dimensions, and format ## 3580 #Param center IRect edge of image corners and sides ## 3581 #Param dst destination Rect of image to draw to ## 3582 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3583 and so on; or nullptr 3584 ## 3585 3586 #Example 3587 #Height 128 3588 #Description 3589 The two leftmost bitmap draws has four corners and sides to the left and right of center. 3590 The leftmost bitmap draw scales the width of corners proportionately to fit. 3591 The third and fourth draw corners are not scaled; the sides and center are scaled to 3592 fill the remaining space. 3593 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above 3594 and below center to fill the remaining space. 3595 ## 3596 void draw(SkCanvas* canvas) { 3597 SkIRect center = { 20, 10, 50, 40 }; 3598 SkBitmap bitmap; 3599 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 3600 SkCanvas bitCanvas(bitmap); 3601 SkPaint paint; 3602 SkColor gray = 0xFF000000; 3603 int left = 0; 3604 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 3605 int top = 0; 3606 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 3607 paint.setColor(gray); 3608 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 3609 gray += 0x001f1f1f; 3610 top = bottom; 3611 } 3612 left = right; 3613 } 3614 for (auto dest: { 20, 30, 40, 60, 90 } ) { 3615 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr); 3616 canvas->translate(dest + 4, 0); 3617 } 3618 } 3619 ## 3620 3621 #SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect 3622 3623 ## 3624 3625 # ------------------------------------------------------------------------------ 3626 #Subtopic Lattice 3627 #Line # divides Bitmap or Image into a rectangular grid ## 3628 3629 #Struct Lattice 3630 #Line # divides Bitmap or Image into a rectangular grid ## 3631 3632 #Code 3633 #Populate 3634 ## 3635 3636 Lattice divides Bitmap or Image into a rectangular grid. 3637 Grid entries on even columns and even rows are fixed; these entries are 3638 always drawn at their original size if the destination is large enough. 3639 If the destination side is too small to hold the fixed entries, all fixed 3640 entries are proportionately scaled down to fit. 3641 The grid entries not on even columns and rows are scaled to fit the 3642 remaining space, if any. 3643 3644 #Enum RectType 3645 #Line # optional setting per rectangular grid entry ## 3646 #Code 3647 #Populate 3648 ## 3649 3650 Optional setting per rectangular grid entry to make it transparent, 3651 or to fill the grid entry with a color. 3652 3653 #Const kDefault 0 3654 #Line # draws Bitmap into lattice rectangle ## 3655 ## 3656 3657 #Const kTransparent 1 3658 #Line # skips lattice rectangle by making it transparent ## 3659 ## 3660 3661 #Const kFixedColor 2 3662 #Line # draws one of fColors into lattice rectangle ## 3663 ## 3664 ## 3665 3666 #Subtopic Members 3667 ## 3668 3669 #Member const int* fXDivs 3670 #Line # x-axis values dividing bitmap ## 3671 Array of x-axis values that divide the bitmap vertically. 3672 Array entries must be unique, increasing, greater than or equal to 3673 fBounds left edge, and less than fBounds right edge. 3674 Set the first element to fBounds left to collapse the left column of 3675 fixed grid entries. 3676 ## 3677 3678 #Member const int* fYDivs 3679 #Line # y-axis values dividing bitmap ## 3680 Array of y-axis values that divide the bitmap horizontally. 3681 Array entries must be unique, increasing, greater than or equal to 3682 fBounds top edge, and less than fBounds bottom edge. 3683 Set the first element to fBounds top to collapse the top row of fixed 3684 grid entries. 3685 ## 3686 3687 #Member const RectType* fRectTypes 3688 #Line # array of fill types ## 3689 Optional array of fill types, one per rectangular grid entry: 3690 array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##. 3691 3692 Each RectType is one of: kDefault, kTransparent, kFixedColor. 3693 3694 Array entries correspond to the rectangular grid entries, ascending 3695 left to right and then top to bottom. 3696 ## 3697 3698 #Member int fXCount 3699 #Line # number of x-coordinates ## 3700 Number of entries in fXDivs array; one less than the number of 3701 horizontal divisions. 3702 ## 3703 3704 #Member int fYCount 3705 #Line # number of y-coordinates ## 3706 Number of entries in fYDivs array; one less than the number of vertical 3707 divisions. 3708 ## 3709 3710 #Member const SkIRect* fBounds 3711 #Line # source bounds to draw from ## 3712 Optional subset IRect source to draw from. 3713 If nullptr, source bounds is dimensions of Bitmap or Image. 3714 ## 3715 3716 #Member const SkColor* fColors 3717 #Line # array of colors ## 3718 Optional array of colors, one per rectangular grid entry. 3719 Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##. 3720 3721 Array entries correspond to the rectangular grid entries, ascending 3722 left to right, then top to bottom. 3723 ## 3724 3725 #Struct Lattice ## 3726 3727 #Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst, 3728 const SkPaint* paint = nullptr) 3729 #In Draw_Image 3730 #In Draw 3731 #Line # draws proportionally stretched Bitmap ## 3732 3733 Draws Bitmap bitmap stretched proportionally to fit into Rect dst. 3734 3735 Lattice lattice divides bitmap into a rectangular grid. 3736 Each intersection of an even-numbered row and column is fixed; like the corners 3737 of drawBitmapNine, fixed lattice elements never scale larger than their initial 3738 size and shrink proportionately when all fixed elements exceed the bitmap 3739 dimension. All other grid elements scale to fill the available space, if any. 3740 3741 Additionally transform draw using Clip, Matrix, and optional Paint paint. 3742 3743 #paint_as_used_by_draw_lattice_or_draw_nine(bitmap)# 3744 3745 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 3746 just as Shader made from SkShader::MakeBitmapShader with 3747 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 3748 outside of its bounds. 3749 3750 #Param bitmap Bitmap containing pixels, dimensions, and format ## 3751 #Param lattice division of bitmap into fixed and variable rectangles ## 3752 #Param dst destination Rect of image to draw to ## 3753 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3754 and so on; or nullptr 3755 ## 3756 3757 #Example 3758 #Height 128 3759 #Description 3760 The two leftmost bitmap draws has four corners and sides to the left and right of center. 3761 The leftmost bitmap draw scales the width of corners proportionately to fit. 3762 The third and fourth draw corners are not scaled; the sides are scaled to 3763 fill the remaining space; the center is transparent. 3764 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above 3765 and below center to fill the remaining space. 3766 ## 3767 void draw(SkCanvas* canvas) { 3768 SkIRect center = { 20, 10, 50, 40 }; 3769 SkBitmap bitmap; 3770 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 3771 SkCanvas bitCanvas(bitmap); 3772 SkPaint paint; 3773 SkColor gray = 0xFF000000; 3774 int left = 0; 3775 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 3776 int top = 0; 3777 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 3778 paint.setColor(gray); 3779 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 3780 gray += 0x001f1f1f; 3781 top = bottom; 3782 } 3783 left = right; 3784 } 3785 const int xDivs[] = { center.fLeft, center.fRight }; 3786 const int yDivs[] = { center.fTop, center.fBottom }; 3787 SkCanvas::Lattice::RectType fillTypes[3][3]; 3788 memset(fillTypes, 0, sizeof(fillTypes)); 3789 fillTypes[1][1] = SkCanvas::Lattice::kTransparent; 3790 SkColor dummy[9]; // temporary pending bug fix 3791 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs), 3792 SK_ARRAY_COUNT(yDivs), nullptr, dummy }; 3793 for (auto dest: { 20, 30, 40, 60, 90 } ) { 3794 canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr); 3795 canvas->translate(dest + 4, 0); 3796 } 3797 } 3798 ## 3799 3800 #SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice 3801 3802 ## 3803 3804 # ------------------------------------------------------------------------------ 3805 3806 #Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, 3807 const SkPaint* paint = nullptr) 3808 #In Draw_Image 3809 #In Draw 3810 #Line # draws proportionally stretched Image ## 3811 3812 Draws Image image stretched proportionally to fit into Rect dst. 3813 3814 Lattice lattice divides image into a rectangular grid. 3815 Each intersection of an even-numbered row and column is fixed; like the corners 3816 of drawBitmapNine, fixed lattice elements never scale larger than their initial 3817 size and shrink proportionately when all fixed elements exceed the bitmap 3818 dimension. All other grid elements scale to fill the available space, if any. 3819 3820 Additionally transform draw using Clip, Matrix, and optional Paint paint. 3821 3822 #paint_as_used_by_draw_lattice_or_draw_nine(image)# 3823 3824 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, 3825 just as Shader made from SkShader::MakeBitmapShader with 3826 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples 3827 outside of its bounds. 3828 3829 #Param image Image containing pixels, dimensions, and format ## 3830 #Param lattice division of bitmap into fixed and variable rectangles ## 3831 #Param dst destination Rect of image to draw to ## 3832 #Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, 3833 and so on; or nullptr 3834 ## 3835 3836 #Example 3837 #Height 128 3838 #Description 3839 The leftmost image is smaller than center; only corners are drawn, all scaled to fit. 3840 The second image equals the size of center; only corners are drawn without scaling. 3841 The remaining images are larger than center. All corners draw without scaling. The sides 3842 are scaled if needed to take up the remaining space; the center is transparent. 3843 ## 3844 void draw(SkCanvas* canvas) { 3845 SkIRect center = { 20, 10, 50, 40 }; 3846 SkBitmap bitmap; 3847 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60)); 3848 SkCanvas bitCanvas(bitmap); 3849 SkPaint paint; 3850 SkColor gray = 0xFF000000; 3851 int left = 0; 3852 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) { 3853 int top = 0; 3854 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) { 3855 paint.setColor(gray); 3856 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint); 3857 gray += 0x001f1f1f; 3858 top = bottom; 3859 } 3860 left = right; 3861 } 3862 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); 3863 SkImage* imagePtr = image.get(); 3864 for (auto dest: { 20, 30, 40, 60, 90 } ) { 3865 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr); 3866 canvas->translate(dest + 4, 0); 3867 } 3868 } 3869 ## 3870 3871 #SeeAlso drawBitmapLattice drawImage drawImageNine Lattice 3872 3873 ## 3874 3875 #Subtopic Lattice ## 3876 3877 #Subtopic Draw_Image ## 3878 3879 # ------------------------------------------------------------------------------ 3880 #Subtopic Draw_Text 3881 #Line # draws text into Canvas ## 3882 ## 3883 3884 #Method void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding, 3885 SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) 3886 #In Draw_Text 3887 #In Draw 3888 #Line # draws text at (x, y), using font advance ## 3889 #Populate 3890 3891 #Example 3892 #Height 200 3893 #Description 3894 The same text is drawn varying Paint_Text_Size and varying 3895 Matrix. 3896 ## 3897 void draw(SkCanvas* canvas) { 3898 SkPaint paint; 3899 SkFont font; 3900 float textSizes[] = { 12, 18, 24, 36 }; 3901 for (auto size: textSizes ) { 3902 font.setSize(size); 3903 canvas->drawSimpleText("Aa", 2, kUTF8_SkTextEncoding, 10, 20, font, paint); 3904 canvas->translate(0, size * 2); 3905 } 3906 font.setSize(12); 3907 float yPos = 20; 3908 for (auto size: textSizes ) { 3909 float scale = size / 12.f; 3910 canvas->resetMatrix(); 3911 canvas->translate(100, 0); 3912 canvas->scale(scale, scale); 3913 canvas->drawSimpleText("Aa", 2, kUTF8_SkTextEncoding, 3914 10 / scale, yPos / scale, font, paint); 3915 yPos += size * 2; 3916 } 3917 } 3918 ## 3919 3920 #SeeAlso drawString drawTextBlob 3921 3922 ## 3923 3924 # ------------------------------------------------------------------------------ 3925 3926 #Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) 3927 #In Draw_Text 3928 #In Draw 3929 #Line # draws text with arrays of positions and Paint ## 3930 Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint. 3931 3932 blob contains Glyphs, their positions, and paint attributes specific to text: 3933 #font_metrics#. 3934 3935 Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding. 3936 3937 Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha, 3938 Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and 3939 Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style: 3940 Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width; 3941 apply to Path created from blob. 3942 3943 #Param blob Glyphs, positions, and their paints' text size, typeface, and so on ## 3944 #Param x horizontal offset applied to blob ## 3945 #Param y vertical offset applied to blob ## 3946 #Param paint blend, color, stroking, and so on, used to draw ## 3947 3948 #Example 3949 #Height 120 3950 void draw(SkCanvas* canvas) { 3951 SkTextBlobBuilder textBlobBuilder; 3952 const char bunny[] = "/(^x^)\\"; 3953 const int len = sizeof(bunny) - 1; 3954 uint16_t glyphs[len]; 3955 SkFont font; 3956 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, len); 3957 int runs[] = { 3, 1, 3 }; 3958 SkPoint textPos = { 20, 100 }; 3959 int glyphIndex = 0; 3960 for (auto runLen : runs) { 3961 font.setSize(1 == runLen ? 20 : 50); 3962 const SkTextBlobBuilder::RunBuffer& run = 3963 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY); 3964 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen); 3965 font.setSize(1 == runLen ? 20 : 50); 3966 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, 3967 SkTextEncoding::kGlyphID); 3968 glyphIndex += runLen; 3969 } 3970 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 3971 canvas->drawTextBlob(blob.get(), 0, 0, SkPaint()); 3972 } 3973 ## 3974 3975 #SeeAlso drawText 3976 3977 ## 3978 3979 # ------------------------------------------------------------------------------ 3980 3981 #Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) 3982 3983 Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint. 3984 3985 blob contains Glyphs, their positions, and paint attributes specific to text: 3986 #font_metrics#. 3987 3988 Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding. 3989 3990 Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter, 3991 Image_Filter, and Draw_Looper; apply to blob. 3992 3993 #Param blob Glyphs, positions, and their paints' text size, typeface, and so on ## 3994 #Param x horizontal offset applied to blob ## 3995 #Param y vertical offset applied to blob ## 3996 #Param paint blend, color, stroking, and so on, used to draw ## 3997 3998 #Example 3999 #Height 120 4000 #Description 4001 Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob. 4002 ## 4003 void draw(SkCanvas* canvas) { 4004 SkTextBlobBuilder textBlobBuilder; 4005 SkFont font; 4006 font.setSize(50); 4007 const SkTextBlobBuilder::RunBuffer& run = 4008 textBlobBuilder.allocRun(font, 1, 20, 100); 4009 run.glyphs[0] = 20; 4010 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 4011 SkPaint paint; 4012 paint.setTextSize(10); 4013 paint.setColor(SK_ColorBLUE); 4014 canvas->drawTextBlob(blob.get(), 0, 0, paint); 4015 } 4016 ## 4017 4018 #SeeAlso drawText 4019 4020 ## 4021 4022 # ------------------------------------------------------------------------------ 4023 4024 #Method void drawPicture(const SkPicture* picture) 4025 #In Draw 4026 #Line # draws Picture using Clip and Matrix ## 4027 #Populate 4028 4029 #Example 4030 void draw(SkCanvas* canvas) { 4031 SkPictureRecorder recorder; 4032 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 4033 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 4034 SkPaint paint; 4035 paint.setColor(color); 4036 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 4037 recordingCanvas->translate(10, 10); 4038 recordingCanvas->scale(1.2f, 1.4f); 4039 } 4040 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 4041 canvas->drawPicture(playback); 4042 canvas->scale(2, 2); 4043 canvas->translate(50, 0); 4044 canvas->drawPicture(playback); 4045 } 4046 ## 4047 4048 #SeeAlso drawDrawable SkPicture SkPicture::playback 4049 4050 ## 4051 4052 # ------------------------------------------------------------------------------ 4053 4054 #Method void drawPicture(const sk_sp<SkPicture>& picture) 4055 #Populate 4056 4057 #Example 4058 void draw(SkCanvas* canvas) { 4059 SkPictureRecorder recorder; 4060 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 4061 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 4062 SkPaint paint; 4063 paint.setColor(color); 4064 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 4065 recordingCanvas->translate(10, 10); 4066 recordingCanvas->scale(1.2f, 1.4f); 4067 } 4068 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 4069 canvas->drawPicture(playback); 4070 canvas->scale(2, 2); 4071 canvas->translate(50, 0); 4072 canvas->drawPicture(playback); 4073 } 4074 ## 4075 4076 #SeeAlso drawDrawable SkPicture SkPicture::playback 4077 4078 ## 4079 4080 # ------------------------------------------------------------------------------ 4081 4082 #Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) 4083 #Populate 4084 4085 #Example 4086 void draw(SkCanvas* canvas) { 4087 SkPaint paint; 4088 SkPictureRecorder recorder; 4089 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 4090 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 4091 paint.setColor(color); 4092 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 4093 recordingCanvas->translate(10, 10); 4094 recordingCanvas->scale(1.2f, 1.4f); 4095 } 4096 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 4097 const SkPicture* playbackPtr = playback.get(); 4098 SkMatrix matrix; 4099 matrix.reset(); 4100 for (auto alpha : { 70, 140, 210 } ) { 4101 paint.setAlpha(alpha); 4102 canvas->drawPicture(playbackPtr, &matrix, &paint); 4103 matrix.preTranslate(70, 70); 4104 } 4105 } 4106 ## 4107 4108 #SeeAlso drawDrawable SkPicture SkPicture::playback 4109 4110 ## 4111 4112 # ------------------------------------------------------------------------------ 4113 4114 #Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) 4115 #Populate 4116 4117 #Example 4118 void draw(SkCanvas* canvas) { 4119 SkPaint paint; 4120 SkPictureRecorder recorder; 4121 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50); 4122 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) { 4123 paint.setColor(color); 4124 recordingCanvas->drawRect({10, 10, 30, 40}, paint); 4125 recordingCanvas->translate(10, 10); 4126 recordingCanvas->scale(1.2f, 1.4f); 4127 } 4128 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture(); 4129 SkMatrix matrix; 4130 matrix.reset(); 4131 for (auto alpha : { 70, 140, 210 } ) { 4132 paint.setAlpha(alpha); 4133 canvas->drawPicture(playback, &matrix, &paint); 4134 matrix.preTranslate(70, 70); 4135 } 4136 } 4137 ## 4138 4139 #SeeAlso drawDrawable SkPicture SkPicture::playback 4140 4141 ## 4142 4143 # ------------------------------------------------------------------------------ 4144 4145 #Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) 4146 #In Draw 4147 #Line # draws Vertices, a triangle mesh ## 4148 #Populate 4149 4150 #Example 4151 void draw(SkCanvas* canvas) { 4152 SkPaint paint; 4153 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } }; 4154 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 4155 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 4156 SK_ARRAY_COUNT(points), points, nullptr, colors); 4157 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint); 4158 } 4159 ## 4160 4161 #SeeAlso drawPatch drawPicture 4162 4163 ## 4164 4165 # ------------------------------------------------------------------------------ 4166 4167 #Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint) 4168 #Populate 4169 4170 #Example 4171 void draw(SkCanvas* canvas) { 4172 SkPaint paint; 4173 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } }; 4174 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } }; 4175 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 4176 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4, 4177 SkShader::kClamp_TileMode)); 4178 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 4179 SK_ARRAY_COUNT(points), points, texs, colors); 4180 canvas->drawVertices(vertices, SkBlendMode::kDarken, paint); 4181 } 4182 ## 4183 4184 #SeeAlso drawPatch drawPicture 4185 4186 ## 4187 4188 # ------------------------------------------------------------------------------ 4189 4190 #Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[], 4191 int boneCount, SkBlendMode mode, const SkPaint& paint) 4192 #Populate 4193 4194 #NoExample 4195 void draw(SkCanvas* canvas) { 4196 SkPaint paint; 4197 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } }; 4198 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } }; 4199 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 4200 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 }, 4201 { 1, 0, 0, 0 }, 4202 { 2, 0, 0, 0 }, 4203 { 3, 0, 0, 0 } }; 4204 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f }, 4205 { 1.0f, 0.0f, 0.0f, 0.0f }, 4206 { 1.0f, 0.0f, 0.0f, 0.0f }, 4207 { 1.0f, 0.0f, 0.0f, 0.0f } }; 4208 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}, 4209 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }}, 4210 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }}, 4211 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} }; 4212 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4, 4213 SkShader::kClamp_TileMode)); 4214 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 4215 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights); 4216 canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint); 4217 } 4218 ## 4219 4220 #SeeAlso drawPatch drawPicture 4221 4222 ## 4223 4224 # ------------------------------------------------------------------------------ 4225 4226 #Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[], 4227 int boneCount, SkBlendMode mode, const SkPaint& paint) 4228 #Populate 4229 4230 #NoExample 4231 void draw(SkCanvas* canvas) { 4232 SkPaint paint; 4233 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } }; 4234 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } }; 4235 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 4236 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 }, 4237 { 1, 0, 0, 0 }, 4238 { 2, 0, 0, 0 }, 4239 { 3, 0, 0, 0 } }; 4240 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f }, 4241 { 1.0f, 0.0f, 0.0f, 0.0f }, 4242 { 1.0f, 0.0f, 0.0f, 0.0f }, 4243 { 1.0f, 0.0f, 0.0f, 0.0f } }; 4244 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}, 4245 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }}, 4246 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }}, 4247 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} }; 4248 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4, 4249 SkShader::kClamp_TileMode)); 4250 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 4251 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights); 4252 canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint); 4253 } 4254 ## 4255 4256 #SeeAlso drawPatch drawPicture 4257 4258 ## 4259 4260 # ------------------------------------------------------------------------------ 4261 4262 #Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 4263 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint) 4264 #In Draw 4265 #Line # draws Coons_Patch ## 4266 #Populate 4267 4268 #Example 4269 #Image 5 4270 void draw(SkCanvas* canvas) { 4271 // SkBitmap source = cmbkygk; 4272 SkPaint paint; 4273 paint.setFilterQuality(kLow_SkFilterQuality); 4274 paint.setAntiAlias(true); 4275 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 }, 4276 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 }, 4277 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 }, 4278 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ }; 4279 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff }; 4280 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} }; 4281 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode, 4282 SkShader::kClamp_TileMode, nullptr)); 4283 canvas->scale(15, 15); 4284 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) { 4285 canvas->drawPatch(cubics, colors, texCoords, blend, paint); 4286 canvas->translate(4, 4); 4287 } 4288 } 4289 ## 4290 4291 #ToDo can patch use image filter? ## 4292 #SeeAlso drawVertices drawPicture 4293 4294 ## 4295 4296 # ------------------------------------------------------------------------------ 4297 4298 #Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4], 4299 const SkPoint texCoords[4], const SkPaint& paint) 4300 #Populate 4301 4302 #Example 4303 void draw(SkCanvas* canvas) { 4304 SkPaint paint; 4305 paint.setAntiAlias(true); 4306 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 }, 4307 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 }, 4308 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 }, 4309 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ }; 4310 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN }; 4311 canvas->scale(30, 30); 4312 canvas->drawPatch(cubics, colors, nullptr, paint); 4313 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f}, 4314 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f}, 4315 {0.5f,3.2f} }; 4316 4317 SkFont font(nullptr, 18.f / 30); 4318 for (int i = 0; i< 10; ++i) { 4319 char digit = '0' + i; 4320 canvas->drawSimpleText(&digit, kUTF8_SkTextEncoding, 1, text[i].fX, text[i].fY, font, paint); 4321 } 4322 canvas->drawString("10", text[10].fX, text[10].fY, font, paint); 4323 canvas->drawString("11", text[11].fX, text[11].fY, font, paint); 4324 paint.setStyle(SkPaint::kStroke_Style); 4325 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint); 4326 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint); 4327 } 4328 ## 4329 4330 #Example 4331 #Image 6 4332 void draw(SkCanvas* canvas) { 4333 // SkBitmap source = checkerboard; 4334 SkPaint paint; 4335 paint.setFilterQuality(kLow_SkFilterQuality); 4336 paint.setAntiAlias(true); 4337 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 }, 4338 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 }, 4339 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 }, 4340 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ }; 4341 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } }; 4342 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode, 4343 SkShader::kClamp_TileMode, nullptr)); 4344 canvas->scale(30, 30); 4345 canvas->drawPatch(cubics, nullptr, texCoords, paint); 4346 } 4347 ## 4348 4349 #ToDo can patch use image filter? ## 4350 #SeeAlso drawVertices drawPicture 4351 4352 ## 4353 4354 # ------------------------------------------------------------------------------ 4355 4356 #Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], 4357 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect, 4358 const SkPaint* paint) 4359 #In Draw 4360 #Line # draws sprites using Clip, Matrix, and Paint ## 4361 #Populate 4362 4363 #Example 4364 #Image 3 4365 void draw(SkCanvas* canvas) { 4366 // SkBitmap source = mandrill; 4367 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } }; 4368 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; 4369 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf }; 4370 const SkImage* imagePtr = image.get(); 4371 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr); 4372 } 4373 ## 4374 4375 #SeeAlso drawBitmap drawImage 4376 4377 ## 4378 4379 # ------------------------------------------------------------------------------ 4380 4381 #Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[], 4382 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect, 4383 const SkPaint* paint) 4384 #Populate 4385 4386 #Example 4387 #Image 3 4388 void draw(SkCanvas* canvas) { 4389 // SkBitmap source = mandrill; 4390 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } }; 4391 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; 4392 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf }; 4393 SkPaint paint; 4394 paint.setAlpha(127); 4395 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint); 4396 } 4397 ## 4398 4399 #ToDo bug in example on cpu side, gpu looks ok ## 4400 4401 #SeeAlso drawBitmap drawImage 4402 4403 ## 4404 4405 # ------------------------------------------------------------------------------ 4406 4407 #Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count, 4408 const SkRect* cullRect, const SkPaint* paint) 4409 #Populate 4410 4411 #Example 4412 #Image 3 4413 void draw(SkCanvas* canvas) { 4414 // sk_sp<SkImage> image = mandrill; 4415 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } }; 4416 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } }; 4417 const SkImage* imagePtr = image.get(); 4418 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr); 4419 } 4420 ## 4421 4422 #SeeAlso drawBitmap drawImage 4423 4424 ## 4425 4426 # ------------------------------------------------------------------------------ 4427 4428 #Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[], 4429 int count, const SkRect* cullRect, const SkPaint* paint) 4430 #Populate 4431 4432 #Example 4433 #Image 3 4434 void draw(SkCanvas* canvas) { 4435 // sk_sp<SkImage> image = mandrill; 4436 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } }; 4437 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } }; 4438 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr); 4439 } 4440 ## 4441 4442 #SeeAlso drawBitmap drawImage 4443 4444 ## 4445 4446 # ------------------------------------------------------------------------------ 4447 4448 #Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr) 4449 #In Draw 4450 #Line # draws Drawable, encapsulated drawing commands ## 4451 #Populate 4452 4453 #Example 4454 #Height 100 4455 #Function 4456 struct MyDrawable : public SkDrawable { 4457 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); } 4458 4459 void onDraw(SkCanvas* canvas) override { 4460 SkPath path; 4461 path.conicTo(10, 90, 50, 90, 0.9f); 4462 SkPaint paint; 4463 paint.setColor(SK_ColorBLUE); 4464 canvas->drawRect(path.getBounds(), paint); 4465 paint.setAntiAlias(true); 4466 paint.setColor(SK_ColorWHITE); 4467 canvas->drawPath(path, paint); 4468 } 4469 }; 4470 4471 #Function ## 4472 void draw(SkCanvas* canvas) { 4473 sk_sp<SkDrawable> drawable(new MyDrawable); 4474 SkMatrix matrix; 4475 matrix.setTranslate(10, 10); 4476 canvas->drawDrawable(drawable.get(), &matrix); 4477 } 4478 ## 4479 4480 #SeeAlso SkDrawable drawPicture 4481 4482 ## 4483 4484 # ------------------------------------------------------------------------------ 4485 4486 #Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y) 4487 #Populate 4488 4489 #Example 4490 #Height 100 4491 #Function 4492 struct MyDrawable : public SkDrawable { 4493 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); } 4494 4495 void onDraw(SkCanvas* canvas) override { 4496 SkPath path; 4497 path.conicTo(10, 90, 50, 90, 0.9f); 4498 SkPaint paint; 4499 paint.setColor(SK_ColorBLUE); 4500 canvas->drawRect(path.getBounds(), paint); 4501 paint.setAntiAlias(true); 4502 paint.setColor(SK_ColorWHITE); 4503 canvas->drawPath(path, paint); 4504 } 4505 }; 4506 4507 #Function ## 4508 void draw(SkCanvas* canvas) { 4509 sk_sp<SkDrawable> drawable(new MyDrawable); 4510 canvas->drawDrawable(drawable.get(), 10, 10); 4511 } 4512 ## 4513 4514 #SeeAlso SkDrawable drawPicture 4515 4516 ## 4517 4518 # ------------------------------------------------------------------------------ 4519 4520 #Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value) 4521 #In Draw 4522 #In Utility 4523 #Line # associates a Rect with a key-value pair ## 4524 #Populate 4525 4526 #Example 4527 #Height 1 4528 const char text[] = "Click this link!"; 4529 SkRect bounds; 4530 SkPaint paint; 4531 SkFont font(nullptr, 40); 4532 (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 4533 const char url[] = "https://www.google.com/"; 4534 sk_sp<SkData> urlData(SkData::MakeWithCString(url)); 4535 canvas->drawAnnotation(bounds, "url_key", urlData.get()); 4536 ## 4537 4538 #SeeAlso SkPicture SkDocument 4539 4540 ## 4541 4542 # ------------------------------------------------------------------------------ 4543 4544 #Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) 4545 #Populate 4546 4547 #Example 4548 #Height 1 4549 const char text[] = "Click this link!"; 4550 SkRect bounds; 4551 SkPaint paint; 4552 SkFont font(nullptr, 40); 4553 (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 4554 const char url[] = "https://www.google.com/"; 4555 sk_sp<SkData> urlData(SkData::MakeWithCString(url)); 4556 canvas->drawAnnotation(bounds, "url_key", urlData.get()); 4557 ## 4558 4559 #SeeAlso SkPicture SkDocument 4560 4561 ## 4562 4563 # ------------------------------------------------------------------------------ 4564 4565 #Method virtual bool isClipEmpty() const 4566 #In Property 4567 #Line # returns if Clip is empty ## 4568 #Populate 4569 4570 #Example 4571 void draw(SkCanvas* canvas) { 4572 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not"); 4573 SkPath path; 4574 canvas->clipPath(path); 4575 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not"); 4576 } 4577 #StdOut 4578 clip is not empty 4579 clip is empty 4580 ## 4581 ## 4582 4583 #SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds 4584 4585 ## 4586 4587 # ------------------------------------------------------------------------------ 4588 4589 #Method virtual bool isClipRect() const 4590 #In Property 4591 #Line # returns if Clip is Rect and not empty ## 4592 #Populate 4593 4594 #Example 4595 void draw(SkCanvas* canvas) { 4596 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not"); 4597 canvas->clipRect({0, 0, 0, 0}); 4598 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not"); 4599 } 4600 #StdOut 4601 clip is rect 4602 clip is not rect 4603 ## 4604 ## 4605 4606 #SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds 4607 4608 ## 4609 4610 #Class SkCanvas ## 4611 4612 #Topic Canvas ## 4613