1 #Topic Paint 2 #Alias Paint_Reference ## 3 4 #Class SkPaint 5 6 #Code 7 #Populate 8 ## 9 10 Paint controls options applied when drawing and measuring. Paint collects all 11 options outside of the Canvas_Clip and Canvas_Matrix. 12 13 Various options apply to text, strokes and fills, and images. 14 15 Some options may not be implemented on all platforms; in these cases, setting 16 the option has no effect. Some options are conveniences that duplicate Canvas 17 functionality; for instance, text size is identical to matrix scale. 18 19 Paint options are rarely exclusive; each option modifies a stage of the drawing 20 pipeline and multiple pipeline stages may be affected by a single Paint. 21 22 Paint collects effects and filters that describe single-pass and multiple-pass 23 algorithms that alter the drawing geometry, color, and transparency. For instance, 24 Paint does not directly implement dashing or blur, but contains the objects that do so. 25 26 The objects contained by Paint are opaque, and cannot be edited outside of the Paint 27 to affect it. The implementation is free to defer computations associated with the 28 Paint, or ignore them altogether. For instance, some GPU implementations draw all 29 Path geometries with Anti_Aliasing. 30 31 Paint describes a single color, a single font, a single image quality, and so on. 32 Multiple colors are drawn either by using multiple paints or with objects like 33 Shader attached to Paint. 34 35 #Method SkPaint() 36 #Line # constructs with default values ## 37 Constructs Paint with default values. 38 39 #Table 40 #Legend 41 # attribute # default value ## 42 #Legend ## 43 # Anti_Alias # false ## 44 # Blend_Mode # SkBlendMode::kSrcOver ## 45 # Color # SK_ColorBLACK ## 46 # Color_Alpha # 255 ## 47 # Color_Filter # nullptr ## 48 # Dither # false ## 49 # Draw_Looper # nullptr ## 50 # Filter_Quality # kNone_SkFilterQuality ## 51 # Image_Filter # nullptr ## 52 # Miter_Limit # 4 ## 53 # Mask_Filter # nullptr ## 54 # Path_Effect # nullptr ## 55 # Shader # nullptr ## 56 # Style # kFill_Style ## 57 # Stroke_Cap # kButt_Cap ## 58 # Stroke_Join # kMiter_Join ## 59 # Stroke_Width # 0 ## 60 #Table ## 61 62 The miter limit may be overridden at compile time by defining 63 paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the 64 build system. 65 66 #Return default initialized Paint ## 67 68 #Example 69 #ToDo mark this as no output ## 70 #Height 1 71 ###$ $ redefine markup character so preprocessor commands appear normally 72 #ifndef SkUserConfig_DEFINED 73 #define SkUserConfig_DEFINED 74 75 #define SkPaintDefaults_TextSize 24.f // double default font size 76 #define SkPaintDefaults_Hinting 3 // use full hinting 77 #define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting 78 79 #endif 80 $$$# # restore original markup character 81 ## 82 83 84 ## 85 86 #Method SkPaint(const SkPaint& paint) 87 #Line # makes a shallow copy ## 88 #Populate 89 90 #Example 91 #ToDo why is this double-spaced on Fiddle? ## 92 SkPaint paint1; 93 paint1.setColor(SK_ColorRED); 94 SkPaint paint2(paint1); 95 paint2.setColor(SK_ColorBLUE); 96 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!'); 97 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!'); 98 99 #StdOut 100 SK_ColorRED == paint1.getColor() 101 SK_ColorBLUE == paint2.getColor() 102 ## 103 ## 104 105 ## 106 107 #Method SkPaint(SkPaint&& paint) 108 #Line # moves paint without copying it ## 109 #Populate 110 111 #Example 112 SkPaint paint; 113 float intervals[] = { 5, 5 }; 114 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f)); 115 SkPaint dashed(std::move(paint)); 116 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false"); 117 118 #StdOut 119 path effect unique: true 120 ## 121 ## 122 123 ## 124 125 # ------------------------------------------------------------------------------ 126 127 #Method void reset() 128 #In Constructors 129 #Line # sets to default values ## 130 #Populate 131 132 #Example 133 SkPaint paint1, paint2; 134 paint1.setColor(SK_ColorRED); 135 paint1.reset(); 136 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!'); 137 138 #StdOut 139 paint1 == paint2 140 ## 141 ## 142 143 ## 144 145 # ------------------------------------------------------------------------------ 146 147 #Method ~SkPaint() 148 #Line # decreases Reference_Count of owned objects ## 149 #Populate 150 151 #NoExample 152 ## 153 154 ## 155 156 157 # ------------------------------------------------------------------------------ 158 159 #Subtopic Management 160 #Line # paint copying, moving, comparing ## 161 ## 162 163 #Method SkPaint& operator=(const SkPaint& paint) 164 #In Management 165 #Line # makes a shallow copy ## 166 #Populate 167 168 #Example 169 SkPaint paint1, paint2; 170 paint1.setColor(SK_ColorRED); 171 paint2 = paint1; 172 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!'); 173 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!'); 174 175 #StdOut 176 SK_ColorRED == paint1.getColor() 177 SK_ColorRED == paint2.getColor() 178 ## 179 ## 180 181 ## 182 183 # ------------------------------------------------------------------------------ 184 185 #Method SkPaint& operator=(SkPaint&& paint) 186 #In Management 187 #Line # moves paint without copying it ## 188 #Populate 189 190 #Example 191 SkPaint paint1, paint2; 192 paint1.setColor(SK_ColorRED); 193 paint2 = std::move(paint1); 194 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!'); 195 196 #StdOut 197 SK_ColorRED == paint2.getColor() 198 ## 199 ## 200 201 ## 202 203 # ------------------------------------------------------------------------------ 204 205 #Method bool operator==(const SkPaint& a, const SkPaint& b) 206 #Line # compares paints for equality ## 207 #Populate 208 209 #Example 210 SkPaint paint1, paint2; 211 paint1.setColor(SK_ColorRED); 212 paint2.setColor(0xFFFF0000); 213 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 214 float intervals[] = { 5, 5 }; 215 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f)); 216 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f)); 217 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 218 219 #StdOut 220 paint1 == paint2 221 paint1 != paint2 222 ## 223 ## 224 #SeeAlso operator!=(const SkPaint& a, const SkPaint& b) 225 ## 226 227 # ------------------------------------------------------------------------------ 228 229 #Method bool operator!=(const SkPaint& a, const SkPaint& b) 230 #Line # compares paints for inequality ## 231 #Populate 232 233 #Example 234 SkPaint paint1, paint2; 235 paint1.setColor(SK_ColorRED); 236 paint2.setColor(0xFFFF0000); 237 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 238 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '='); 239 240 #StdOut 241 paint1 == paint2 242 paint1 == paint2 243 ## 244 ## 245 #SeeAlso operator==(const SkPaint& a, const SkPaint& b) 246 ## 247 248 # ------------------------------------------------------------------------------ 249 250 #Method uint32_t getHash() const 251 #In Management 252 #Line # returns a shallow hash for equality checks ## 253 #Populate 254 255 #Example 256 SkPaint paint1, paint2; 257 paint1.setColor(SK_ColorRED); 258 paint2.setColor(0xFFFF0000); 259 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 260 SkDebugf("paint1.getHash() %c= paint2.getHash()\n", 261 paint1.getHash() == paint2.getHash() ? '=' : '!'); 262 263 #StdOut 264 paint1 == paint2 265 paint1.getHash() == paint2.getHash() 266 ## 267 ## 268 269 ## 270 271 # ------------------------------------------------------------------------------ 272 #Subtopic Anti_Alias 273 #Alias Anti_Alias 274 #Substitute anti-alias 275 ## 276 #Alias Anti_Aliased 277 #Substitute anti-aliased 278 ## 279 #Alias Anti_Aliasing 280 #Substitute anti-aliasing 281 ## 282 #In Related_Function 283 #Line # approximating coverage with transparency ## 284 285 Anti_Alias drawing approximates partial pixel coverage with transparency. 286 287 The rule for Aliased pixels is inconsistent across platforms. A shape edge 288 passing through the pixel center may, but is not required to, draw the pixel. 289 290 Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an 291 active Path edge, and whose center is to the left of the end of the active Path edge. 292 293 #ToDo add illustration of raster pixels ## 294 295 A platform may only support Anti_Aliased drawing. Some GPU-backed platforms use 296 Supersampling to Anti_Alias all drawing, and have no mechanism to selectively 297 Alias. 298 299 The amount of coverage computed for Anti_Aliased pixels also varies across platforms. 300 301 Anti_Alias is disabled by default. 302 303 #Example 304 #Width 512 305 #Description 306 A red line is drawn with transparency on the edges to make it look smoother. 307 A blue line draws only where the pixel centers are contained. 308 The lines are drawn into Bitmap, then drawn magnified to make the 309 Aliasing easier to see. 310 ## 311 312 void draw(SkCanvas* canvas) { 313 SkBitmap bitmap; 314 bitmap.allocN32Pixels(50, 50); 315 SkCanvas offscreen(bitmap); 316 SkPaint paint; 317 paint.setStyle(SkPaint::kStroke_Style); 318 paint.setStrokeWidth(10); 319 for (bool antialias : { false, true }) { 320 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE); 321 paint.setAntiAlias(antialias); 322 bitmap.eraseColor(0); 323 offscreen.drawLine(5, 5, 15, 30, paint); 324 canvas->drawLine(5, 5, 15, 30, paint); 325 canvas->save(); 326 canvas->scale(10, 10); 327 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0); 328 canvas->restore(); 329 canvas->translate(15, 0); 330 } 331 } 332 ## 333 #Subtopic Anti_Alias ## 334 335 #Method bool isAntiAlias() const 336 #In Anti_alias 337 #Line # returns true if Anti_Alias is set ## 338 #Populate 339 340 #Example 341 SkPaint paint; 342 ## 343 ## 344 345 #Method void setAntiAlias(bool aa) 346 #In Anti_alias 347 #Line # sets or clears Anti_Alias ## 348 #Populate 349 350 #Example 351 SkPaint paint; 352 ## 353 ## 354 355 # ------------------------------------------------------------------------------ 356 #Subtopic Dither 357 #Line # distributing color error ## 358 359 Dither increases fidelity by adjusting the color of adjacent pixels. 360 This can help to smooth color transitions and reducing banding in gradients. 361 Dithering lessens visible banding from kRGB_565_SkColorType 362 and kRGBA_8888_SkColorType gradients, 363 and improves rendering into a kRGB_565_SkColorType Surface. 364 365 Dithering is always enabled for linear gradients drawing into 366 kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface. 367 Dither cannot be enabled for kAlpha_8_SkColorType Surface and 368 kRGBA_F16_SkColorType Surface. 369 370 Dither is disabled by default. 371 372 Some platform implementations may ignore dithering. Set #Formula # SK_IGNORE_GPU_DITHER ## 373 to ignore Dither on GPU_Surface. 374 375 #Example 376 #Description 377 Dithering in the bottom half more closely approximates the requested color by 378 alternating nearby colors from pixel to pixel. 379 ## 380 void draw(SkCanvas* canvas) { 381 SkBitmap bm16; 382 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType)); 383 SkCanvas c16(bm16); 384 SkPaint colorPaint; 385 for (auto dither : { false, true } ) { 386 colorPaint.setDither(dither); 387 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) { 388 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) { 389 colorPaint.setColor(colors & mask); 390 c16.drawRect({0, 0, 8, 4}, colorPaint); 391 c16.translate(8, 0); 392 } 393 c16.translate(-32, 4); 394 } 395 } 396 canvas->scale(8, 8); 397 canvas->drawBitmap(bm16, 0, 0); 398 } 399 ## 400 401 #Example 402 #Description 403 Dithering introduces subtle adjustments to color to smooth gradients. 404 Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the 405 dither, making it easier to see. 406 ## 407 void draw(SkCanvas* canvas) { 408 canvas->clear(0); 409 SkBitmap bm32; 410 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType)); 411 SkCanvas c32(bm32); 412 SkPoint points[] = {{0, 0}, {20, 0}}; 413 SkColor colors[] = {0xFF334455, 0xFF662211 }; 414 SkPaint paint; 415 paint.setShader(SkGradientShader::MakeLinear( 416 points, colors, nullptr, SK_ARRAY_COUNT(colors), 417 SkShader::kClamp_TileMode, 0, nullptr)); 418 paint.setDither(true); 419 c32.drawPaint(paint); 420 canvas->scale(12, 12); 421 canvas->drawBitmap(bm32, 0, 0); 422 paint.setBlendMode(SkBlendMode::kPlus); 423 canvas->drawBitmap(bm32, 0, 11, &paint); 424 canvas->drawBitmap(bm32, 0, 11, &paint); 425 canvas->drawBitmap(bm32, 0, 11, &paint); 426 } 427 ## 428 #SeeAlso Gradient kRGB_565_SkColorType 429 #Subtopic Dither ## 430 431 #Method bool isDither() const 432 #In Dither 433 #Line # returns true if Dither is set ## 434 #Populate 435 436 #Example 437 SkPaint paint; 438 ## 439 ## 440 441 #Method void setDither(bool dither) 442 #In Dither 443 #Line # sets or clears Dither ## 444 #Populate 445 446 #Example 447 SkPaint paint; 448 ## 449 450 #SeeAlso kRGB_565_SkColorType 451 452 ## 453 454 # ------------------------------------------------------------------------------ 455 #Subtopic Filter_Quality_Methods 456 #Line # get and set Filter_Quality ## 457 458 Filter_Quality trades speed for image filtering when the image is scaled. 459 A lower Filter_Quality draws faster, but has less fidelity. 460 A higher Filter_Quality draws slower, but looks better. 461 If the image is drawn without scaling, the Filter_Quality choice will not result 462 in a noticeable difference. 463 464 Filter_Quality is used in Paint passed as a parameter to 465 #List 466 # SkCanvas::drawBitmap ## 467 # SkCanvas::drawBitmapRect ## 468 # SkCanvas::drawImage ## 469 # SkCanvas::drawImageRect ## 470 #ToDo probably more... ## 471 #List ## 472 and when Paint has a Shader specialization that uses Image or Bitmap. 473 474 Filter_Quality is kNone_SkFilterQuality by default. 475 476 #Example 477 #Image 3 478 void draw(SkCanvas* canvas) { 479 SkPaint paint; 480 canvas->scale(.2f, .2f); 481 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality, 482 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) { 483 paint.setFilterQuality(q); 484 canvas->drawImage(image.get(), 0, 0, &paint); 485 canvas->translate(550, 0); 486 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550); 487 } 488 } 489 ## 490 #Subtopic Filter_Quality_Methods ## 491 492 #Method SkFilterQuality getFilterQuality() const 493 #In Filter_Quality_Methods 494 #Line # returns Filter_Quality, image filtering level ## 495 #Populate 496 497 #Example 498 SkPaint paint; 499 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n", 500 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!'); 501 502 #StdOut 503 kNone_SkFilterQuality == paint.getFilterQuality() 504 ## 505 ## 506 507 ## 508 509 510 #Method void setFilterQuality(SkFilterQuality quality) 511 #In Filter_Quality_Methods 512 #Line # sets Filter_Quality, the image filtering level ## 513 #Populate 514 515 #Example 516 SkPaint paint; 517 paint.setFilterQuality(kHigh_SkFilterQuality); 518 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n", 519 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!'); 520 521 #StdOut 522 kHigh_SkFilterQuality == paint.getFilterQuality() 523 ## 524 ## 525 526 #SeeAlso SkFilterQuality Image_Scaling 527 528 ## 529 530 # ------------------------------------------------------------------------------ 531 #Subtopic Color_Methods 532 #Line # get and set Color ## 533 534 #Table 535 #Legend 536 # name # description ## 537 #Legend ## 538 # getColor # returns Color_Alpha and RGB, one drawing color ## 539 # setColor # sets Color_Alpha and RGB, one drawing color ## 540 #Table ## 541 542 Color specifies the red, blue, green, and Color_Alpha 543 values used to draw a filled or stroked shape in a 32-bit value. Each component 544 occupies 8-bits, ranging from zero: no contribution; to 255: full intensity. 545 All values in any combination are valid. 546 547 Color is not Premultiplied; Color_Alpha sets the transparency independent of 548 RGB: red, blue, and green. 549 550 The bit positions of Color_Alpha and RGB are independent of the bit 551 positions on the output device, which may have more or fewer bits, and may have 552 a different arrangement. 553 554 #Table 555 #Legend 556 # bit positions # Color_Alpha # red # blue # green ## 557 #Legend ## 558 # # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ## 559 #Table ## 560 561 #Example 562 #Height 128 563 void draw(SkCanvas* canvas) { 564 SkPaint paint; 565 paint.setColor(0x8000FF00); // transparent green 566 canvas->drawCircle(50, 50, 40, paint); 567 paint.setARGB(128, 255, 0, 0); // transparent red 568 canvas->drawCircle(80, 50, 40, paint); 569 paint.setColor(SK_ColorBLUE); 570 paint.setAlpha(0x80); 571 canvas->drawCircle(65, 65, 40, paint); 572 } 573 ## 574 #Subtopic Color_Methods ## 575 576 #Method SkColor getColor() const 577 #In Color_Methods 578 #Line # returns Color_Alpha and RGB, one drawing color ## 579 #Populate 580 581 #Example 582 SkPaint paint; 583 paint.setColor(SK_ColorYELLOW); 584 SkColor y = paint.getColor(); 585 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f), 586 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f)); 587 588 #StdOut 589 Yellow is 100% red, 100% green, and 0% blue. 590 ## 591 ## 592 593 #SeeAlso getColor4f SkColor 594 595 ## 596 597 #Method SkColor4f getColor4f() const 598 #In Color_Methods 599 #Line # returns Color_Alpha and RGB, one drawing color ## 600 #Populate 601 602 #Example 603 SkPaint paint; 604 paint.setColor(SK_ColorYELLOW); 605 SkColor4f y = paint.getColor4f(); 606 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (y.fR * 100), 607 (int) (y.fG * 100), (int) (y.fB * 100)); 608 609 #StdOut 610 Yellow is 100% red, 100% green, and 0% blue. 611 ## 612 ## 613 614 #SeeAlso getColor SkColor 615 ## 616 617 618 #Method void setColor(SkColor color) 619 #In Color_Methods 620 #Line # sets Color_Alpha and RGB, one drawing color ## 621 #Populate 622 623 #Example 624 SkPaint green1, green2; 625 unsigned a = 255; 626 unsigned r = 0; 627 unsigned g = 255; 628 unsigned b = 0; 629 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0)); 630 green2.setColor(0xFF00FF00); 631 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!'); 632 633 #StdOut 634 green1 == green2 635 ## 636 ## 637 638 #SeeAlso SkColor setColor4f setARGB SkColorSetARGB 639 640 ## 641 642 #Method void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace) 643 #In Color_Methods 644 #Line # sets Color_Alpha and RGB, one drawing color ## 645 #Populate 646 647 #Example 648 SkPaint green1, green2; 649 green1.setColor4f({0, 1, 0, 1}, nullptr); // R=0 G=1 B=0 A=1 650 green2.setColor(0xFF00FF00); // A=255 R=0 G=255 B=0 651 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!'); 652 653 #StdOut 654 green1 == green2 655 ## 656 ## 657 658 #SeeAlso SkColor setColor setARGB SkColorSetARGB 659 660 ## 661 662 #Subtopic Alpha_Methods 663 #Line # get and set Alpha ## 664 665 Color_Alpha sets the transparency independent of RGB: red, blue, and green. 666 #Subtopic Alpha_Methods ## 667 668 #Method uint8_t getAlpha() const 669 #In Alpha_Methods 670 #Line # returns Color_Alpha, color opacity ## 671 #Populate 672 673 #Example 674 SkPaint paint; 675 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!'); 676 677 #StdOut 678 255 == paint.getAlpha() 679 ## 680 ## 681 682 ## 683 684 #Method float getAlphaf() const 685 #In Alpha_Methods 686 #Line # returns Color_Alpha, color opacity ## 687 #Populate 688 689 #Example 690 SkPaint paint; 691 ## 692 693 ## 694 695 #Method void setAlpha(U8CPU a) 696 #In Alpha_Methods 697 #Line # sets Color_Alpha, color opacity ## 698 #Populate 699 700 #Example 701 SkPaint paint; 702 paint.setColor(0x00112233); 703 paint.setAlpha(0x44); 704 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!'); 705 706 #StdOut 707 0x44112233 == paint.getColor() 708 ## 709 ## 710 711 ## 712 713 #Method void setAlphaf(float a) 714 #In Alpha_Methods 715 #Line # sets Color_Alpha, color opacity ## 716 #Populate 717 718 #Example 719 SkPaint paint; 720 ## 721 722 ## 723 724 #Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 725 #In Color_Methods 726 #Line # sets color by component ## 727 #Populate 728 729 #Example 730 SkPaint transRed1, transRed2; 731 transRed1.setARGB(255 / 2, 255, 0, 0); 732 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0)); 733 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!'); 734 735 #StdOut 736 transRed1 == transRed2 737 ## 738 ## 739 740 #SeeAlso setColor SkColorSetARGB 741 742 ## 743 744 # ------------------------------------------------------------------------------ 745 #Subtopic Style 746 #Line # geometry filling, stroking ## 747 748 Style specifies if the geometry is filled, stroked, or both filled and stroked. 749 Some shapes ignore Style and are always drawn filled or stroked. 750 751 #Subtopic Fill 752 Set Style to kFill_Style to fill the shape. 753 The fill covers the area inside the geometry for most shapes. 754 #Subtopic Fill ## 755 756 #Subtopic Stroke 757 Set Style to kStroke_Style to stroke the shape. 758 759 The stroke covers the area described by following the shape edge with a pen or brush of 760 Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap. 761 The area covered where the shape turns a corner is described by Stroke_Join. 762 The stroke is centered on the shape; it extends equally on either side of the shape edge. 763 #Subtopic Stroke ## 764 765 As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one 766 may have gaps, and if antialiasing is on, Color_Alpha will increase to visually decrease coverage. 767 768 #SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke 769 #Subtopic Style ## 770 771 #Subtopic Hairline 772 Stroke_Width of zero has a special meaning and switches drawing to use Hairline. 773 Hairline draws the thinnest continuous frame. If antialiasing is off, adjacent pixels 774 flow horizontally, vertically,or diagonally. 775 776 #ToDo what is the description of Anti_Aliased hairlines? ## 777 778 Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing 779 two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent 780 pixel. If antialiasing is on, transparency is applied twice, resulting in a darker pixel. Some 781 GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels 782 while stroking. 783 784 #SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke 785 #Subtopic Hairline ## 786 787 #Enum Style 788 #Line # stroke, fill, or both ## 789 790 #Code 791 #Populate 792 ## 793 794 #Code 795 #In Constant 796 #Filter kStyle 797 #Populate 798 ## 799 800 Set Style to fill, stroke, or both fill and stroke geometry. 801 The stroke and fill 802 share all paint attributes; for instance, they are drawn with the same color. 803 804 Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and 805 a fill draw. 806 807 #Const kFill_Style 0 808 #Line # set to fill geometry ## 809 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text. 810 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if 811 kFill_Style is set, and ignore the set Style. 812 The Path_Fill_Type specifies additional rules to fill the area outside the path edge, 813 and to create an unfilled hole inside the shape. 814 Style is set to kFill_Style by default. 815 ## 816 817 #Const kStroke_Style 1 818 #Line # set to stroke geometry ## 819 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text. 820 Arcs, Lines, and points, are always drawn as if kStroke_Style is set, 821 and ignore the set Style. 822 The stroke construction is unaffected by the Path_Fill_Type. 823 ## 824 825 #Const kStrokeAndFill_Style 2 826 #Line # sets to stroke and fill geometry ## 827 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text. 828 Path is treated as if it is set to SkPath::kWinding_FillType, 829 and the set Path_Fill_Type is ignored. 830 ## 831 832 #Const kStyleCount 3 833 #Line # number of different Style values defined ## 834 May be used to verify that Style is a legal value. 835 ## 836 837 #Enum Style ## 838 839 #Method Style getStyle() const 840 #In Style 841 #Line # returns Style: stroke, fill, or both ## 842 #Populate 843 844 #Example 845 SkPaint paint; 846 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n", 847 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!'); 848 849 #StdOut 850 SkPaint::kFill_Style == paint.getStyle() 851 ## 852 ## 853 854 #SeeAlso Style setStyle 855 ## 856 857 #Method void setStyle(Style style) 858 #In Style 859 #Line # sets Style: stroke, fill, or both ## 860 #Populate 861 862 #Example 863 void draw(SkCanvas* canvas) { 864 SkPaint paint; 865 paint.setStrokeWidth(5); 866 SkRegion region; 867 region.op(140, 10, 160, 30, SkRegion::kUnion_Op); 868 region.op(170, 40, 190, 60, SkRegion::kUnion_Op); 869 SkBitmap bitmap; 870 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50); 871 uint8_t pixels[50][50]; 872 for (int x = 0; x < 50; ++x) { 873 for (int y = 0; y < 50; ++y) { 874 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00; 875 } 876 } 877 bitmap.setPixels(pixels); 878 for (auto style : { SkPaint::kFill_Style, 879 SkPaint::kStroke_Style, 880 SkPaint::kStrokeAndFill_Style }) { 881 paint.setStyle(style); 882 canvas->drawLine(10, 10, 60, 60, paint); 883 canvas->drawRect({80, 10, 130, 60}, paint); 884 canvas->drawRegion(region, paint); 885 canvas->drawBitmap(bitmap, 200, 10, &paint); 886 canvas->translate(0, 80); 887 } 888 } 889 ## 890 891 #SeeAlso Style getStyle 892 ## 893 894 # ------------------------------------------------------------------------------ 895 #Subtopic Stroke_Width 896 #Line # thickness perpendicular to geometry ## 897 898 Stroke_Width sets the width for stroking. The width is the thickness 899 of the stroke perpendicular to the path direction when the paint style is 900 set to kStroke_Style or kStrokeAndFill_Style. 901 902 When width is greater than zero, the stroke encompasses as many pixels partially 903 or fully as needed. When the width equals zero, the paint enables hairlines; 904 the stroke is always one pixel wide. 905 906 The stroke dimensions are scaled by the canvas matrix, but Hairline stroke 907 remains one pixel wide regardless of scaling. 908 909 The default width for the paint is zero. 910 911 #Example 912 #Height 170 913 #Platform raster gpu 914 #Description 915 The pixels hit to represent thin lines vary with the angle of the 916 line and the platform implementation. 917 ## 918 void draw(SkCanvas* canvas) { 919 SkPaint paint; 920 for (bool antialias : { false, true }) { 921 paint.setAntiAlias(antialias); 922 for (int width = 0; width <= 4; ++width) { 923 SkScalar offset = antialias * 100 + width * 20; 924 paint.setStrokeWidth(width * 0.25f); 925 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint); 926 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint); 927 } 928 } 929 } 930 ## 931 932 #Method SkScalar getStrokeWidth() const 933 934 #In Stroke_Width 935 #Line # returns thickness of the stroke ## 936 #Populate 937 938 #Example 939 SkPaint paint; 940 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!'); 941 942 #StdOut 943 0 == paint.getStrokeWidth() 944 ## 945 ## 946 947 ## 948 949 #Method void setStrokeWidth(SkScalar width) 950 951 #In Stroke_Width 952 #Line # sets thickness of the stroke ## 953 #Populate 954 955 #Example 956 SkPaint paint; 957 paint.setStrokeWidth(5); 958 paint.setStrokeWidth(-1); 959 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!'); 960 961 #StdOut 962 5 == paint.getStrokeWidth() 963 ## 964 ## 965 966 ## 967 968 #Subtopic Stroke_Width ## 969 # ------------------------------------------------------------------------------ 970 #Subtopic Miter_Limit 971 #Line # maximum length of stroked corners ## 972 973 Miter_Limit specifies the maximum miter length, 974 relative to the stroke width. 975 976 Miter_Limit is used when the Stroke_Join 977 is set to kMiter_Join, and the Style is either kStroke_Style 978 or kStrokeAndFill_Style. 979 980 If the miter at a corner exceeds this limit, kMiter_Join 981 is replaced with kBevel_Join. 982 983 Miter_Limit can be computed from the corner angle using: 984 #Formula # miter limit = 1 / sin ( angle / 2 ) ##. 985 986 Miter_Limit default value is 4. 987 The default may be changed at compile time by setting SkPaintDefaults_MiterLimit 988 in "SkUserConfig.h" or as a define supplied by the build environment. 989 990 Here are some miter limits and the angles that triggers them. 991 #Table 992 #Legend 993 # miter limit # angle in degrees ## 994 #Legend ## 995 # 10 # 11.48 ## 996 # 9 # 12.76 ## 997 # 8 # 14.36 ## 998 # 7 # 16.43 ## 999 # 6 # 19.19 ## 1000 # 5 # 23.07 ## 1001 # 4 # 28.96 ## 1002 # 3 # 38.94 ## 1003 # 2 # 60 ## 1004 # 1 # 180 ## 1005 #Table ## 1006 1007 #Example 1008 #Height 170 1009 #Width 384 1010 #Description 1011 This example draws a stroked corner and the miter length beneath. 1012 When the miter limit is decreased slightly, the miter join is replaced 1013 by a bevel join. 1014 ## 1015 void draw(SkCanvas* canvas) { 1016 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }}; 1017 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] }; 1018 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX); 1019 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX); 1020 const SkScalar strokeWidth = 20; 1021 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2); 1022 SkScalar miterLength = strokeWidth * miterLimit; 1023 SkPath path; 1024 path.moveTo(pts[0]); 1025 path.lineTo(pts[1]); 1026 path.lineTo(pts[2]); 1027 SkPaint paint; // set to default kMiter_Join 1028 paint.setAntiAlias(true); 1029 paint.setStyle(SkPaint::kStroke_Style); 1030 paint.setStrokeMiter(miterLimit); 1031 paint.setStrokeWidth(strokeWidth); 1032 canvas->drawPath(path, paint); 1033 paint.setStrokeWidth(1); 1034 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50, 1035 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint); 1036 canvas->translate(200, 0); 1037 miterLimit *= 0.99f; 1038 paint.setStrokeMiter(miterLimit); 1039 paint.setStrokeWidth(strokeWidth); 1040 canvas->drawPath(path, paint); 1041 paint.setStrokeWidth(1); 1042 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50, 1043 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint); 1044 } 1045 ## 1046 1047 #Method SkScalar getStrokeMiter() const 1048 1049 #In Miter_Limit 1050 #Line # returns Miter_Limit, angles with sharp corners ## 1051 #Populate 1052 1053 #Example 1054 SkPaint paint; 1055 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter()); 1056 1057 #StdOut 1058 default miter limit == 4 1059 ## 1060 ## 1061 1062 #SeeAlso Miter_Limit setStrokeMiter Join 1063 1064 ## 1065 1066 #Method void setStrokeMiter(SkScalar miter) 1067 1068 #In Miter_Limit 1069 #Line # sets Miter_Limit, angles with sharp corners ## 1070 #Populate 1071 1072 #Example 1073 SkPaint paint; 1074 paint.setStrokeMiter(8); 1075 paint.setStrokeMiter(-1); 1076 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter()); 1077 1078 #StdOut 1079 default miter limit == 8 1080 ## 1081 ## 1082 1083 #SeeAlso Miter_Limit getStrokeMiter Join 1084 1085 ## 1086 1087 #Subtopic Miter_Limit ## 1088 # ------------------------------------------------------------------------------ 1089 #Subtopic Stroke_Cap 1090 #Line # decorations at ends of open strokes ## 1091 #Subtopic Stroke_Cap ## 1092 1093 #Enum Cap 1094 #Line # start and end geometry on stroked shapes ## 1095 1096 #Code 1097 #Populate 1098 ## 1099 1100 #Code 1101 #In Constant 1102 #Filter kCap 1103 #Populate 1104 ## 1105 1106 Stroke_Cap draws at the beginning and end of an open Path_Contour. 1107 1108 #Const kButt_Cap 0 1109 #Line # no stroke extension ## 1110 Does not extend the stroke past the beginning or the end. 1111 ## 1112 #Const kRound_Cap 1 1113 #Line # adds circle ## 1114 Adds a circle with a diameter equal to Stroke_Width at the beginning 1115 and end. 1116 ## 1117 #Const kSquare_Cap 2 1118 #Line # adds square ## 1119 Adds a square with sides equal to Stroke_Width at the beginning 1120 and end. The square sides are parallel to the initial and final direction 1121 of the stroke. 1122 ## 1123 #Const kLast_Cap 2 1124 #Line # largest Stroke_Cap value ## 1125 Equivalent to the largest value for Stroke_Cap. 1126 ## 1127 #Const kDefault_Cap 0 1128 #Line # equivalent to kButt_Cap ## 1129 Stroke_Cap is set to kButt_Cap by default. 1130 ## 1131 1132 #Const kCapCount 3 1133 #Line # number of different Stroke_Cap values defined ## 1134 May be used to verify that Stroke_Cap is a legal value. 1135 ## 1136 #Enum ## 1137 1138 Stroke describes the area covered by a pen of Stroke_Width as it 1139 follows the Path_Contour, moving parallel to the contour direction. 1140 1141 If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a 1142 visible beginning and end. 1143 1144 Path_Contour may start and end at the same point; defining Zero_Length_Contour. 1145 1146 kButt_Cap and Zero_Length_Contour is not drawn. 1147 kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width 1148 at the contour point. 1149 kSquare_Cap and Zero_Length_Contour draws an upright square with a side of 1150 Stroke_Width at the contour point. 1151 1152 Stroke_Cap is kButt_Cap by default. 1153 1154 #Example 1155 #Height 200 1156 SkPaint paint; 1157 paint.setStyle(SkPaint::kStroke_Style); 1158 paint.setStrokeWidth(20); 1159 SkPath path; 1160 path.moveTo(30, 30); 1161 path.lineTo(30, 30); 1162 path.moveTo(70, 30); 1163 path.lineTo(90, 40); 1164 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) { 1165 paint.setStrokeCap(c); 1166 canvas->drawPath(path, paint); 1167 canvas->translate(0, 70); 1168 } 1169 ## 1170 1171 #Method Cap getStrokeCap() const 1172 1173 #In Stroke_Cap 1174 #Line # returns Cap, the area drawn at path ends ## 1175 #Populate 1176 1177 #Example 1178 SkPaint paint; 1179 SkDebugf("kButt_Cap %c= default stroke cap\n", 1180 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!'); 1181 1182 #StdOut 1183 kButt_Cap == default stroke cap 1184 ## 1185 ## 1186 1187 #SeeAlso Stroke_Cap setStrokeCap 1188 ## 1189 1190 #Method void setStrokeCap(Cap cap) 1191 1192 #In Stroke_Cap 1193 #Line # sets Cap, the area drawn at path ends ## 1194 #Populate 1195 1196 #Example 1197 SkPaint paint; 1198 paint.setStrokeCap(SkPaint::kRound_Cap); 1199 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount); 1200 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n", 1201 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!'); 1202 1203 #StdOut 1204 kRound_Cap == paint.getStrokeCap() 1205 ## 1206 ## 1207 1208 #SeeAlso Stroke_Cap getStrokeCap 1209 ## 1210 1211 # ------------------------------------------------------------------------------ 1212 #Subtopic Stroke_Join 1213 #Line # decoration at corners of strokes ## 1214 #Subtopic Stroke_Join ## 1215 1216 Stroke_Join draws at the sharp corners of an open or closed Path_Contour. 1217 1218 Stroke describes the area covered by a pen of Stroke_Width as it 1219 follows the Path_Contour, moving parallel to the contour direction. 1220 1221 If the contour direction changes abruptly, because the tangent direction leading 1222 to the end of a curve within the contour does not match the tangent direction of 1223 the following curve, the pair of curves meet at Stroke_Join. 1224 1225 #Example 1226 #Height 200 1227 SkPaint paint; 1228 paint.setStyle(SkPaint::kStroke_Style); 1229 paint.setStrokeWidth(20); 1230 SkPath path; 1231 path.moveTo(30, 20); 1232 path.lineTo(40, 40); 1233 path.conicTo(70, 20, 100, 20, .707f); 1234 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) { 1235 paint.setStrokeJoin(j); 1236 canvas->drawPath(path, paint); 1237 canvas->translate(0, 70); 1238 } 1239 ## 1240 1241 #Enum Join 1242 #Line # corner geometry on stroked shapes ## 1243 #Code 1244 #Populate 1245 ## 1246 1247 #Code 1248 #In Constant 1249 #Filter kJoin 1250 #Populate 1251 ## 1252 1253 Join specifies how corners are drawn when a shape is stroked. Join 1254 affects the four corners of a stroked rectangle, and the connected segments in a 1255 stroked path. 1256 1257 Choose miter join to draw sharp corners. Choose round join to draw a circle with a 1258 radius equal to the stroke width on top of the corner. Choose bevel join to minimally 1259 connect the thick strokes. 1260 1261 The fill path constructed to describe the stroked path respects the join setting but may 1262 not contain the actual join. For instance, a fill path constructed with round joins does 1263 not necessarily include circles at each connected segment. 1264 1265 #Const kMiter_Join 0 1266 #Line # extends to Miter_Limit ## 1267 Extends the outside corner to the extent allowed by Miter_Limit. 1268 If the extension exceeds Miter_Limit, kBevel_Join is used instead. 1269 ## 1270 1271 #Const kRound_Join 1 1272 #Line # adds circle ## 1273 Adds a circle with a diameter of Stroke_Width at the sharp corner. 1274 ## 1275 1276 #Const kBevel_Join 2 1277 #Line # connects outside edges ## 1278 Connects the outside edges of the sharp corner. 1279 ## 1280 1281 #Const kLast_Join 2 1282 #Line # equivalent to the largest value for Stroke_Join ## 1283 ## 1284 1285 #Const kDefault_Join 1 1286 #Line # equivalent to kMiter_Join ## 1287 Stroke_Join is set to kMiter_Join by default. 1288 ## 1289 1290 #Const kJoinCount 3 1291 #Line # number of different Stroke_Join values defined ## 1292 May be used to verify that Stroke_Join is a legal value. 1293 ## 1294 1295 #Example 1296 #Width 462 1297 void draw(SkCanvas* canvas) { 1298 SkPath path; 1299 path.moveTo(10, 50); 1300 path.quadTo(35, 110, 60, 210); 1301 path.quadTo(105, 110, 130, 10); 1302 SkPaint paint; // set to default kMiter_Join 1303 paint.setAntiAlias(true); 1304 paint.setStyle(SkPaint::kStroke_Style); 1305 paint.setStrokeWidth(20); 1306 canvas->drawPath(path, paint); 1307 canvas->translate(150, 0); 1308 paint.setStrokeJoin(SkPaint::kBevel_Join); 1309 canvas->drawPath(path, paint); 1310 canvas->translate(150, 0); 1311 paint.setStrokeJoin(SkPaint::kRound_Join); 1312 canvas->drawPath(path, paint); 1313 } 1314 ## 1315 1316 #SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter 1317 1318 #Enum ## 1319 1320 #Method Join getStrokeJoin() const 1321 1322 #In Stroke_Join 1323 #Line # returns Join, geometry on path corners ## 1324 #Populate 1325 1326 #Example 1327 SkPaint paint; 1328 SkDebugf("kMiter_Join %c= default stroke join\n", 1329 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!'); 1330 1331 #StdOut 1332 kMiter_Join == default stroke join 1333 ## 1334 ## 1335 1336 #SeeAlso Stroke_Join setStrokeJoin 1337 ## 1338 1339 #Method void setStrokeJoin(Join join) 1340 1341 #In Stroke_Join 1342 #Line # sets Join, geometry on path corners ## 1343 #Populate 1344 1345 #Example 1346 SkPaint paint; 1347 paint.setStrokeJoin(SkPaint::kMiter_Join); 1348 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount); 1349 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n", 1350 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!'); 1351 1352 #StdOut 1353 kMiter_Join == paint.getStrokeJoin() 1354 ## 1355 ## 1356 1357 #SeeAlso Stroke_Join getStrokeJoin 1358 ## 1359 1360 #SeeAlso Miter_Limit 1361 1362 # ------------------------------------------------------------------------------ 1363 #Subtopic Fill_Path 1364 #Line # make Path from Path_Effect, stroking ## 1365 1366 Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke. 1367 1368 If Paint contains Path_Effect, Path_Effect operates on the source Path; the result 1369 replaces the destination Path. Otherwise, the source Path is replaces the 1370 destination Path. 1371 1372 Fill Path can request the Path_Effect to restrict to a culling rectangle, but 1373 the Path_Effect is not required to do so. 1374 1375 If Style is kStroke_Style or kStrokeAndFill_Style, 1376 and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join, 1377 and Miter_Limit operate on the destination Path, replacing it. 1378 1379 Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry. 1380 1381 If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath 1382 returns false since Hairline has no filled equivalent. 1383 1384 #SeeAlso Style_Stroke Stroke_Width Path_Effect 1385 1386 #Subtopic Fill_Path ## 1387 1388 #Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect, 1389 SkScalar resScale = 1) const 1390 #In Fill_Path 1391 #Line # returns fill path equivalent to stroke ## 1392 #Populate 1393 1394 #Example 1395 #Height 192 1396 #Description 1397 A very small Quad stroke is turned into a filled path with increasing levels of precision. 1398 At the lowest precision, the Quad stroke is approximated by a rectangle. 1399 At the highest precision, the filled path has high fidelity compared to the original stroke. 1400 ## 1401 void draw(SkCanvas* canvas) { 1402 SkPaint strokePaint; 1403 strokePaint.setAntiAlias(true); 1404 strokePaint.setStyle(SkPaint::kStroke_Style); 1405 strokePaint.setStrokeWidth(.1f); 1406 SkPath strokePath; 1407 strokePath.moveTo(.08f, .08f); 1408 strokePath.quadTo(.09f, .08f, .17f, .17f); 1409 SkPath fillPath; 1410 SkPaint outlinePaint(strokePaint); 1411 outlinePaint.setStrokeWidth(2); 1412 SkMatrix scale = SkMatrix::MakeScale(300, 300); 1413 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) { 1414 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision); 1415 fillPath.transform(scale); 1416 canvas->drawPath(fillPath, outlinePaint); 1417 canvas->translate(60, 0); 1418 if (1.f == precision) canvas->translate(-180, 100); 1419 } 1420 strokePath.transform(scale); 1421 strokePaint.setStrokeWidth(30); 1422 canvas->drawPath(strokePath, strokePaint); 1423 } 1424 ## 1425 1426 ## 1427 1428 #Method bool getFillPath(const SkPath& src, SkPath* dst) const 1429 1430 #In Fill_Path 1431 #Populate 1432 1433 #Example 1434 #Height 128 1435 void draw(SkCanvas* canvas) { 1436 SkPaint paint; 1437 paint.setStyle(SkPaint::kStroke_Style); 1438 paint.setStrokeWidth(10); 1439 SkPath strokePath; 1440 strokePath.moveTo(20, 20); 1441 strokePath.lineTo(100, 100); 1442 canvas->drawPath(strokePath, paint); 1443 SkPath fillPath; 1444 paint.getFillPath(strokePath, &fillPath); 1445 paint.setStrokeWidth(2); 1446 canvas->translate(40, 0); 1447 canvas->drawPath(fillPath, paint); 1448 } 1449 ## 1450 1451 ## 1452 1453 # ------------------------------------------------------------------------------ 1454 #Subtopic Shader_Methods 1455 #Line # get and set Shader ## 1456 1457 Shader defines the colors used when drawing a shape. 1458 Shader may be an image, a gradient, or a computed fill. 1459 If Paint has no Shader, then Color fills the shape. 1460 1461 Shader is modulated by Color_Alpha component of Color. 1462 If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes 1463 the fill. 1464 1465 The drawn transparency can be modified without altering Shader, by changing Color_Alpha. 1466 1467 #Example 1468 void draw(SkCanvas* canvas) { 1469 SkPaint paint; 1470 SkPoint center = { 50, 50 }; 1471 SkScalar radius = 50; 1472 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 }; 1473 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, 1474 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); 1475 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) { 1476 paint.setAlpha((int) (a * 255)); 1477 canvas->drawCircle(center.fX, center.fY, radius, paint); 1478 canvas->translate(70, 70); 1479 } 1480 } 1481 ## 1482 1483 If Shader generates only Color_Alpha then all components of Color modulate the output. 1484 1485 #Example 1486 void draw(SkCanvas* canvas) { 1487 SkPaint paint; 1488 SkBitmap bitmap; 1489 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha 1490 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF }; 1491 bitmap.setPixels(pixels); 1492 paint.setShader(SkShader::MakeBitmapShader(bitmap, 1493 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode)); 1494 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 1495 paint.setColor(c); // all components in color affect shader 1496 canvas->drawCircle(50, 50, 50, paint); 1497 canvas->translate(70, 70); 1498 } 1499 } 1500 ## 1501 1502 #Method SkShader* getShader() const 1503 1504 #In Shader_Methods 1505 #Line # returns Shader, multiple drawing colors; gradients ## 1506 #Populate 1507 1508 #Example 1509 void draw(SkCanvas* canvas) { 1510 SkPaint paint; 1511 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '='); 1512 paint.setShader(SkShader::MakeEmptyShader()); 1513 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '='); 1514 } 1515 1516 #StdOut 1517 nullptr == shader 1518 nullptr != shader 1519 ## 1520 ## 1521 1522 ## 1523 1524 #Method sk_sp<SkShader> refShader() const 1525 1526 #In Shader_Methods 1527 #Line # references Shader, multiple drawing colors; gradients ## 1528 #Populate 1529 1530 #Example 1531 void draw(SkCanvas* canvas) { 1532 SkPaint paint1, paint2; 1533 paint1.setShader(SkShader::MakeEmptyShader()); 1534 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false"); 1535 paint2.setShader(paint1.refShader()); 1536 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false"); 1537 } 1538 1539 #StdOut 1540 shader unique: true 1541 shader unique: false 1542 ## 1543 ## 1544 1545 ## 1546 1547 #Method void setShader(sk_sp<SkShader> shader) 1548 1549 #In Shader_Methods 1550 #Line # sets Shader, multiple drawing colors; gradients ## 1551 #Populate 1552 1553 #Example 1554 #Height 64 1555 void draw(SkCanvas* canvas) { 1556 SkPaint paint; 1557 paint.setColor(SK_ColorBLUE); 1558 paint.setShader(SkShader::MakeColorShader(SK_ColorRED)); 1559 canvas->drawRect(SkRect::MakeWH(40, 40), paint); 1560 paint.setShader(nullptr); 1561 canvas->translate(50, 0); 1562 canvas->drawRect(SkRect::MakeWH(40, 40), paint); 1563 } 1564 ## 1565 1566 ## 1567 1568 #Subtopic Shader_Methods ## 1569 # ------------------------------------------------------------------------------ 1570 #Subtopic Color_Filter_Methods 1571 #Line # get and set Color_Filter ## 1572 1573 Color_Filter alters the color used when drawing a shape. 1574 Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters. 1575 If Paint has no Color_Filter, the color is unaltered. 1576 1577 The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha. 1578 1579 #Example 1580 #Height 128 1581 void draw(SkCanvas* canvas) { 1582 SkPaint paint; 1583 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000)); 1584 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) { 1585 paint.setColor(c); 1586 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint); 1587 paint.setAlpha(0x80); 1588 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint); 1589 canvas->translate(100, 0); 1590 } 1591 } 1592 ## 1593 1594 #Method SkColorFilter* getColorFilter() const 1595 1596 #In Color_Filter_Methods 1597 #Line # returns Color_Filter, how colors are altered ## 1598 #Populate 1599 1600 #Example 1601 void draw(SkCanvas* canvas) { 1602 SkPaint paint; 1603 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '='); 1604 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn)); 1605 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '='); 1606 } 1607 1608 #StdOut 1609 nullptr == color filter 1610 nullptr != color filter 1611 ## 1612 ## 1613 ## 1614 1615 #Method sk_sp<SkColorFilter> refColorFilter() const 1616 1617 #In Color_Filter_Methods 1618 #Line # references Color_Filter, how colors are altered ## 1619 #Populate 1620 1621 #Example 1622 void draw(SkCanvas* canvas) { 1623 SkPaint paint1, paint2; 1624 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop)); 1625 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false"); 1626 paint2.setColorFilter(paint1.refColorFilter()); 1627 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false"); 1628 } 1629 1630 #StdOut 1631 color filter unique: true 1632 color filter unique: false 1633 ## 1634 ## 1635 ## 1636 1637 #Method void setColorFilter(sk_sp<SkColorFilter> colorFilter) 1638 1639 #In Color_Filter_Methods 1640 #Line # sets Color_Filter, alters color ## 1641 #Populate 1642 1643 #Example 1644 #Height 64 1645 void draw(SkCanvas* canvas) { 1646 SkPaint paint; 1647 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn)); 1648 canvas->drawRect(SkRect::MakeWH(50, 50), paint); 1649 paint.setColorFilter(nullptr); 1650 canvas->translate(70, 0); 1651 canvas->drawRect(SkRect::MakeWH(50, 50), paint); 1652 } 1653 ## 1654 1655 ## 1656 1657 #Subtopic Color_Filter_Methods ## 1658 # ------------------------------------------------------------------------------ 1659 #Subtopic Blend_Mode_Methods 1660 #Line # get and set Blend_Mode ## 1661 1662 Blend_Mode describes how Color combines with the destination color. 1663 The default setting, SkBlendMode::kSrcOver, draws the source color 1664 over the destination color. 1665 1666 #Example 1667 void draw(SkCanvas* canvas) { 1668 SkPaint normal, blender; 1669 normal.setColor(0xFF58a889); 1670 blender.setColor(0xFF8958a8); 1671 canvas->clear(0); 1672 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) { 1673 normal.setBlendMode(SkBlendMode::kSrcOver); 1674 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal); 1675 blender.setBlendMode(m); 1676 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender); 1677 canvas->translate(70, 70); 1678 } 1679 } 1680 ## 1681 1682 #SeeAlso Blend_Mode 1683 1684 #Method SkBlendMode getBlendMode() const 1685 1686 #In Blend_Mode_Methods 1687 #Line # returns Blend_Mode, how colors combine with Device ## 1688 #Populate 1689 1690 #Example 1691 void draw(SkCanvas* canvas) { 1692 SkPaint paint; 1693 SkDebugf("kSrcOver %c= getBlendMode\n", 1694 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!'); 1695 paint.setBlendMode(SkBlendMode::kSrc); 1696 SkDebugf("kSrcOver %c= getBlendMode\n", 1697 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!'); 1698 } 1699 1700 #StdOut 1701 kSrcOver == getBlendMode 1702 kSrcOver != getBlendMode 1703 ## 1704 ## 1705 1706 ## 1707 1708 #Method bool isSrcOver() const 1709 1710 #In Blend_Mode_Methods 1711 #Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ## 1712 #Populate 1713 1714 #Example 1715 void draw(SkCanvas* canvas) { 1716 SkPaint paint; 1717 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 1718 paint.setBlendMode(SkBlendMode::kSrc); 1719 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 1720 } 1721 1722 #StdOut 1723 isSrcOver == true 1724 isSrcOver != true 1725 ## 1726 ## 1727 1728 ## 1729 1730 #Method void setBlendMode(SkBlendMode mode) 1731 1732 #In Blend_Mode_Methods 1733 #Line # sets Blend_Mode, how colors combine with destination ## 1734 #Populate 1735 1736 #Example 1737 void draw(SkCanvas* canvas) { 1738 SkPaint paint; 1739 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 1740 paint.setBlendMode(SkBlendMode::kSrc); 1741 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 1742 } 1743 1744 #StdOut 1745 isSrcOver == true 1746 isSrcOver != true 1747 ## 1748 ## 1749 1750 ## 1751 1752 #Subtopic Blend_Mode_Methods ## 1753 # ------------------------------------------------------------------------------ 1754 #Subtopic Path_Effect_Methods 1755 #Line # get and set Path_Effect ## 1756 1757 Path_Effect modifies the path geometry before drawing it. 1758 Path_Effect may implement dashing, custom fill effects and custom stroke effects. 1759 If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked. 1760 1761 #Example 1762 #Height 160 1763 void draw(SkCanvas* canvas) { 1764 SkPaint paint; 1765 paint.setStyle(SkPaint::kStroke_Style); 1766 paint.setStrokeWidth(16); 1767 SkScalar intervals[] = {30, 10}; 1768 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1)); 1769 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint); 1770 } 1771 ## 1772 1773 #SeeAlso Path_Effect 1774 1775 #Method SkPathEffect* getPathEffect() const 1776 1777 #In Path_Effect_Methods 1778 #Line # returns Path_Effect, modifications to path geometry; dashing ## 1779 #Populate 1780 1781 #Example 1782 void draw(SkCanvas* canvas) { 1783 SkPaint paint; 1784 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '='); 1785 paint.setPathEffect(SkCornerPathEffect::Make(10)); 1786 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '='); 1787 } 1788 1789 #StdOut 1790 nullptr == path effect 1791 nullptr != path effect 1792 ## 1793 ## 1794 1795 ## 1796 1797 1798 #Method sk_sp<SkPathEffect> refPathEffect() const 1799 1800 #In Path_Effect_Methods 1801 #Line # references Path_Effect, modifications to path geometry; dashing ## 1802 #Populate 1803 1804 #Example 1805 void draw(SkCanvas* canvas) { 1806 SkPaint paint1, paint2; 1807 SkScalar intervals[] = {1, 2}; 1808 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10)); 1809 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false"); 1810 paint2.setPathEffect(paint1.refPathEffect()); 1811 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false"); 1812 } 1813 1814 #StdOut 1815 path effect unique: true 1816 path effect unique: false 1817 ## 1818 ## 1819 1820 ## 1821 1822 1823 #Method void setPathEffect(sk_sp<SkPathEffect> pathEffect) 1824 1825 #In Path_Effect_Methods 1826 #Line # sets Path_Effect, modifications to path geometry; dashing ## 1827 #Populate 1828 1829 #Example 1830 void draw(SkCanvas* canvas) { 1831 SkPaint paint; 1832 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5)); 1833 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint); 1834 } 1835 ## 1836 1837 ## 1838 1839 #Subtopic Path_Effect_Methods ## 1840 # ------------------------------------------------------------------------------ 1841 #Subtopic Mask_Filter_Methods 1842 #Line # get and set Mask_Filter ## 1843 1844 Mask_Filter uses coverage of the shape drawn to create Mask_Alpha. 1845 Mask_Filter takes a Mask, and returns a Mask. 1846 1847 Mask_Filter may change the geometry and transparency of the shape, such as 1848 creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from 1849 modifying the draw. 1850 1851 #Example 1852 void draw(SkCanvas* canvas) { 1853 SkPaint paint; 1854 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3)); 1855 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint); 1856 } 1857 ## 1858 1859 #Method SkMaskFilter* getMaskFilter() const 1860 1861 #In Mask_Filter_Methods 1862 #Line # returns Mask_Filter, alterations to Mask_Alpha ## 1863 #Populate 1864 1865 #Example 1866 void draw(SkCanvas* canvas) { 1867 SkPaint paint; 1868 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '='); 1869 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3)); 1870 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '='); 1871 } 1872 1873 #StdOut 1874 nullptr == mask filter 1875 nullptr != mask filter 1876 ## 1877 ## 1878 1879 ## 1880 1881 #Method sk_sp<SkMaskFilter> refMaskFilter() const 1882 1883 #In Mask_Filter_Methods 1884 #Line # references Mask_Filter, alterations to Mask_Alpha ## 1885 #Populate 1886 1887 #Example 1888 void draw(SkCanvas* canvas) { 1889 SkPaint paint1, paint2; 1890 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1)); 1891 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false"); 1892 paint2.setMaskFilter(paint1.refMaskFilter()); 1893 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false"); 1894 } 1895 1896 #StdOut 1897 mask filter unique: true 1898 mask filter unique: false 1899 ## 1900 ## 1901 1902 ## 1903 1904 #Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter) 1905 1906 #In Mask_Filter_Methods 1907 #Line # sets Mask_Filter, alterations to Mask_Alpha ## 1908 #Populate 1909 1910 #Example 1911 void draw(SkCanvas* canvas) { 1912 SkPaint paint; 1913 paint.setStyle(SkPaint::kStroke_Style); 1914 paint.setStrokeWidth(10); 1915 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10)); 1916 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint); 1917 } 1918 ## 1919 1920 ## 1921 1922 #Subtopic Mask_Filter_Methods ## 1923 # ------------------------------------------------------------------------------ 1924 #Subtopic Typeface_Methods 1925 #Line # get and set Typeface ## 1926 1927 Typeface identifies the font used when drawing and measuring text. 1928 Typeface may be specified by name, from a file, or from a data stream. 1929 The default Typeface defers to the platform-specific default font 1930 implementation. 1931 1932 #Example 1933 #Height 100 1934 void draw(SkCanvas* canvas) { 1935 SkPaint paint; 1936 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle())); 1937 SkFont font(nullptr, 36); 1938 canvas->drawString("A Big Hello!", 10, 40, font, paint); 1939 paint.setTypeface(nullptr); 1940 paint.setFakeBoldText(true); 1941 canvas->drawString("A Big Hello!", 10, 80, font, paint); 1942 } 1943 ## 1944 1945 #Subtopic Typeface_Methods ## 1946 # ------------------------------------------------------------------------------ 1947 #Subtopic Image_Filter_Methods 1948 #Line # get and set Image_Filter ## 1949 1950 Image_Filter operates on the pixel representation of the shape, as modified by Paint 1951 with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap, 1952 which is drawn to the device using the set Blend_Mode. 1953 1954 Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter 1955 can operate on all channels of Color, while Mask_Filter generates Alpha only. 1956 Image_Filter operates independently of and can be used in combination with 1957 Mask_Filter. 1958 1959 #Example 1960 #ToDo explain why the two draws are so different ## 1961 #Function 1962 ###$ 1963 #include "SkBlurImageFilter.h" 1964 $$$# 1965 ## 1966 void draw(SkCanvas* canvas) { 1967 SkPaint paint; 1968 paint.setStyle(SkPaint::kStroke_Style); 1969 paint.setStrokeWidth(2); 1970 SkRegion region; 1971 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op); 1972 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op); 1973 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr)); 1974 canvas->drawRegion(region, paint); 1975 paint.setImageFilter(nullptr); 1976 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5)); 1977 canvas->translate(100, 100); 1978 canvas->drawRegion(region, paint); 1979 } 1980 ## 1981 1982 #Method SkImageFilter* getImageFilter() const 1983 1984 #In Image_Filter_Methods 1985 #Line # returns Image_Filter, alter pixels; blur ## 1986 #Populate 1987 1988 #Example 1989 #Function 1990 ###$ 1991 #include "SkBlurImageFilter.h" 1992 $$$# 1993 ## 1994 void draw(SkCanvas* canvas) { 1995 SkPaint paint; 1996 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '='); 1997 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr)); 1998 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '='); 1999 } 2000 2001 #StdOut 2002 nullptr == image filter 2003 nullptr != image filter 2004 ## 2005 ## 2006 2007 ## 2008 2009 #Method sk_sp<SkImageFilter> refImageFilter() const 2010 2011 #In Image_Filter_Methods 2012 #Line # references Image_Filter, alter pixels; blur ## 2013 #Populate 2014 2015 #Example 2016 void draw(SkCanvas* canvas) { 2017 SkPaint paint1, paint2; 2018 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr)); 2019 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false"); 2020 paint2.setImageFilter(paint1.refImageFilter()); 2021 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false"); 2022 } 2023 2024 #StdOut 2025 image filter unique: true 2026 image filter unique: false 2027 ## 2028 ## 2029 2030 ## 2031 2032 #Method void setImageFilter(sk_sp<SkImageFilter> imageFilter) 2033 2034 #In Image_Filter_Methods 2035 #Line # sets Image_Filter, alter pixels; blur ## 2036 #Populate 2037 2038 #Example 2039 #Height 160 2040 void draw(SkCanvas* canvas) { 2041 SkBitmap bitmap; 2042 bitmap.allocN32Pixels(100, 100); 2043 SkCanvas offscreen(bitmap); 2044 SkPaint paint; 2045 paint.setAntiAlias(true); 2046 paint.setColor(SK_ColorWHITE); 2047 SkFont font(nullptr, 96); 2048 offscreen.clear(0); 2049 offscreen.drawString("e", 20, 70, font, paint); 2050 paint.setImageFilter( 2051 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10), 2052 SK_ColorWHITE, 1, 2, nullptr, nullptr)); 2053 canvas->drawBitmap(bitmap, 0, 0, &paint); 2054 } 2055 ## 2056 2057 ## 2058 2059 #Subtopic Image_Filter_Methods ## 2060 # ------------------------------------------------------------------------------ 2061 #Subtopic Draw_Looper_Methods 2062 #Line # get and set Draw_Looper ## 2063 2064 Draw_Looper sets a modifier that communicates state from one Draw_Layer 2065 to another to construct the draw. 2066 2067 Draw_Looper draws one or more times, modifying the canvas and paint each time. 2068 Draw_Looper may be used to draw multiple colors or create a colored shadow. 2069 Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw. 2070 2071 #Example 2072 #Height 128 2073 void draw(SkCanvas* canvas) { 2074 SkLayerDrawLooper::LayerInfo info; 2075 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit; 2076 info.fColorMode = SkBlendMode::kSrc; 2077 SkLayerDrawLooper::Builder looperBuilder; 2078 SkPaint* loopPaint = looperBuilder.addLayer(info); 2079 loopPaint->setColor(SK_ColorRED); 2080 info.fOffset.set(20, 20); 2081 loopPaint = looperBuilder.addLayer(info); 2082 loopPaint->setColor(SK_ColorBLUE); 2083 SkPaint paint; 2084 paint.setDrawLooper(looperBuilder.detach()); 2085 canvas->drawCircle(50, 50, 50, paint); 2086 } 2087 2088 ## 2089 2090 #Method SkDrawLooper* getDrawLooper() const 2091 2092 #In Draw_Looper_Methods 2093 #Line # returns Draw_Looper, multiple layers ## 2094 #Populate 2095 2096 #Example 2097 void draw(SkCanvas* canvas) { 2098 SkPaint paint; 2099 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '='); 2100 SkLayerDrawLooper::Builder looperBuilder; 2101 paint.setDrawLooper(looperBuilder.detach()); 2102 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '='); 2103 } 2104 2105 #StdOut 2106 nullptr == draw looper 2107 nullptr != draw looper 2108 ## 2109 ## 2110 2111 ## 2112 2113 #Method sk_sp<SkDrawLooper> refDrawLooper() const 2114 2115 #In Draw_Looper_Methods 2116 #Line # references Draw_Looper, multiple layers ## 2117 #Populate 2118 2119 #Example 2120 void draw(SkCanvas* canvas) { 2121 SkPaint paint1, paint2; 2122 SkLayerDrawLooper::Builder looperBuilder; 2123 paint1.setDrawLooper(looperBuilder.detach()); 2124 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false"); 2125 paint2.setDrawLooper(paint1.refDrawLooper()); 2126 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false"); 2127 } 2128 2129 #StdOut 2130 draw looper unique: true 2131 draw looper unique: false 2132 ## 2133 ## 2134 2135 ## 2136 2137 #Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper) 2138 #In Draw_Looper_Methods 2139 #Line # sets Draw_Looper, multiple layers ## 2140 #Populate 2141 2142 #Example 2143 #Height 128 2144 void draw(SkCanvas* canvas) { 2145 SkPaint paint; 2146 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10)); 2147 paint.setStyle(SkPaint::kStroke_Style); 2148 paint.setStrokeWidth(10); 2149 paint.setAntiAlias(true); 2150 paint.setColor(0x7f0000ff); 2151 canvas->drawCircle(70, 70, 50, paint); 2152 } 2153 ## 2154 2155 ## 2156 2157 #Subtopic Draw_Looper_Methods ## 2158 2159 #Subtopic Text_Size 2160 #Line # overall height in points ## 2161 2162 Text_Size adjusts the overall text size in points. 2163 Text_Size can be set to any positive value or zero. 2164 Text_Size defaults to 12. 2165 Set SkPaintDefaults_TextSize at compile time to change the default setting. 2166 2167 #Example 2168 #Height 135 2169 void draw(SkCanvas* canvas) { 2170 SkPaint paint; 2171 SkFont font; 2172 canvas->drawString("12 point", 10, 20, font, paint); 2173 font.setSize(24); 2174 canvas->drawString("24 point", 10, 60, font, paint); 2175 font.setSize(48); 2176 canvas->drawString("48 point", 10, 120, paint); 2177 } 2178 ## 2179 2180 #Subtopic Text_Size ## 2181 # ------------------------------------------------------------------------------ 2182 #Subtopic Text_Scale_X 2183 #Line # text horizontal scale ## 2184 2185 Text_Scale_X adjusts the text horizontal scale. 2186 Text scaling approximates condensed and expanded type faces when the actual face 2187 is not available. 2188 Text_Scale_X can be set to any value. 2189 Text_Scale_X defaults to 1. 2190 2191 #Example 2192 #Height 128 2193 void draw(SkCanvas* canvas) { 2194 SkPaint paint; 2195 SkFont font(nullptr, 24); 2196 font.setScaleX(.8f); 2197 canvas->drawString("narrow", 10, 20, font, paint); 2198 font.setScaleX(1); 2199 canvas->drawString("normal", 10, 60, font, paint); 2200 font.setScaleX(1.2f); 2201 canvas->drawString("wide", 10, 100, font, paint); 2202 } 2203 ## 2204 2205 #Subtopic Text_Scale_X ## 2206 2207 #Subtopic Text_Skew_X 2208 #Line # text horizontal slant ## 2209 2210 2211 Text_Skew_X adjusts the text horizontal slant. 2212 Text skewing approximates italic and oblique type faces when the actual face 2213 is not available. 2214 Text_Skew_X can be set to any value. 2215 Text_Skew_X defaults to 0. 2216 2217 #Example 2218 #Height 128 2219 void draw(SkCanvas* canvas) { 2220 SkPaint paint; 2221 SkFont font(nullptr, 24); 2222 font.setSkewX(-.25f); 2223 canvas->drawString("right-leaning", 10, 100, font, paint); 2224 font.setSkewX(0); 2225 canvas->drawString("normal", 10, 60, font, paint); 2226 font.setSkewX(.25f); 2227 canvas->drawString("left-leaning", 10, 20, font, paint); 2228 } 2229 ## 2230 2231 #Subtopic Text_Skew_X ## 2232 2233 # ------------------------------------------------------------------------------ 2234 #Subtopic Text_Encoding 2235 #Line # text encoded as characters or Glyphs ## 2236 2237 #Example 2238 #Height 128 2239 #Description 2240 First line is encoded in UTF-8. 2241 Second line is encoded in UTF-16. 2242 Third line is encoded in UTF-32. 2243 Fourth line has 16-bit glyph indices. 2244 ## 2245 void draw(SkCanvas* canvas) { 2246 SkPaint paint; 2247 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA"; 2248 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A }; 2249 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A }; 2250 SkFont font(nullptr, 24); 2251 canvas->drawSimpleText(hello8, sizeof(hello8) - 1, SkTextEncoding::kUTF8, 10, 30, font, paint); 2252 canvas->drawSimpleText(hello16, sizeof(hello16), SkTextEncoding::kUTF16, 10, 60, font, paint); 2253 canvas->drawSimpleText(hello32, sizeof(hello32), SkTextEncoding::kUTF32, 10, 90, font, paint); 2254 uint16_t glyphs[SK_ARRAY_COUNT(hello32)]; 2255 font.textToGlyphs(hello32, sizeof(hello32), SkTextEncoding::kUTF32, 2256 glyphs, SK_ARRAY_COUNT(hello32)); 2257 canvas->drawSimpleText(glyphs, sizeof(glyphs), kGlyphID_SkTextEncoding, 10, 120, font, paint); 2258 } 2259 ## 2260 2261 #Subtopic Text_Encoding ## 2262 2263 # ------------------------------------------------------------------------------ 2264 2265 #Method bool nothingToDraw() const 2266 #In Utility 2267 #Line # returns true if Paint prevents all drawing ## 2268 #Populate 2269 2270 #Example 2271 void draw(SkCanvas* canvas) { 2272 auto debugster = [](const char* prefix, const SkPaint& p) -> void { 2273 SkDebugf("%s nothing to draw: %s\n", prefix, 2274 p.nothingToDraw() ? "true" : "false"); 2275 }; 2276 SkPaint paint; 2277 debugster("initial", paint); 2278 paint.setBlendMode(SkBlendMode::kDst); 2279 debugster("blend dst", paint); 2280 paint.setBlendMode(SkBlendMode::kSrcOver); 2281 debugster("blend src over", paint); 2282 paint.setAlpha(0); 2283 debugster("alpha 0", paint); 2284 } 2285 2286 #StdOut 2287 initial nothing to draw: false 2288 blend dst nothing to draw: true 2289 blend src over nothing to draw: false 2290 alpha 0 nothing to draw: true 2291 #StdOut ## 2292 ## 2293 2294 ## 2295 2296 # ------------------------------------------------------------------------------ 2297 #Subtopic Utility 2298 #Line # rarely called management functions ## 2299 ## 2300 2301 # ------------------------------------------------------------------------------ 2302 2303 #Class SkPaint ## 2304 2305 #Topic Paint ## 2306