1#Topic Paint 2#Alias Paint_Reference 3 4#Subtopic Overview 5 #Subtopic Subtopic 6 #Populate 7 ## 8## 9 10#Class SkPaint 11 12Paint controls options applied when drawing and measuring. Paint collects all 13options outside of the Canvas_Clip and Canvas_Matrix. 14 15Various options apply to text, strokes and fills, and images. 16 17Some options may not be implemented on all platforms; in these cases, setting 18the option has no effect. Some options are conveniences that duplicate Canvas 19functionality; for instance, text size is identical to matrix scale. 20 21Paint options are rarely exclusive; each option modifies a stage of the drawing 22pipeline and multiple pipeline stages may be affected by a single Paint. 23 24Paint collects effects and filters that describe single-pass and multiple-pass 25algorithms that alter the drawing geometry, color, and transparency. For instance, 26Paint does not directly implement dashing or blur, but contains the objects that do so. 27 28The objects contained by Paint are opaque, and cannot be edited outside of the Paint 29to affect it. The implementation is free to defer computations associated with the 30Paint, or ignore them altogether. For instance, some GPU implementations draw all 31Path geometries with Anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag 32is set in Paint. 33 34Paint describes a single color, a single font, a single image quality, and so on. 35Multiple colors are drawn either by using multiple paints or with objects like 36Shader attached to Paint. 37 38#Subtopic Related_Function 39#Populate 40## 41 42#Subtopic Constant 43#Populate 44## 45 46#Subtopic Class_or_Struct 47#Populate 48## 49 50#Subtopic Constructor 51#Populate 52## 53 54#Subtopic Operator 55#Populate 56## 57 58#Subtopic Member_Function 59#Populate 60## 61 62# ------------------------------------------------------------------------------ 63#Subtopic Initializers 64#Line # constructors and initialization ## 65 66#Method SkPaint() 67 68#In Initializers 69#Line # constructs with default values ## 70Constructs Paint with default values. 71 72#Table 73#Legend 74# attribute # default value ## 75#Legend ## 76# Anti-alias # false ## 77# Blend_Mode # SkBlendMode::kSrcOver ## 78# Color # SK_ColorBLACK ## 79# Color_Alpha # 255 ## 80# Color_Filter # nullptr ## 81# Dither # false ## 82# Draw_Looper # nullptr ## 83# Fake_Bold # false ## 84# Filter_Quality # kNone_SkFilterQuality ## 85# Font_Embedded_Bitmaps # false ## 86# Automatic_Hinting # false ## 87# Full_Hinting_Spacing # false ## 88# Hinting # kNormal_Hinting ## 89# Image_Filter # nullptr ## 90# LCD_Text # false ## 91# Linear_Text # false ## 92# Miter_Limit # 4 ## 93# Mask_Filter # nullptr ## 94# Path_Effect # nullptr ## 95# Shader # nullptr ## 96# Style # kFill_Style ## 97# Text_Align # kLeft_Align ## 98# Text_Encoding # kUTF8_TextEncoding ## 99# Text_Scale_X # 1 ## 100# Text_Size # 12 ## 101# Text_Skew_X # 0 ## 102# Typeface # nullptr ## 103# Stroke_Cap # kButt_Cap ## 104# Stroke_Join # kMiter_Join ## 105# Stroke_Width # 0 ## 106# Subpixel_Text # false ## 107# Vertical_Text # false ## 108#Table ## 109 110The flags, text size, hinting, and miter limit may be overridden at compile time by defining 111paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the 112build system. 113 114#Return default initialized Paint ## 115 116#Example 117#ToDo mark this as no output ## 118#Height 1 119###$ $ redefine markup character so preprocessor commands appear normally 120#ifndef SkUserConfig_DEFINED 121#define SkUserConfig_DEFINED 122 123#define SkPaintDefaults_Flags 0x01 // always enable antialiasing 124#define SkPaintDefaults_TextSize 24.f // double default font size 125#define SkPaintDefaults_Hinting 3 // use full hinting 126#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting 127 128#endif 129$$$# # restore original markup character 130## 131 132 133## 134 135#Method SkPaint(const SkPaint& paint) 136 137#In Initializers 138#Line # makes a shallow copy ## 139Makes a shallow copy of Paint. Typeface, Path_Effect, Shader, 140Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared 141between the original paint and the copy. Objects containing Reference_Count increment 142their references by one. 143 144The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter, 145Draw_Looper, and Image_Filter cannot be modified after they are created. 146This prevents objects with Reference_Count from being modified once Paint refers to them. 147 148#Param paint original to copy ## 149 150#Return shallow copy of paint ## 151 152#Example 153#ToDo why is this double-spaced on Fiddle? ## 154 SkPaint paint1; 155 paint1.setColor(SK_ColorRED); 156 SkPaint paint2(paint1); 157 paint2.setColor(SK_ColorBLUE); 158 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!'); 159 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!'); 160 161 #StdOut 162 SK_ColorRED == paint1.getColor() 163 SK_ColorBLUE == paint2.getColor() 164 ## 165## 166 167## 168 169#Method SkPaint(SkPaint&& paint) 170 171#In Initializers 172#Line # moves paint without copying it ## 173 Implements a move constructor to avoid increasing the reference counts 174 of objects referenced by the paint. 175 176 After the call, paint is undefined, and can be safely destructed. 177 178 #Param paint original to move ## 179 180 #Return content of paint ## 181 182 #Example 183 SkPaint paint; 184 float intervals[] = { 5, 5 }; 185 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f)); 186 SkPaint dashed(std::move(paint)); 187 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false"); 188 189 #StdOut 190 path effect unique: true 191 ## 192 ## 193 194## 195 196# ------------------------------------------------------------------------------ 197 198#Method void reset() 199 200#In Initializers 201#Line # sets to default values ## 202Sets all Paint contents to their initial values. This is equivalent to replacing 203Paint with the result of SkPaint(). 204 205#Example 206 SkPaint paint1, paint2; 207 paint1.setColor(SK_ColorRED); 208 paint1.reset(); 209 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!'); 210 211 #StdOut 212 paint1 == paint2 213 ## 214## 215 216## 217 218#Subtopic Initializers ## 219 220# ------------------------------------------------------------------------------ 221 222#Method ~SkPaint() 223 224#Line # decreases Reference_Count of owned objects ## 225Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader, 226Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the 227objects containing Reference_Count go to zero, they are deleted. 228 229#NoExample 230## 231 232## 233 234 235# ------------------------------------------------------------------------------ 236#Subtopic Management 237#Line # paint copying, moving, comparing ## 238 239#Method SkPaint& operator=(const SkPaint& paint) 240 241#In Management 242#Line # makes a shallow copy ## 243Makes a shallow copy of Paint. Typeface, Path_Effect, Shader, 244Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared 245between the original paint and the copy. Objects containing Reference_Count in the 246prior destination are decreased by one, and the referenced objects are deleted if the 247resulting count is zero. Objects containing Reference_Count in the parameter paint 248are increased by one. paint is unmodified. 249 250#Param paint original to copy ## 251 252#Return content of paint ## 253 254#Example 255 SkPaint paint1, paint2; 256 paint1.setColor(SK_ColorRED); 257 paint2 = paint1; 258 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!'); 259 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!'); 260 261 #StdOut 262 SK_ColorRED == paint1.getColor() 263 SK_ColorRED == paint2.getColor() 264 ## 265## 266 267## 268 269# ------------------------------------------------------------------------------ 270 271#Method SkPaint& operator=(SkPaint&& paint) 272 273#In Management 274#Line # moves paint without copying it ## 275Moves the paint to avoid increasing the reference counts 276of objects referenced by the paint parameter. Objects containing Reference_Count in the 277prior destination are decreased by one; those objects are deleted if the resulting count 278is zero. 279 280After the call, paint is undefined, and can be safely destructed. 281 282 #Param paint original to move ## 283 284 #Return content of paint ## 285 286#Example 287 SkPaint paint1, paint2; 288 paint1.setColor(SK_ColorRED); 289 paint2 = std::move(paint1); 290 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!'); 291 292 #StdOut 293 SK_ColorRED == paint2.getColor() 294 ## 295## 296 297## 298 299# ------------------------------------------------------------------------------ 300 301#Method bool operator==(const SkPaint& a, const SkPaint& b) 302 303#In Management 304#Line # compares paints for equality ## 305 Compares a and b, and returns true if a and b are equivalent. May return false 306 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter, 307 Draw_Looper, or Image_Filter have identical contents but different pointers. 308 309 #Param a Paint to compare ## 310 #Param b Paint to compare ## 311 312 #Return true if Paint pair are equivalent ## 313 314 #Example 315 SkPaint paint1, paint2; 316 paint1.setColor(SK_ColorRED); 317 paint2.setColor(0xFFFF0000); 318 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 319 float intervals[] = { 5, 5 }; 320 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f)); 321 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f)); 322 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 323 324 #StdOut 325 paint1 == paint2 326 paint1 != paint2 327 ## 328 ## 329 330## 331 332# ------------------------------------------------------------------------------ 333 334#Method bool operator!=(const SkPaint& a, const SkPaint& b) 335 336#In Management 337#Line # compares paints for inequality ## 338 Compares a and b, and returns true if a and b are not equivalent. May return true 339 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter, 340 Draw_Looper, or Image_Filter have identical contents but different pointers. 341 342 #Param a Paint to compare ## 343 #Param b Paint to compare ## 344 345 #Return true if Paint pair are not equivalent ## 346 347#Example 348 SkPaint paint1, paint2; 349 paint1.setColor(SK_ColorRED); 350 paint2.setColor(0xFFFF0000); 351 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 352 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '='); 353 354 #StdOut 355 paint1 == paint2 356 paint1 == paint2 357 ## 358## 359 360## 361 362# ------------------------------------------------------------------------------ 363 364#Method uint32_t getHash() const 365 366#In Management 367#Line # returns a shallow hash for equality checks ## 368Returns a hash generated from Paint values and pointers. 369Identical hashes guarantee that the paints are 370equivalent, but differing hashes do not guarantee that the paints have differing 371contents. 372 373If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints, 374their hashes are also equal. 375 376The hash returned is platform and implementation specific. 377 378#Return a shallow hash ## 379 380#Example 381 SkPaint paint1, paint2; 382 paint1.setColor(SK_ColorRED); 383 paint2.setColor(0xFFFF0000); 384 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 385 SkDebugf("paint1.getHash() %c= paint2.getHash()\n", 386 paint1.getHash() == paint2.getHash() ? '=' : '!'); 387 388 #StdOut 389 paint1 == paint2 390 paint1.getHash() == paint2.getHash() 391 ## 392## 393 394## 395 396# ------------------------------------------------------------------------------ 397 398#Method void flatten(SkWriteBuffer& buffer) const 399 400#In Management 401#Line # serializes into a buffer ## 402Serializes Paint into a buffer. A companion unflatten() call 403can reconstitute the paint at a later time. 404 405#Param buffer Write_Buffer receiving the flattened Paint data ## 406 407# why is flatten() public? 408#Bug 6172 409 410#NoExample 411## 412 413## 414 415# ------------------------------------------------------------------------------ 416 417#Method bool unflatten(SkReadBuffer& buffer) 418 419#In Management 420#Line # populates from a serialized stream ## 421Populates Paint, typically from a serialized stream, created by calling 422flatten() at an earlier time. 423 424SkReadBuffer class is not public, so unflatten() cannot be meaningfully called 425by the client. 426 427#Param buffer serialized data describing Paint content ## 428 429#Return false if the buffer contains invalid data ## 430 431# why is unflatten() public? 432#Bug 6172 433 434#NoExample 435## 436 437#SeeAlso SkReadBuffer 438 439## 440 441#Subtopic Management ## 442 443# ------------------------------------------------------------------------------ 444#Subtopic Hinting 445#Line # glyph outline adjustment ## 446 447#Enum Hinting 448#Line # level of glyph outline adjustment ## 449 450#Code 451 enum Hinting { 452 kNo_Hinting = 0, 453 kSlight_Hinting = 1, 454 kNormal_Hinting = 2, 455 kFull_Hinting = 3, 456 }; 457## 458 459Hinting adjusts the glyph outlines so that the shape provides a uniform 460look at a given point size on font engines that support it. Hinting may have a 461muted effect or no effect at all depending on the platform. 462 463The four levels roughly control corresponding features on platforms that use FreeType 464as the Font_Engine. 465 466#Const kNo_Hinting 0 467 Leaves glyph outlines unchanged from their native representation. 468 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING 469 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector 470 outline being loaded should not be fitted to the pixel grid but simply scaled 471 to 26.6 fractional pixels. 472## 473#Const kSlight_Hinting 1 474 Modifies glyph outlines minimally to improve constrast. 475 With FreeType, this is equivalent in spirit to the 476 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a 477 lighter hinting algorithm for non-monochrome modes. 478 Generated Glyphs may be fuzzy but better resemble their original shape. 479## 480#Const kNormal_Hinting 2 481 Modifies glyph outlines to improve constrast. This is the default. 482 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph, 483 choosing the default hinting algorithm, which is optimized for standard 484 gray-level rendering. 485## 486#Const kFull_Hinting 3 487 Modifies glyph outlines for maxiumum constrast. With FreeType, this selects 488 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set. 489 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for 490 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a 491 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays. 492## 493 494#Track 495#File SkFontHost_mac.cpp:1777,1806 496#Time 2013-03-03 07:16:29 +0000 497#Bug 915 498On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines 499to account for LCD text. No hinting uses Core_Text gray scale output. 500Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear, 501the LCD output is reduced to a single grayscale channel. 502#Track ## 503 504On Windows with DirectWrite, Hinting has no effect. 505 506Hinting defaults to kNormal_Hinting. 507Set SkPaintDefaults_Hinting at compile time to change the default setting. 508 509#ToDo add an illustration? linux running GM:typefacerendering is best for this 510 the hinting variations are every other character horizontally 511#ToDo ## 512 513#Enum ## 514 515#Method Hinting getHinting() const 516 517#In Hinting 518#Line # returns Hinting, glyph outline adjustment level ## 519 Returns level of glyph outline adjustment. 520 521 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ## 522 523 #Example 524 SkPaint paint; 525 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n", 526 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':'); 527 528 #StdOut 529 SkPaint::kNormal_Hinting == paint.getHinting() 530 ## 531 ## 532## 533 534#Method void setHinting(Hinting hintingLevel) 535 536#In Hinting 537#Line # sets Hinting, glyph outline adjustment level ## 538 Sets level of glyph outline adjustment. 539 Does not check for valid values of hintingLevel. 540 541 #Table 542 #Legend 543 # Hinting # value # effect on generated glyph outlines ## 544 ## 545 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ## 546 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ## 547 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ## 548 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ## 549 ## 550 551 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ## 552 553 #Example 554 SkPaint paint1, paint2; 555 paint2.setHinting(SkPaint::kNormal_Hinting); 556 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':'); 557 558 #StdOut 559 paint1 == paint2 560 ## 561 ## 562## 563 564#Subtopic Hinting ## 565# ------------------------------------------------------------------------------ 566#Subtopic Flags 567#Line # attributes represented by single bits ## 568 569#Enum Flags 570#Line # values described by bits and masks ## 571 572#Code 573 enum Flags { 574 kAntiAlias_Flag = 0x01, 575 kDither_Flag = 0x04, 576 kFakeBoldText_Flag = 0x20, 577 kLinearText_Flag = 0x40, 578 kSubpixelText_Flag = 0x80, 579 kDevKernText_Flag = 0x100, 580 kLCDRenderText_Flag = 0x200, 581 kEmbeddedBitmapText_Flag = 0x400, 582 kAutoHinting_Flag = 0x800, 583 kVerticalText_Flag = 0x1000, 584 kGenA8FromLCD_Flag = 0x2000, 585 586 kAllFlags = 0xFFFF, 587 }; 588 589## 590 591The bit values stored in Flags. 592The default value for Flags, normally zero, can be changed at compile time 593with a custom definition of SkPaintDefaults_Flags. 594All flags can be read and written explicitly; Flags allows manipulating 595multiple settings at once. 596 597 #Const kAntiAlias_Flag 0x0001 598 mask for setting Anti-alias 599 ## 600 #Const kDither_Flag 0x0004 601 mask for setting Dither 602 ## 603 604 #Const kFakeBoldText_Flag 0x0020 605 mask for setting Fake_Bold 606 ## 607 #Const kLinearText_Flag 0x0040 608 mask for setting Linear_Text 609 ## 610 #Const kSubpixelText_Flag 0x0080 611 mask for setting Subpixel_Text 612 ## 613 #Const kDevKernText_Flag 0x0100 614 mask for setting Full_Hinting_Spacing 615 ## 616 #Const kLCDRenderText_Flag 0x0200 617 mask for setting LCD_Text 618 ## 619 #Const kEmbeddedBitmapText_Flag 0x0400 620 mask for setting Font_Embedded_Bitmaps 621 ## 622 #Const kAutoHinting_Flag 0x0800 623 mask for setting Automatic_Hinting 624 ## 625 #Const kVerticalText_Flag 0x1000 626 mask for setting Vertical_Text 627 ## 628 #Const kGenA8FromLCD_Flag 0x2000 629 #Private 630 Hack for GDI -- do not use if you can help it 631 ## 632 not intended for public use 633 ## 634 #Const kAllFlags 0xFFFF 635 mask of all Flags, including private flags and flags reserved for future use 636 ## 637 638Flags default to all flags clear, disabling the associated feature. 639 640#Enum ## 641 642#Enum ReserveFlags 643#Deprecated soon 644 645Only valid for Android framework. 646 647#Code 648 enum ReserveFlags { 649 kUnderlineText_ReserveFlag = 0x08, 650 kStrikeThruText_ReserveFlag = 0x10, 651 }; 652## 653 654#Const kUnderlineText_ReserveFlag 0x0008 655#Deprecated soon 656## 657#Const kStrikeThruText_ReserveFlag 0x0010 658#Deprecated soon 659## 660## 661 662#Method uint32_t getFlags() const 663 664#In Flags 665#Line # returns Flags stored in a bit field ## 666Returns paint settings described by Flags. Each setting uses one 667bit, and can be tested with Flags members. 668 669#Return zero, one, or more bits described by Flags ## 670 671#Example 672 SkPaint paint; 673 paint.setAntiAlias(true); 674 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n", 675 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '='); 676 677 #StdOut 678 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0 679 ## 680## 681 682## 683 684#Method void setFlags(uint32_t flags) 685 686#In Flags 687#Line # sets multiple Flags in a bit field ## 688Replaces Flags with flags, the union of the Flags members. 689All Flags members may be cleared, or one or more may be set. 690 691#Param flags union of Flags for Paint ## 692 693#Example 694 SkPaint paint; 695 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag)); 696 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '='); 697 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '='); 698 699 #StdOut 700 paint.isAntiAlias() 701 paint.isDither() 702 ## 703## 704 705## 706 707#Subtopic Flags ## 708# ------------------------------------------------------------------------------ 709#Subtopic Anti-alias 710#Alias Anti-alias # permit hyphen in topic name, should probably not substitute hyphen with _ 711#In Related_Function 712#Line # approximating coverage with transparency ## 713 714Anti-alias drawing approximates partial pixel coverage with transparency. 715If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque. 716If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage. 717 718The rule for Aliased pixels is inconsistent across platforms. A shape edge 719passing through the pixel center may, but is not required to, draw the pixel. 720 721Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an 722active Path edge, and whose center is to the left of the end of the active Path edge. 723 724#ToDo add illustration of raster pixels ## 725 726A platform may only support Anti-aliased drawing. Some GPU-backed platforms use 727Supersampling to Anti-alias all drawing, and have no mechanism to selectively 728Alias. 729 730The amount of coverage computed for Anti-aliased pixels also varies across platforms. 731 732Anti-alias is disabled by default. 733Anti-alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag 734at compile time. 735 736#Example 737 #Width 512 738 #Description 739 A red line is drawn with transparency on the edges to make it look smoother. 740 A blue line draws only where the pixel centers are contained. 741 The lines are drawn into Bitmap, then drawn magnified to make the 742 Aliasing easier to see. 743 ## 744 745 void draw(SkCanvas* canvas) { 746 SkBitmap bitmap; 747 bitmap.allocN32Pixels(50, 50); 748 SkCanvas offscreen(bitmap); 749 SkPaint paint; 750 paint.setStyle(SkPaint::kStroke_Style); 751 paint.setStrokeWidth(10); 752 for (bool antialias : { false, true }) { 753 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE); 754 paint.setAntiAlias(antialias); 755 bitmap.eraseColor(0); 756 offscreen.drawLine(5, 5, 15, 30, paint); 757 canvas->drawLine(5, 5, 15, 30, paint); 758 canvas->save(); 759 canvas->scale(10, 10); 760 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0); 761 canvas->restore(); 762 canvas->translate(15, 0); 763 } 764 } 765## 766 767#Method bool isAntiAlias() const 768#In Anti_alias 769#Line # returns true if Anti-alias is set ## 770 771 If true, pixels on the active edges of Path may be drawn with partial transparency. 772 773 Equivalent to getFlags masked with kAntiAlias_Flag. 774 775 #Return kAntiAlias_Flag state ## 776 777 #Example 778 SkPaint paint; 779 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n", 780 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!'); 781 paint.setAntiAlias(true); 782 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n", 783 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!'); 784 785 #StdOut 786 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) 787 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) 788 ## 789 ## 790## 791 792#Method void setAntiAlias(bool aa) 793 794#In Anti_alias 795#Line # sets or clears Anti-alias ## 796 Requests, but does not require, that Path edge pixels draw opaque or with 797 partial transparency. 798 799 Sets kAntiAlias_Flag if aa is true. 800 Clears kAntiAlias_Flag if aa is false. 801 802 #Param aa setting for kAntiAlias_Flag ## 803 804 #Example 805 SkPaint paint1, paint2; 806 paint1.setAntiAlias(true); 807 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag); 808 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 809 810 #StdOut 811 paint1 == paint2 812 ## 813 ## 814 815## 816 817#Subtopic Anti-alias ## 818# ------------------------------------------------------------------------------ 819#Subtopic Dither 820#Line # distributing color error ## 821 822Dither increases fidelity by adjusting the color of adjacent pixels. 823This can help to smooth color transitions and reducing banding in gradients. 824Dithering lessens visible banding from kRGB_565_SkColorType 825and kRGBA_8888_SkColorType gradients, 826and improves rendering into a kRGB_565_SkColorType Surface. 827 828Dithering is always enabled for linear gradients drawing into 829kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface. 830Dither cannot be enabled for kAlpha_8_SkColorType Surface and 831kRGBA_F16_SkColorType Surface. 832 833Dither is disabled by default. 834Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag 835at compile time. 836 837Some platform implementations may ignore dithering. Set 838 839#Define SK_IGNORE_GPU_DITHER 840 841to ignore Dither on GPU_Surface. 842 843#Example 844#Description 845Dithering in the bottom half more closely approximates the requested color by 846alternating nearby colors from pixel to pixel. 847## 848void draw(SkCanvas* canvas) { 849 SkBitmap bm16; 850 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType)); 851 SkCanvas c16(bm16); 852 SkPaint colorPaint; 853 for (auto dither : { false, true } ) { 854 colorPaint.setDither(dither); 855 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) { 856 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) { 857 colorPaint.setColor(colors & mask); 858 c16.drawRect({0, 0, 8, 4}, colorPaint); 859 c16.translate(8, 0); 860 } 861 c16.translate(-32, 4); 862 } 863 } 864 canvas->scale(8, 8); 865 canvas->drawBitmap(bm16, 0, 0); 866} 867## 868 869#Example 870#Description 871Dithering introduces subtle adjustments to color to smooth gradients. 872Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the 873dither, making it easier to see. 874## 875void draw(SkCanvas* canvas) { 876 canvas->clear(0); 877 SkBitmap bm32; 878 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType)); 879 SkCanvas c32(bm32); 880 SkPoint points[] = {{0, 0}, {20, 0}}; 881 SkColor colors[] = {0xFF334455, 0xFF662211 }; 882 SkPaint paint; 883 paint.setShader(SkGradientShader::MakeLinear( 884 points, colors, nullptr, SK_ARRAY_COUNT(colors), 885 SkShader::kClamp_TileMode, 0, nullptr)); 886 paint.setDither(true); 887 c32.drawPaint(paint); 888 canvas->scale(12, 12); 889 canvas->drawBitmap(bm32, 0, 0); 890 paint.setBlendMode(SkBlendMode::kPlus); 891 canvas->drawBitmap(bm32, 0, 11, &paint); 892 canvas->drawBitmap(bm32, 0, 11, &paint); 893 canvas->drawBitmap(bm32, 0, 11, &paint); 894} 895## 896 897#Method bool isDither() const 898 899#In Dither 900#Line # returns true if Dither is set ## 901 If true, color error may be distributed to smooth color transition. 902 903 Equivalent to getFlags masked with kDither_Flag. 904 905 #Return kDither_Flag state ## 906 907 #Example 908 SkPaint paint; 909 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n", 910 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!'); 911 paint.setDither(true); 912 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n", 913 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!'); 914 915 #StdOut 916 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) 917 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) 918 ## 919 ## 920 921## 922 923#Method void setDither(bool dither) 924 925#In Dither 926#Line # sets or clears Dither ## 927 Requests, but does not require, to distribute color error. 928 929 Sets kDither_Flag if dither is true. 930 Clears kDither_Flag if dither is false. 931 932 #Param dither setting for kDither_Flag ## 933 934 #Example 935 SkPaint paint1, paint2; 936 paint1.setDither(true); 937 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag); 938 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 939 940 #StdOut 941 paint1 == paint2 942 ## 943 ## 944 945 #SeeAlso kRGB_565_SkColorType 946 947## 948 949#SeeAlso Gradient Color_RGB-565 950 951#Subtopic Dither ## 952# ------------------------------------------------------------------------------ 953#Subtopic Device_Text 954#Line # increase precision of glyph position ## 955 956LCD_Text and Subpixel_Text increase the precision of glyph position. 957 958When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that 959create a color, and relies 960on the small size of the stripe and visual perception to make the color fringing imperceptible. 961LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order 962the color components as Color_RGB or Color_RBG. 963 964Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset. 965As the opaqueness 966of the color increases, the edge of the glyph appears to move towards the outside of the pixel. 967 968Either or both techniques can be enabled. 969kLCDRenderText_Flag and kSubpixelText_Flag are clear by default. 970LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to 971kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time. 972 973#Example 974 #Description 975 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text. 976 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced. 977 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced. 978 ## 979 980 SkBitmap bitmap; 981 bitmap.allocN32Pixels(24, 33); 982 SkCanvas offscreen(bitmap); 983 offscreen.clear(SK_ColorWHITE); 984 SkPaint paint; 985 paint.setAntiAlias(true); 986 paint.setTextSize(20); 987 for (bool lcd : { false, true }) { 988 paint.setLCDRenderText(lcd); 989 for (bool subpixel : { false, true }) { 990 paint.setSubpixelText(subpixel); 991 offscreen.drawString(",,,,", 0, 4, paint); 992 offscreen.translate(0, 7); 993 } 994 } 995 canvas->drawBitmap(bitmap, 4, 12); 996 canvas->scale(9, 9); 997 canvas->drawBitmap(bitmap, 4, -1); 998## 999#Subtopic Device_Text ## 1000 1001#Subtopic Linear_Text 1002#Alias Linear_Text 1003#Line # selects text rendering as Glyph or Path ## 1004 1005Linear_Text selects whether text is rendered as a Glyph or as a Path. 1006If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting. 1007If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting. 1008 1009#Method bool isLinearText() const 1010 1011#Line # returns true if text is converted to Path ## 1012#In Linear_Text 1013 If true, text is converted to Path before drawing and measuring. 1014 1015 Equivalent to getFlags masked with kLinearText_Flag. 1016 1017 #Return kLinearText_Flag state ## 1018 1019 #Example 1020 #Height 128 1021 void draw(SkCanvas* canvas) { 1022 SkPaint paint; 1023 paint.setAntiAlias(true); 1024 const char testStr[] = "xxxx xxxx"; 1025 for (auto linearText : { false, true } ) { 1026 paint.setLinearText(linearText); 1027 paint.setTextSize(24); 1028 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint); 1029 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) { 1030 paint.setTextSize(textSize); 1031 canvas->translate(0, textSize); 1032 canvas->drawString(testStr, 10, 0, paint); 1033 } 1034 } 1035 } 1036 ## 1037 1038 #SeeAlso setLinearText Hinting 1039## 1040 1041#Method void setLinearText(bool linearText) 1042 1043#Line # converts to Path before draw or measure ## 1044#In Linear_Text 1045 If true, text is converted to Path before drawing and measuring. 1046 By default, kLinearText_Flag is clear. 1047 1048 Sets kLinearText_Flag if linearText is true. 1049 Clears kLinearText_Flag if linearText is false. 1050 1051 #Param linearText setting for kLinearText_Flag ## 1052 1053 #Example 1054 #Height 128 1055 void draw(SkCanvas* canvas) { 1056 SkPaint paint; 1057 paint.setAntiAlias(true); 1058 const char testStr[] = "abcd efgh"; 1059 for (int textSize : { 12, 24 } ) { 1060 paint.setTextSize(textSize); 1061 for (auto linearText : { false, true } ) { 1062 paint.setLinearText(linearText); 1063 SkString width; 1064 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr)); 1065 canvas->translate(0, textSize + 4); 1066 canvas->drawString(testStr, 10, 0, paint); 1067 canvas->drawString(width, 128, 0, paint); 1068 } 1069 } 1070 } 1071 ## 1072 1073 #SeeAlso isLinearText Hinting 1074## 1075 1076#Subtopic Linear_Text ## 1077 1078#Subtopic Subpixel_Text 1079#Alias Subpixel_Text 1080#Line # uses pixel transparency to represent fractional offset ## 1081 1082Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset. 1083As the opaqueness 1084of the color increases, the edge of the glyph appears to move towards the outside of the pixel. 1085 1086#Method bool isSubpixelText() const 1087 1088#In Subpixel_Text 1089#Line # returns true if Subpixel_Text is set ## 1090 If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage. 1091 1092 Equivalent to getFlags masked with kSubpixelText_Flag. 1093 1094 #Return kSubpixelText_Flag state ## 1095 1096 #Example 1097SkPaint paint; 1098SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n", 1099 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!'); 1100paint.setSubpixelText(true); 1101SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n", 1102 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!'); 1103 1104 #StdOut 1105 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) 1106 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) 1107 ## 1108 ## 1109 1110## 1111 1112#Method void setSubpixelText(bool subpixelText) 1113 1114#In Subpixel_Text 1115#Line # sets or clears Subpixel_Text ## 1116 Requests, but does not require, that Glyphs respect sub-pixel positioning. 1117 1118 Sets kSubpixelText_Flag if subpixelText is true. 1119 Clears kSubpixelText_Flag if subpixelText is false. 1120 1121 #Param subpixelText setting for kSubpixelText_Flag ## 1122 1123 #Example 1124 SkPaint paint1, paint2; 1125 paint1.setSubpixelText(true); 1126 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag); 1127 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 1128 1129 #StdOut 1130 paint1 == paint2 1131 ## 1132 ## 1133 1134## 1135 1136#Subtopic Subpixel_Text ## 1137 1138#Subtopic LCD_Text 1139#Substitute LCD text 1140#Line # text relying on the order of Color_RGB stripes ## 1141#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text 1142 1143When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that 1144create a color, and relies 1145on the small size of the stripe and visual perception to make the color fringing imperceptible. 1146LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order 1147the color components as Color_RGB or Color_RBG. 1148 1149#Method bool isLCDRenderText() const 1150 1151#In LCD_Text 1152#Line # returns true if LCD_Text is set ## 1153 If true, Glyphs may use LCD striping to improve glyph edges. 1154 1155 Returns true if Flags kLCDRenderText_Flag is set. 1156 1157 #Return kLCDRenderText_Flag state ## 1158 1159 #Example 1160SkPaint paint; 1161SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n", 1162 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!'); 1163paint.setLCDRenderText(true); 1164SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n", 1165 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!'); 1166 1167 #StdOut 1168 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) 1169 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) 1170 ## 1171 ## 1172 1173## 1174 1175#Method void setLCDRenderText(bool lcdText) 1176 1177#In LCD_Text 1178#Line # sets or clears LCD_Text ## 1179 Requests, but does not require, that Glyphs use LCD striping for glyph edges. 1180 1181 Sets kLCDRenderText_Flag if lcdText is true. 1182 Clears kLCDRenderText_Flag if lcdText is false. 1183 1184 #Param lcdText setting for kLCDRenderText_Flag ## 1185 1186 #Example 1187 SkPaint paint1, paint2; 1188 paint1.setLCDRenderText(true); 1189 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag); 1190 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 1191 1192 #StdOut 1193 paint1 == paint2 1194 ## 1195 ## 1196 1197 1198## 1199 1200#Subtopic LCD_Text ## 1201 1202# ------------------------------------------------------------------------------ 1203#Subtopic Font_Embedded_Bitmaps 1204#Line # custom sized bitmap Glyphs ## 1205#Alias Font_Embedded_Bitmaps # long-winded enough, alias so I don't type Paint_Font_... 1206 1207Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs. 1208Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained 1209in a font if the platform supports this option. 1210 1211FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects 1212the outline glyph if kEmbeddedBitmapText_Flag is clear. 1213Windows may select the bitmap glyph but is not required to do so. 1214OS_X and iOS do not support this option. 1215 1216Font_Embedded_Bitmaps is disabled by default. 1217Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to 1218kEmbeddedBitmapText_Flag at compile time. 1219 1220#Example 1221 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ## 1222 #Platform !fiddle 1223 #Description 1224 The "hintgasp" TrueType font in the Skia resources/fonts directory 1225 includes an embedded bitmap Glyph at odd font sizes. This example works 1226 on platforms that use FreeType as their Font_Engine. 1227 Windows may, but is not required to, return a bitmap glyph if 1228 kEmbeddedBitmapText_Flag is set. 1229 ## 1230 #Image embeddedbitmap.png 1231 1232 SkBitmap bitmap; 1233 bitmap.allocN32Pixels(30, 15); 1234 bitmap.eraseColor(0); 1235 SkCanvas offscreen(bitmap); 1236 SkPaint paint; 1237 paint.setAntiAlias(true); 1238 paint.setTextSize(13); 1239 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf")); 1240 for (bool embedded : { false, true}) { 1241 paint.setEmbeddedBitmapText(embedded); 1242 offscreen.drawString("A", embedded ? 5 : 15, 15, paint); 1243 } 1244 canvas->drawBitmap(bitmap, 0, 0); 1245 canvas->scale(10, 10); 1246 canvas->drawBitmap(bitmap, -2, 1); 1247## 1248 1249#Method bool isEmbeddedBitmapText() const 1250 1251#In Font_Embedded_Bitmaps 1252#Line # returns true if Font_Embedded_Bitmaps is set ## 1253 If true, Font_Engine may return Glyphs from font bitmaps instead of from outlines. 1254 1255 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag. 1256 1257 #Return kEmbeddedBitmapText_Flag state ## 1258 1259 #Example 1260 SkPaint paint; 1261 SkDebugf("paint.isEmbeddedBitmapText() %c=" 1262 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n", 1263 paint.isEmbeddedBitmapText() == 1264 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!'); 1265 paint.setEmbeddedBitmapText(true); 1266 SkDebugf("paint.isEmbeddedBitmapText() %c=" 1267 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n", 1268 paint.isEmbeddedBitmapText() == 1269 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!'); 1270 1271 #StdOut 1272 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) 1273 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) 1274 ## 1275 ## 1276 1277## 1278 1279#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText) 1280 1281#In Font_Embedded_Bitmaps 1282#Line # sets or clears Font_Embedded_Bitmaps ## 1283 Requests, but does not require, to use bitmaps in fonts instead of outlines. 1284 1285 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true. 1286 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false. 1287 1288 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ## 1289 1290 #Example 1291 SkPaint paint1, paint2; 1292 paint1.setEmbeddedBitmapText(true); 1293 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag); 1294 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 1295 1296 #StdOut 1297 paint1 == paint2 1298 ## 1299 ## 1300 1301## 1302 1303#Subtopic Font_Embedded_Bitmaps ## 1304# ------------------------------------------------------------------------------ 1305#Subtopic Automatic_Hinting 1306#Line # always adjust glyph paths ## 1307#Substitute auto-hinting 1308 1309If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting 1310instructs the Font_Manager to always hint Glyphs. 1311Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or 1312kSlight_Hinting. 1313 1314Automatic_Hinting only affects platforms that use FreeType as the Font_Manager. 1315 1316#Method bool isAutohinted() const 1317 1318#In Automatic_Hinting 1319#Line # returns true if Glyphs are always hinted ## 1320 If true, and if Hinting is set to kNormal_Hinting or kFull_Hinting, and if 1321 platform uses FreeType as the Font_Manager, instruct the Font_Manager to always hint 1322 Glyphs. 1323 1324 Equivalent to getFlags masked with kAutoHinting_Flag. 1325 1326 #Return kAutoHinting_Flag state ## 1327 1328 #Example 1329 SkPaint paint; 1330 for (auto forceAutoHinting : { false, true} ) { 1331 paint.setAutohinted(forceAutoHinting); 1332 SkDebugf("paint.isAutohinted() %c=" 1333 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n", 1334 paint.isAutohinted() == 1335 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!'); 1336 } 1337 #StdOut 1338 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) 1339 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) 1340 ## 1341 ## 1342 1343 #SeeAlso setAutohinted Hinting 1344 1345## 1346 1347#Method void setAutohinted(bool useAutohinter) 1348 1349#In Automatic_Hinting 1350#Line # sets Glyphs to always be hinted ## 1351 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set, 1352 instruct the Font_Manager to always hint Glyphs. 1353 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or 1354 kSlight_Hinting. 1355 1356 Only affects platforms that use FreeType as the Font_Manager. 1357 1358 Sets kAutoHinting_Flag if useAutohinter is true. 1359 Clears kAutoHinting_Flag if useAutohinter is false. 1360 1361 #Param useAutohinter setting for kAutoHinting_Flag ## 1362 1363 #Example 1364 void draw(SkCanvas* canvas) { 1365 SkPaint paint; 1366 paint.setAntiAlias(true); 1367 const char testStr[] = "xxxx xxxx"; 1368 for (auto forceAutoHinting : { false, true} ) { 1369 paint.setAutohinted(forceAutoHinting); 1370 paint.setTextSize(24); 1371 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint); 1372 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) { 1373 paint.setTextSize(textSize); 1374 canvas->translate(0, textSize); 1375 canvas->drawString(testStr, 10, 0, paint); 1376 } 1377 } 1378 } 1379 ## 1380 1381 #SeeAlso isAutohinted Hinting 1382 1383## 1384 1385#Subtopic Automatic_Hinting ## 1386# ------------------------------------------------------------------------------ 1387#Subtopic Vertical_Text 1388#Line # orient text from top to bottom ## 1389 1390Text may be drawn by positioning each glyph, or by positioning the first glyph and 1391using Font_Advance to position subsequent Glyphs. By default, each successive glyph 1392is positioned to the right of the preceding glyph. Vertical_Text sets successive 1393Glyphs to position below the preceding glyph. 1394 1395Skia can translate text character codes as a series of Glyphs, but does not implement 1396font substitution, 1397textual substitution, line layout, or contextual spacing like Kerning pairs. Use 1398a text shaping engine like 1399#A HarfBuzz # http://harfbuzz.org/ ## 1400 to translate text runs 1401into glyph series. 1402 1403Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom. 1404 1405Flags kVerticalText_Flag if clear draws text left to right. 1406Flags kVerticalText_Flag if set draws text top to bottom. 1407 1408Vertical_Text is clear by default. 1409Vertical_Text can be set by default by setting SkPaintDefaults_Flags to 1410kVerticalText_Flag at compile time. 1411 1412#Example 1413 1414void draw(SkCanvas* canvas) { 1415 SkPaint paint; 1416 paint.setAntiAlias(true); 1417 paint.setTextSize(50); 1418 for (bool vertical : { false, true } ) { 1419 paint.setVerticalText(vertical); 1420 canvas->drawString("aAlL", 25, 50, paint); 1421 } 1422} 1423 1424## 1425 1426#Method bool isVerticalText() const 1427 1428#In Vertical_Text 1429#Line # returns true if Vertical_Text is set ## 1430 If true, Glyphs are drawn top to bottom instead of left to right. 1431 1432 Equivalent to getFlags masked with kVerticalText_Flag. 1433 1434 #Return kVerticalText_Flag state ## 1435 1436 #Example 1437 SkPaint paint; 1438 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n", 1439 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!'); 1440 paint.setVerticalText(true); 1441 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n", 1442 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!'); 1443 1444 #StdOut 1445 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) 1446 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) 1447 ## 1448 ## 1449 1450## 1451 1452#Method void setVerticalText(bool verticalText) 1453 1454#In Vertical_Text 1455#Line # sets or clears Vertical_Text ## 1456 If true, text advance positions the next glyph below the previous glyph instead of to the 1457 right of previous glyph. 1458 1459 Sets kVerticalText_Flag if vertical is true. 1460 Clears kVerticalText_Flag if vertical is false. 1461 1462 #Param verticalText setting for kVerticalText_Flag ## 1463 1464 #Example 1465 SkPaint paint1, paint2; 1466 paint1.setVerticalText(true); 1467 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag); 1468 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 1469 1470 #StdOut 1471 paint1 == paint2 1472 ## 1473 ## 1474 1475## 1476 1477#Subtopic Vertical_Text ## 1478# ------------------------------------------------------------------------------ 1479 1480#Subtopic Fake_Bold 1481#Line # approximate font styles ## 1482 1483Fake_Bold approximates the bold font style accompanying a normal font when a bold font face 1484is not available. Skia does not provide font substitution; it is up to the client to find the 1485bold font face using the platform Font_Manager. 1486 1487Use Text_Skew_X to approximate an italic font style when the italic font face 1488is not available. 1489 1490A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct 1491the font engine to create the bold Glyphs. Otherwise, the extra bold is computed 1492by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed. 1493 1494Fake_Bold is disabled by default. 1495 1496#Example 1497#Height 128 1498void draw(SkCanvas* canvas) { 1499 SkPaint paint; 1500 paint.setAntiAlias(true); 1501 paint.setTextSize(40); 1502 canvas->drawString("OjYy_-", 10, 35, paint); 1503 paint.setFakeBoldText(true); 1504 canvas->drawString("OjYy_-", 10, 75, paint); 1505 // create a custom fake bold by varying the stroke width 1506 paint.setFakeBoldText(false); 1507 paint.setStyle(SkPaint::kStrokeAndFill_Style); 1508 paint.setStrokeWidth(40.f / 48); 1509 canvas->drawString("OjYy_-", 10, 115, paint); 1510} 1511## 1512 1513#Method bool isFakeBoldText() const 1514 1515#In Fake_Bold 1516#Line # returns true if Fake_Bold is set ## 1517 If true, approximate bold by increasing the stroke width when creating glyph bitmaps 1518 from outlines. 1519 1520 Equivalent to getFlags masked with kFakeBoldText_Flag. 1521 1522 #Return kFakeBoldText_Flag state ## 1523 1524 #Example 1525 SkPaint paint; 1526 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n", 1527 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!'); 1528 paint.setFakeBoldText(true); 1529 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n", 1530 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!'); 1531 1532 #StdOut 1533 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) 1534 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) 1535 ## 1536 ## 1537 1538## 1539 1540#Method void setFakeBoldText(bool fakeBoldText) 1541 1542#In Fake_Bold 1543#Line # sets or clears Fake_Bold ## 1544 Use increased stroke width when creating glyph bitmaps to approximate a bold typeface. 1545 1546 Sets kFakeBoldText_Flag if fakeBoldText is true. 1547 Clears kFakeBoldText_Flag if fakeBoldText is false. 1548 1549 #Param fakeBoldText setting for kFakeBoldText_Flag ## 1550 1551 #Example 1552 SkPaint paint1, paint2; 1553 paint1.setFakeBoldText(true); 1554 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag); 1555 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 1556 1557 #StdOut 1558 paint1 == paint2 1559 ## 1560 ## 1561 1562## 1563 1564#Subtopic Fake_Bold ## 1565 1566# ------------------------------------------------------------------------------ 1567#Subtopic Full_Hinting_Spacing 1568#Line # glyph spacing affected by hinting ## 1569#Alias Full_Hinting_Spacing # long winded enough -- maybe things with two underscores auto-aliased? 1570 1571if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character 1572spacing by the difference of the hinted and Unhinted Left_Side_Bearing and 1573Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use 1574FreeType as their Font_Engine. 1575 1576Full_Hinting_Spacing is not related to text Kerning, where the space between 1577a specific pair of characters is adjusted using data in the font Kerning tables. 1578 1579#Method bool isDevKernText() const 1580 1581#In Full_Hinting_Spacing 1582#Line # returns true if Full_Hinting_Spacing is set ## 1583 Returns if character spacing may be adjusted by the hinting difference. 1584 1585 Equivalent to getFlags masked with kDevKernText_Flag. 1586 1587 #Return kDevKernText_Flag state ## 1588 1589 #Example 1590 SkPaint paint; 1591 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n", 1592 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!'); 1593 paint.setDevKernText(true); 1594 SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n", 1595 paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!'); 1596 ## 1597 1598## 1599 1600#Method void setDevKernText(bool devKernText) 1601 1602#In Full_Hinting_Spacing 1603#Line # sets or clears Full_Hinting_Spacing ## 1604 Requests, but does not require, to use hinting to adjust glyph spacing. 1605 1606 Sets kDevKernText_Flag if devKernText is true. 1607 Clears kDevKernText_Flag if devKernText is false. 1608 1609 #Param devKernText setting for devKernText ## 1610 1611 #Example 1612 SkPaint paint1, paint2; 1613 paint1.setDevKernText(true); 1614 paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag); 1615 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!'); 1616 1617 #StdOut 1618 paint1 == paint2 1619 ## 1620 ## 1621 1622## 1623 1624#Subtopic Full_Hinting_Spacing ## 1625# ------------------------------------------------------------------------------ 1626#Subtopic Filter_Quality_Methods 1627#Line # get and set Filter_Quality ## 1628 1629Filter_Quality trades speed for image filtering when the image is scaled. 1630A lower Filter_Quality draws faster, but has less fidelity. 1631A higher Filter_Quality draws slower, but looks better. 1632If the image is drawn without scaling, the Filter_Quality choice will not result 1633in a noticeable difference. 1634 1635Filter_Quality is used in Paint passed as a parameter to 1636#List 1637# SkCanvas::drawBitmap ## 1638# SkCanvas::drawBitmapRect ## 1639# SkCanvas::drawImage ## 1640# SkCanvas::drawImageRect ## 1641 #ToDo probably more... ## 1642#List ## 1643and when Paint has a Shader specialization that uses Image or Bitmap. 1644 1645Filter_Quality is kNone_SkFilterQuality by default. 1646 1647#Example 1648#Image 3 1649void draw(SkCanvas* canvas) { 1650 SkPaint paint; 1651 canvas->scale(.2f, .2f); 1652 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality, 1653 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) { 1654 paint.setFilterQuality(q); 1655 canvas->drawImage(image.get(), 0, 0, &paint); 1656 canvas->translate(550, 0); 1657 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550); 1658 } 1659} 1660## 1661 1662#Method SkFilterQuality getFilterQuality() const 1663 1664#In Filter_Quality_Methods 1665#Line # returns Filter_Quality, image filtering level ## 1666Returns Filter_Quality, the image filtering level. A lower setting 1667draws faster; a higher setting looks better when the image is scaled. 1668 1669#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality, 1670 kMedium_SkFilterQuality, kHigh_SkFilterQuality 1671#Return ## 1672 1673#Example 1674 SkPaint paint; 1675 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n", 1676 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!'); 1677 1678 #StdOut 1679 kNone_SkFilterQuality == paint.getFilterQuality() 1680 ## 1681## 1682 1683## 1684 1685 1686#Method void setFilterQuality(SkFilterQuality quality) 1687 1688#In Filter_Quality_Methods 1689#Line # sets Filter_Quality, the image filtering level ## 1690Sets Filter_Quality, the image filtering level. A lower setting 1691draws faster; a higher setting looks better when the image is scaled. 1692Does not check to see if quality is valid. 1693 1694#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality, 1695 kMedium_SkFilterQuality, kHigh_SkFilterQuality 1696## 1697 1698#Example 1699 SkPaint paint; 1700 paint.setFilterQuality(kHigh_SkFilterQuality); 1701 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n", 1702 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!'); 1703 1704 #StdOut 1705 kHigh_SkFilterQuality == paint.getFilterQuality() 1706 ## 1707## 1708 1709#SeeAlso SkFilterQuality Image_Scaling 1710 1711## 1712 1713#Subtopic Filter_Quality_Methods ## 1714# ------------------------------------------------------------------------------ 1715#Subtopic Color_Methods 1716#Line # get and set Color ## 1717 1718#Table 1719#Legend 1720# name # description ## 1721#Legend ## 1722# getColor # returns Color_Alpha and Color_RGB, one drawing color ## 1723# setColor # sets Color_Alpha and Color_RGB, one drawing color ## 1724#Table ## 1725 1726Color specifies the Color_RGB_Red, Color_RGB_Blue, Color_RGB_Green, and Color_Alpha 1727values used to draw a filled or stroked shape in a 32-bit value. Each component 1728occupies 8-bits, ranging from zero: no contribution; to 255: full intensity. 1729All values in any combination are valid. 1730 1731Color is not Premultiplied; Color_Alpha sets the transparency independent of 1732Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green. 1733 1734The bit positions of Color_Alpha and Color_RGB are independent of the bit 1735positions on the output device, which may have more or fewer bits, and may have 1736a different arrangement. 1737 1738#Table 1739#Legend 1740# bit positions # Color_Alpha # Color_RGB_Red # Color_RGB_Blue # Color_RGB_Green ## 1741#Legend ## 1742# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ## 1743#Table ## 1744 1745#Example 1746#Height 128 1747 void draw(SkCanvas* canvas) { 1748 SkPaint paint; 1749 paint.setColor(0x8000FF00); // transparent green 1750 canvas->drawCircle(50, 50, 40, paint); 1751 paint.setARGB(128, 255, 0, 0); // transparent red 1752 canvas->drawCircle(80, 50, 40, paint); 1753 paint.setColor(SK_ColorBLUE); 1754 paint.setAlpha(0x80); 1755 canvas->drawCircle(65, 65, 40, paint); 1756 } 1757## 1758 1759#Method SkColor getColor() const 1760 1761#In Color_Methods 1762#Line # returns Color_Alpha and Color_RGB, one drawing color ## 1763 Retrieves Alpha and Color_RGB, Unpremultiplied, packed into 32 bits. 1764 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract 1765 a color component. 1766 1767 #Return Unpremultiplied Color_ARGB ## 1768 1769 #Example 1770 SkPaint paint; 1771 paint.setColor(SK_ColorYELLOW); 1772 SkColor y = paint.getColor(); 1773 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f), 1774 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f)); 1775 1776 #StdOut 1777 Yellow is 100% red, 100% green, and 0% blue. 1778 ## 1779 ## 1780 1781 #SeeAlso SkColor 1782 1783## 1784 1785#Method void setColor(SkColor color) 1786 1787#In Color_Methods 1788#Line # sets Color_Alpha and Color_RGB, one drawing color ## 1789 Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value, 1790 Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green. 1791 1792 #Param color Unpremultiplied Color_ARGB ## 1793 1794 #Example 1795 SkPaint green1, green2; 1796 unsigned a = 255; 1797 unsigned r = 0; 1798 unsigned g = 255; 1799 unsigned b = 0; 1800 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0)); 1801 green2.setColor(0xFF00FF00); 1802 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!'); 1803 1804 #StdOut 1805 green1 == green2 1806 ## 1807 ## 1808 1809 #SeeAlso SkColor setARGB SkColorSetARGB 1810 1811## 1812#Subtopic Color_Methods ## 1813 1814#Subtopic Alpha_Methods 1815#Line # get and set Alpha ## 1816 1817Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color_RGB_Blue, and Color_RGB_Green. 1818 1819#Method uint8_t getAlpha() const 1820 1821#In Alpha_Methods 1822#Line # returns Color_Alpha, color opacity ## 1823 Retrieves Alpha from the Color used when stroking and filling. 1824 1825 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ## 1826 1827 #Example 1828 SkPaint paint; 1829 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!'); 1830 1831 #StdOut 1832 255 == paint.getAlpha() 1833 ## 1834 ## 1835 1836## 1837 1838#Method void setAlpha(U8CPU a) 1839 1840#In Alpha_Methods 1841#Line # sets Color_Alpha, color opacity ## 1842 Replaces Alpha, leaving Color_RGB 1843 unchanged. An out of range value triggers an assert in the debug 1844 build. a is a value from zero to 255. 1845 a set to zero makes Color fully transparent; a set to 255 makes Color 1846 fully opaque. 1847 1848 #Param a Alpha component of Color ## 1849 1850 #Example 1851 SkPaint paint; 1852 paint.setColor(0x00112233); 1853 paint.setAlpha(0x44); 1854 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!'); 1855 1856 #StdOut 1857 0x44112233 == paint.getColor() 1858 ## 1859 ## 1860 1861## 1862 1863#Subtopic Alpha_Methods ## 1864 1865#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 1866 1867#In Color_Methods 1868#Line # sets color by component ## 1869 Sets Color used when drawing solid fills. The color components range from 0 to 255. 1870 The color is Unpremultiplied; Alpha sets the transparency independent of Color_RGB. 1871 1872 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ## 1873 #Param r amount of Color_RGB_Red, from no red (0) to full red (255) ## 1874 #Param g amount of Color_RGB_Green, from no green (0) to full green (255) ## 1875 #Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ## 1876 1877 #Example 1878 SkPaint transRed1, transRed2; 1879 transRed1.setARGB(255 / 2, 255, 0, 0); 1880 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0)); 1881 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!'); 1882 1883 #StdOut 1884 transRed1 == transRed2 1885 ## 1886 ## 1887 1888 #SeeAlso setColor SkColorSetARGB 1889 1890## 1891 1892# ------------------------------------------------------------------------------ 1893#Subtopic Style 1894#Line # geometry filling, stroking ## 1895 1896Style specifies if the geometry is filled, stroked, or both filled and stroked. 1897Some shapes ignore Style and are always drawn filled or stroked. 1898 1899Set Style to kFill_Style to fill the shape. 1900The fill covers the area inside the geometry for most shapes. 1901 1902Set Style to kStroke_Style to stroke the shape. 1903 1904# ------------------------------------------------------------------------------ 1905#Subtopic Fill 1906#Line # fill and stroke ## 1907#ToDo write up whatever generalities make sense to describe filling ## 1908 1909#SeeAlso Path_Fill_Type 1910#Subtopic Fill ## 1911 1912#Subtopic Stroke 1913#Line # lines and curves with width ## 1914The stroke covers the area described by following the shape edge with a pen or brush of 1915Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap. 1916The area covered where the shape turns a corner is described by Stroke_Join. 1917The stroke is centered on the shape; it extends equally on either side of the shape edge. 1918 1919As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one 1920may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage. 1921#Subtopic Stroke ## 1922 1923#Subtopic Hairline 1924#Line # lines and curves with minimal width ## 1925#Alias Hairline # maybe should be Stroke_Hairline ? 1926 1927Stroke_Width of zero has a special meaning and switches drawing to use Hairline. 1928Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels 1929flow horizontally, vertically,or diagonally. 1930 1931#ToDo what is the description of Anti-aliased hairlines? ## 1932 1933Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing 1934two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent 1935pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some 1936GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels 1937while stroking. 1938 1939#Subtopic Hairline ## 1940 1941#Enum Style 1942#Line # stroke, fill, or both ## 1943 1944#Code 1945 enum Style { 1946 kFill_Style, 1947 kStroke_Style, 1948 kStrokeAndFill_Style, 1949 }; 1950## 1951 1952Set Style to fill, stroke, or both fill and stroke geometry. 1953The stroke and fill 1954share all paint attributes; for instance, they are drawn with the same color. 1955 1956Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and 1957a fill draw. 1958 1959#Const kFill_Style 0 1960 Set to fill geometry. 1961 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text. 1962 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if 1963 kFill_Style is set, and ignore the set Style. 1964 The Path_Fill_Type specifies additional rules to fill the area outside the path edge, 1965 and to create an unfilled hole inside the shape. 1966 Style is set to kFill_Style by default. 1967## 1968 1969#Const kStroke_Style 1 1970 Set to stroke geometry. 1971 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text. 1972 Arcs, Lines, and points, are always drawn as if kStroke_Style is set, 1973 and ignore the set Style. 1974 The stroke construction is unaffected by the Path_Fill_Type. 1975## 1976 1977#Const kStrokeAndFill_Style 2 1978 Set to stroke and fill geometry. 1979 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text. 1980 Path is treated as if it is set to SkPath::kWinding_FillType, 1981 and the set Path_Fill_Type is ignored. 1982## 1983 1984#Enum Style ## 1985 1986#Enum 1987#Line # number of Style defines ## 1988#Code 1989 enum { 1990 kStyleCount = kStrokeAndFill_Style + 1, 1991 }; 1992## 1993 1994#Const kStyleCount 3 1995The number of different Style values defined. 1996May be used to verify that Style is a legal value. 1997## 1998 1999#Enum ## 2000 2001#Method Style getStyle() const 2002 2003#In Style 2004#Line # returns Style: stroke, fill, or both ## 2005 Whether the geometry is filled, stroked, or filled and stroked. 2006 2007 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ## 2008 2009 #Example 2010 SkPaint paint; 2011 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n", 2012 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!'); 2013 2014 #StdOut 2015 SkPaint::kFill_Style == paint.getStyle() 2016 ## 2017 ## 2018 2019#SeeAlso Style setStyle 2020## 2021 2022#Method void setStyle(Style style) 2023 2024#In Style 2025#Line # sets Style: stroke, fill, or both ## 2026 Sets whether the geometry is filled, stroked, or filled and stroked. 2027 Has no effect if style is not a legal Style value. 2028 2029 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style 2030 ## 2031 2032 #Example 2033 void draw(SkCanvas* canvas) { 2034 SkPaint paint; 2035 paint.setStrokeWidth(5); 2036 SkRegion region; 2037 region.op(140, 10, 160, 30, SkRegion::kUnion_Op); 2038 region.op(170, 40, 190, 60, SkRegion::kUnion_Op); 2039 SkBitmap bitmap; 2040 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50); 2041 uint8_t pixels[50][50]; 2042 for (int x = 0; x < 50; ++x) { 2043 for (int y = 0; y < 50; ++y) { 2044 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00; 2045 } 2046 } 2047 bitmap.setPixels(pixels); 2048 for (auto style : { SkPaint::kFill_Style, 2049 SkPaint::kStroke_Style, 2050 SkPaint::kStrokeAndFill_Style }) { 2051 paint.setStyle(style); 2052 canvas->drawLine(10, 10, 60, 60, paint); 2053 canvas->drawRect({80, 10, 130, 60}, paint); 2054 canvas->drawRegion(region, paint); 2055 canvas->drawBitmap(bitmap, 200, 10, &paint); 2056 canvas->translate(0, 80); 2057 } 2058 } 2059 ## 2060 2061#SeeAlso Style getStyle 2062## 2063 2064#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke 2065#Subtopic Style ## 2066 2067# ------------------------------------------------------------------------------ 2068#Subtopic Stroke_Width 2069#Line # thickness perpendicular to geometry ## 2070 2071Stroke_Width sets the width for stroking. The width is the thickness 2072of the stroke perpendicular to the path direction when the paint style is 2073set to kStroke_Style or kStrokeAndFill_Style. 2074 2075When width is greater than zero, the stroke encompasses as many pixels partially 2076or fully as needed. When the width equals zero, the paint enables hairlines; 2077the stroke is always one pixel wide. 2078 2079The stroke dimensions are scaled by the canvas matrix, but Hairline stroke 2080remains one pixel wide regardless of scaling. 2081 2082The default width for the paint is zero. 2083 2084#Example 2085#Height 170 2086 #Platform raster gpu 2087 #Description 2088 The pixels hit to represent thin lines vary with the angle of the 2089 line and the platform implementation. 2090 ## 2091 void draw(SkCanvas* canvas) { 2092 SkPaint paint; 2093 for (bool antialias : { false, true }) { 2094 paint.setAntiAlias(antialias); 2095 for (int width = 0; width <= 4; ++width) { 2096 SkScalar offset = antialias * 100 + width * 20; 2097 paint.setStrokeWidth(width * 0.25f); 2098 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint); 2099 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint); 2100 } 2101 } 2102 } 2103## 2104 2105#Method SkScalar getStrokeWidth() const 2106 2107#In Stroke_Width 2108#Line # returns thickness of the stroke ## 2109 Returns the thickness of the pen used by Paint to 2110 outline the shape. 2111 2112 #Return zero for Hairline, greater than zero for pen thickness ## 2113 2114 #Example 2115 SkPaint paint; 2116 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!'); 2117 2118 #StdOut 2119 0 == paint.getStrokeWidth() 2120 ## 2121 ## 2122 2123## 2124 2125#Method void setStrokeWidth(SkScalar width) 2126 2127#In Stroke_Width 2128#Line # sets thickness of the stroke ## 2129 Sets the thickness of the pen used by the paint to 2130 outline the shape. 2131 Has no effect if width is less than zero. 2132 2133 #Param width zero thickness for Hairline; greater than zero for pen thickness 2134 ## 2135 2136 #Example 2137 SkPaint paint; 2138 paint.setStrokeWidth(5); 2139 paint.setStrokeWidth(-1); 2140 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!'); 2141 2142 #StdOut 2143 5 == paint.getStrokeWidth() 2144 ## 2145 ## 2146 2147## 2148 2149#Subtopic Stroke_Width ## 2150# ------------------------------------------------------------------------------ 2151#Subtopic Miter_Limit 2152#Line # maximum length of stroked corners ## 2153 2154Miter_Limit specifies the maximum miter length, 2155relative to the stroke width. 2156 2157Miter_Limit is used when the Stroke_Join 2158is set to kMiter_Join, and the Style is either kStroke_Style 2159or kStrokeAndFill_Style. 2160 2161If the miter at a corner exceeds this limit, kMiter_Join 2162is replaced with kBevel_Join. 2163 2164Miter_Limit can be computed from the corner angle: 2165 2166#Formula 2167 miter limit = 1 / sin ( angle / 2 ) 2168#Formula ## 2169 2170Miter_Limit default value is 4. 2171The default may be changed at compile time by setting SkPaintDefaults_MiterLimit 2172in "SkUserConfig.h" or as a define supplied by the build environment. 2173 2174Here are some miter limits and the angles that triggers them. 2175#Table 2176#Legend 2177 # miter limit # angle in degrees ## 2178#Legend ## 2179 # 10 # 11.48 ## 2180 # 9 # 12.76 ## 2181 # 8 # 14.36 ## 2182 # 7 # 16.43 ## 2183 # 6 # 19.19 ## 2184 # 5 # 23.07 ## 2185 # 4 # 28.96 ## 2186 # 3 # 38.94 ## 2187 # 2 # 60 ## 2188 # 1 # 180 ## 2189#Table ## 2190 2191#Example 2192 #Height 170 2193 #Width 384 2194 #Description 2195 This example draws a stroked corner and the miter length beneath. 2196 When the miter limit is decreased slightly, the miter join is replaced 2197 by a bevel join. 2198 ## 2199 void draw(SkCanvas* canvas) { 2200 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }}; 2201 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] }; 2202 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX); 2203 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX); 2204 const SkScalar strokeWidth = 20; 2205 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2); 2206 SkScalar miterLength = strokeWidth * miterLimit; 2207 SkPath path; 2208 path.moveTo(pts[0]); 2209 path.lineTo(pts[1]); 2210 path.lineTo(pts[2]); 2211 SkPaint paint; // set to default kMiter_Join 2212 paint.setAntiAlias(true); 2213 paint.setStyle(SkPaint::kStroke_Style); 2214 paint.setStrokeMiter(miterLimit); 2215 paint.setStrokeWidth(strokeWidth); 2216 canvas->drawPath(path, paint); 2217 paint.setStrokeWidth(1); 2218 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50, 2219 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint); 2220 canvas->translate(200, 0); 2221 miterLimit *= 0.99f; 2222 paint.setStrokeMiter(miterLimit); 2223 paint.setStrokeWidth(strokeWidth); 2224 canvas->drawPath(path, paint); 2225 paint.setStrokeWidth(1); 2226 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50, 2227 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint); 2228 } 2229## 2230 2231#Method SkScalar getStrokeMiter() const 2232 2233#In Miter_Limit 2234#Line # returns Miter_Limit, angles with sharp corners ## 2235 The limit at which a sharp corner is drawn beveled. 2236 2237 #Return zero and greater Miter_Limit ## 2238 2239 #Example 2240 SkPaint paint; 2241 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter()); 2242 2243 #StdOut 2244 default miter limit == 4 2245 ## 2246 ## 2247 2248 #SeeAlso Miter_Limit setStrokeMiter Join 2249 2250## 2251 2252#Method void setStrokeMiter(SkScalar miter) 2253 2254#In Miter_Limit 2255#Line # sets Miter_Limit, angles with sharp corners ## 2256 The limit at which a sharp corner is drawn beveled. 2257 Valid values are zero and greater. 2258 Has no effect if miter is less than zero. 2259 2260 #Param miter zero and greater Miter_Limit 2261 ## 2262 2263 #Example 2264 SkPaint paint; 2265 paint.setStrokeMiter(8); 2266 paint.setStrokeMiter(-1); 2267 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter()); 2268 2269 #StdOut 2270 default miter limit == 8 2271 ## 2272 ## 2273 2274 #SeeAlso Miter_Limit getStrokeMiter Join 2275 2276## 2277 2278#Subtopic Miter_Limit ## 2279# ------------------------------------------------------------------------------ 2280#Subtopic Stroke_Cap 2281#Line # decorations at ends of open strokes ## 2282 2283#Enum Cap 2284#Line # start and end geometry on stroked shapes ## 2285 2286#Code 2287 enum Cap { 2288 kButt_Cap, 2289 kRound_Cap, 2290 kSquare_Cap, 2291 2292 kLast_Cap = kSquare_Cap, 2293 kDefault_Cap = kButt_Cap, 2294 }; 2295 2296 static constexpr int kCapCount = kLast_Cap + 1; 2297## 2298 2299Stroke_Cap draws at the beginning and end of an open Path_Contour. 2300 2301 #Const kButt_Cap 0 2302 Does not extend the stroke past the beginning or the end. 2303 ## 2304 #Const kRound_Cap 1 2305 Adds a circle with a diameter equal to Stroke_Width at the beginning 2306 and end. 2307 ## 2308 #Const kSquare_Cap 2 2309 Adds a square with sides equal to Stroke_Width at the beginning 2310 and end. The square sides are parallel to the initial and final direction 2311 of the stroke. 2312 ## 2313 #Const kLast_Cap 2 2314 Equivalent to the largest value for Stroke_Cap. 2315 ## 2316 #Const kDefault_Cap 0 2317 Equivalent to kButt_Cap. 2318 Stroke_Cap is set to kButt_Cap by default. 2319 ## 2320 2321 #Const kCapCount 3 2322 The number of different Stroke_Cap values defined. 2323 May be used to verify that Stroke_Cap is a legal value. 2324 ## 2325#Enum ## 2326 2327Stroke describes the area covered by a pen of Stroke_Width as it 2328follows the Path_Contour, moving parallel to the contour direction. 2329 2330If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a 2331visible beginning and end. 2332 2333Path_Contour may start and end at the same point; defining Zero_Length_Contour. 2334 2335kButt_Cap and Zero_Length_Contour is not drawn. 2336kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width 2337at the contour point. 2338kSquare_Cap and Zero_Length_Contour draws an upright square with a side of 2339Stroke_Width at the contour point. 2340 2341Stroke_Cap is kButt_Cap by default. 2342 2343#Example 2344#Height 200 2345 SkPaint paint; 2346 paint.setStyle(SkPaint::kStroke_Style); 2347 paint.setStrokeWidth(20); 2348 SkPath path; 2349 path.moveTo(30, 30); 2350 path.lineTo(30, 30); 2351 path.moveTo(70, 30); 2352 path.lineTo(90, 40); 2353 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) { 2354 paint.setStrokeCap(c); 2355 canvas->drawPath(path, paint); 2356 canvas->translate(0, 70); 2357 } 2358## 2359 2360#Method Cap getStrokeCap() const 2361 2362#In Stroke_Cap 2363#Line # returns Cap, the area drawn at path ends ## 2364 The geometry drawn at the beginning and end of strokes. 2365 2366 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ## 2367 2368 #Example 2369 SkPaint paint; 2370 SkDebugf("kButt_Cap %c= default stroke cap\n", 2371 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!'); 2372 2373 #StdOut 2374 kButt_Cap == default stroke cap 2375 ## 2376 ## 2377 2378 #SeeAlso Stroke_Cap setStrokeCap 2379## 2380 2381#Method void setStrokeCap(Cap cap) 2382 2383#In Stroke_Cap 2384#Line # sets Cap, the area drawn at path ends ## 2385 The geometry drawn at the beginning and end of strokes. 2386 2387 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap; 2388 has no effect if cap is not valid 2389 ## 2390 2391 #Example 2392 SkPaint paint; 2393 paint.setStrokeCap(SkPaint::kRound_Cap); 2394 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount); 2395 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n", 2396 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!'); 2397 2398 #StdOut 2399 kRound_Cap == paint.getStrokeCap() 2400 ## 2401 ## 2402 2403 #SeeAlso Stroke_Cap getStrokeCap 2404## 2405 2406#Subtopic Stroke_Cap ## 2407# ------------------------------------------------------------------------------ 2408#Subtopic Stroke_Join 2409#Line # decoration at corners of strokes ## 2410 2411Stroke_Join draws at the sharp corners of an open or closed Path_Contour. 2412 2413Stroke describes the area covered by a pen of Stroke_Width as it 2414follows the Path_Contour, moving parallel to the contour direction. 2415 2416If the contour direction changes abruptly, because the tangent direction leading 2417to the end of a curve within the contour does not match the tangent direction of 2418the following curve, the pair of curves meet at Stroke_Join. 2419 2420#Example 2421#Height 200 2422 SkPaint paint; 2423 paint.setStyle(SkPaint::kStroke_Style); 2424 paint.setStrokeWidth(20); 2425 SkPath path; 2426 path.moveTo(30, 20); 2427 path.lineTo(40, 40); 2428 path.conicTo(70, 20, 100, 20, .707f); 2429 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) { 2430 paint.setStrokeJoin(j); 2431 canvas->drawPath(path, paint); 2432 canvas->translate(0, 70); 2433 } 2434## 2435 2436#Enum Join 2437#Line # corner geometry on stroked shapes ## 2438#Code 2439 enum Join { 2440 kMiter_Join, 2441 kRound_Join, 2442 kBevel_Join, 2443 2444 kLast_Join = kBevel_Join, 2445 kDefault_Join = kMiter_Join, 2446 }; 2447 2448 static constexpr int kJoinCount = kLast_Join + 1; 2449## 2450 2451Join specifies how corners are drawn when a shape is stroked. Join 2452affects the four corners of a stroked rectangle, and the connected segments in a 2453stroked path. 2454 2455Choose miter join to draw sharp corners. Choose round join to draw a circle with a 2456radius equal to the stroke width on top of the corner. Choose bevel join to minimally 2457connect the thick strokes. 2458 2459The fill path constructed to describe the stroked path respects the join setting but may 2460not contain the actual join. For instance, a fill path constructed with round joins does 2461not necessarily include circles at each connected segment. 2462 2463#Const kMiter_Join 0 2464 Extends the outside corner to the extent allowed by Miter_Limit. 2465 If the extension exceeds Miter_Limit, kBevel_Join is used instead. 2466## 2467 2468#Const kRound_Join 1 2469 Adds a circle with a diameter of Stroke_Width at the sharp corner. 2470## 2471 2472#Const kBevel_Join 2 2473 Connects the outside edges of the sharp corner. 2474## 2475 2476#Const kLast_Join 2 2477 Equivalent to the largest value for Stroke_Join. 2478## 2479 2480#Const kDefault_Join 1 2481 Equivalent to kMiter_Join. 2482 Stroke_Join is set to kMiter_Join by default. 2483## 2484 2485#Const kJoinCount 3 2486 The number of different Stroke_Join values defined. 2487 May be used to verify that Stroke_Join is a legal value. 2488## 2489 2490#Example 2491#Width 462 2492void draw(SkCanvas* canvas) { 2493 SkPath path; 2494 path.moveTo(10, 50); 2495 path.quadTo(35, 110, 60, 210); 2496 path.quadTo(105, 110, 130, 10); 2497 SkPaint paint; // set to default kMiter_Join 2498 paint.setAntiAlias(true); 2499 paint.setStyle(SkPaint::kStroke_Style); 2500 paint.setStrokeWidth(20); 2501 canvas->drawPath(path, paint); 2502 canvas->translate(150, 0); 2503 paint.setStrokeJoin(SkPaint::kBevel_Join); 2504 canvas->drawPath(path, paint); 2505 canvas->translate(150, 0); 2506 paint.setStrokeJoin(SkPaint::kRound_Join); 2507 canvas->drawPath(path, paint); 2508} 2509## 2510 2511#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter 2512 2513#Enum ## 2514 2515#Method Join getStrokeJoin() const 2516 2517#In Stroke_Join 2518#Line # returns Join, geometry on path corners ## 2519 The geometry drawn at the corners of strokes. 2520 2521 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ## 2522 2523 #Example 2524 SkPaint paint; 2525 SkDebugf("kMiter_Join %c= default stroke join\n", 2526 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!'); 2527 2528 #StdOut 2529 kMiter_Join == default stroke join 2530 ## 2531 ## 2532 2533 #SeeAlso Stroke_Join setStrokeJoin 2534## 2535 2536#Method void setStrokeJoin(Join join) 2537 2538#In Stroke_Join 2539#Line # sets Join, geometry on path corners ## 2540 The geometry drawn at the corners of strokes. 2541 2542 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join; 2543 otherwise, has no effect 2544 ## 2545 2546 #Example 2547 SkPaint paint; 2548 paint.setStrokeJoin(SkPaint::kMiter_Join); 2549 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount); 2550 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n", 2551 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!'); 2552 2553 #StdOut 2554 kMiter_Join == paint.getStrokeJoin() 2555 ## 2556 ## 2557 2558 #SeeAlso Stroke_Join getStrokeJoin 2559## 2560 2561#SeeAlso Miter_Limit 2562 2563#Subtopic Stroke_Join ## 2564# ------------------------------------------------------------------------------ 2565#Subtopic Fill_Path 2566#Line # make Path from Path_Effect, stroking ## 2567 2568Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke. 2569 2570If Paint contains Path_Effect, Path_Effect operates on the source Path; the result 2571replaces the destination Path. Otherwise, the source Path is replaces the 2572destination Path. 2573 2574Fill Path can request the Path_Effect to restrict to a culling rectangle, but 2575the Path_Effect is not required to do so. 2576 2577If Style is kStroke_Style or kStrokeAndFill_Style, 2578and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join, 2579and Miter_Limit operate on the destination Path, replacing it. 2580 2581Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry. 2582 2583If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath 2584returns false since Hairline has no filled equivalent. 2585 2586#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect, 2587 SkScalar resScale = 1) const 2588#In Fill_Path 2589#Line # returns fill path equivalent to stroke ## 2590 2591 The filled equivalent of the stroked path. 2592 2593 #Param src Path read to create a filled version ## 2594 #Param dst resulting Path; may be the same as src, but may not be nullptr ## 2595 #Param cullRect optional limit passed to Path_Effect ## 2596 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision 2597 to favor speed and size 2598 ## 2599 #Return true if the path represents Style_Fill, or false if it represents Hairline ## 2600 2601 #Example 2602 #Height 192 2603 #Description 2604 A very small Quad stroke is turned into a filled path with increasing levels of precision. 2605 At the lowest precision, the Quad stroke is approximated by a rectangle. 2606 At the highest precision, the filled path has high fidelity compared to the original stroke. 2607 ## 2608 void draw(SkCanvas* canvas) { 2609 SkPaint strokePaint; 2610 strokePaint.setAntiAlias(true); 2611 strokePaint.setStyle(SkPaint::kStroke_Style); 2612 strokePaint.setStrokeWidth(.1f); 2613 SkPath strokePath; 2614 strokePath.moveTo(.08f, .08f); 2615 strokePath.quadTo(.09f, .08f, .17f, .17f); 2616 SkPath fillPath; 2617 SkPaint outlinePaint(strokePaint); 2618 outlinePaint.setStrokeWidth(2); 2619 SkMatrix scale = SkMatrix::MakeScale(300, 300); 2620 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) { 2621 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision); 2622 fillPath.transform(scale); 2623 canvas->drawPath(fillPath, outlinePaint); 2624 canvas->translate(60, 0); 2625 if (1.f == precision) canvas->translate(-180, 100); 2626 } 2627 strokePath.transform(scale); 2628 strokePaint.setStrokeWidth(30); 2629 canvas->drawPath(strokePath, strokePaint); 2630 } 2631 ## 2632 2633## 2634 2635#Method bool getFillPath(const SkPath& src, SkPath* dst) const 2636 2637#In Fill_Path 2638 The filled equivalent of the stroked path. 2639 2640 Replaces dst with the src path modified by Path_Effect and Style_Stroke. 2641 Path_Effect, if any, is not culled. Stroke_Width is created with default precision. 2642 2643 #Param src Path read to create a filled version ## 2644 #Param dst resulting Path dst may be the same as src, but may not be nullptr ## 2645 #Return true if the path represents Style_Fill, or false if it represents Hairline ## 2646 2647 #Example 2648 #Height 128 2649 void draw(SkCanvas* canvas) { 2650 SkPaint paint; 2651 paint.setStyle(SkPaint::kStroke_Style); 2652 paint.setStrokeWidth(10); 2653 SkPath strokePath; 2654 strokePath.moveTo(20, 20); 2655 strokePath.lineTo(100, 100); 2656 canvas->drawPath(strokePath, paint); 2657 SkPath fillPath; 2658 paint.getFillPath(strokePath, &fillPath); 2659 paint.setStrokeWidth(2); 2660 canvas->translate(40, 0); 2661 canvas->drawPath(fillPath, paint); 2662 } 2663 ## 2664 2665## 2666 2667#SeeAlso Style_Stroke Stroke_Width Path_Effect 2668 2669#Subtopic Fill_Path ## 2670# ------------------------------------------------------------------------------ 2671#Subtopic Shader_Methods 2672#Line # get and set Shader ## 2673 2674Shader defines the colors used when drawing a shape. 2675Shader may be an image, a gradient, or a computed fill. 2676If Paint has no Shader, then Color fills the shape. 2677 2678Shader is modulated by Color_Alpha component of Color. 2679If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes 2680the fill. 2681 2682The drawn transparency can be modified without altering Shader, by changing Color_Alpha. 2683 2684#Example 2685void draw(SkCanvas* canvas) { 2686 SkPaint paint; 2687 SkPoint center = { 50, 50 }; 2688 SkScalar radius = 50; 2689 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 }; 2690 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, 2691 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); 2692 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) { 2693 paint.setAlpha((int) (a * 255)); 2694 canvas->drawCircle(center.fX, center.fY, radius, paint); 2695 canvas->translate(70, 70); 2696 } 2697} 2698## 2699 2700If Shader generates only Color_Alpha then all components of Color modulate the output. 2701 2702#Example 2703void draw(SkCanvas* canvas) { 2704 SkPaint paint; 2705 SkBitmap bitmap; 2706 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha 2707 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF }; 2708 bitmap.setPixels(pixels); 2709 paint.setShader(SkShader::MakeBitmapShader(bitmap, 2710 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode)); 2711 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) { 2712 paint.setColor(c); // all components in color affect shader 2713 canvas->drawCircle(50, 50, 50, paint); 2714 canvas->translate(70, 70); 2715 } 2716} 2717## 2718 2719#Method SkShader* getShader() const 2720 2721#In Shader_Methods 2722#Line # returns Shader, multiple drawing colors; gradients ## 2723 Optional colors used when filling a path, such as a gradient. 2724 2725 Does not alter Shader Reference_Count. 2726 2727 #Return Shader if previously set, nullptr otherwise ## 2728 2729 #Example 2730 void draw(SkCanvas* canvas) { 2731 SkPaint paint; 2732 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '='); 2733 paint.setShader(SkShader::MakeEmptyShader()); 2734 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '='); 2735 } 2736 2737 #StdOut 2738 nullptr == shader 2739 nullptr != shader 2740 ## 2741 ## 2742 2743## 2744 2745#Method sk_sp<SkShader> refShader() const 2746 2747#In Shader_Methods 2748#Line # references Shader, multiple drawing colors; gradients ## 2749 Optional colors used when filling a path, such as a gradient. 2750 2751 Increases Shader Reference_Count by one. 2752 2753 #Return Shader if previously set, nullptr otherwise ## 2754 2755 #Example 2756 void draw(SkCanvas* canvas) { 2757 SkPaint paint1, paint2; 2758 paint1.setShader(SkShader::MakeEmptyShader()); 2759 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false"); 2760 paint2.setShader(paint1.refShader()); 2761 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false"); 2762 } 2763 2764 #StdOut 2765 shader unique: true 2766 shader unique: false 2767 ## 2768 ## 2769 2770## 2771 2772#Method void setShader(sk_sp<SkShader> shader) 2773 2774#In Shader_Methods 2775#Line # sets Shader, multiple drawing colors; gradients ## 2776 Optional colors used when filling a path, such as a gradient. 2777 2778 Sets Shader to shader, decreasing Reference_Count of the previous Shader. 2779 Increments shader Reference_Count by one. 2780 2781 #Param shader how geometry is filled with color; if nullptr, Color is used instead ## 2782 2783 #Example 2784 #Height 64 2785 void draw(SkCanvas* canvas) { 2786 SkPaint paint; 2787 paint.setColor(SK_ColorBLUE); 2788 paint.setShader(SkShader::MakeColorShader(SK_ColorRED)); 2789 canvas->drawRect(SkRect::MakeWH(40, 40), paint); 2790 paint.setShader(nullptr); 2791 canvas->translate(50, 0); 2792 canvas->drawRect(SkRect::MakeWH(40, 40), paint); 2793 } 2794 ## 2795 2796## 2797 2798#Subtopic Shader_Methods ## 2799# ------------------------------------------------------------------------------ 2800#Subtopic Color_Filter_Methods 2801#Line # get and set Color_Filter ## 2802 2803Color_Filter alters the color used when drawing a shape. 2804Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters. 2805If Paint has no Color_Filter, the color is unaltered. 2806 2807The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha. 2808 2809#Example 2810#Height 128 2811void draw(SkCanvas* canvas) { 2812 SkPaint paint; 2813 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000)); 2814 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) { 2815 paint.setColor(c); 2816 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint); 2817 paint.setAlpha(0x80); 2818 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint); 2819 canvas->translate(100, 0); 2820 } 2821} 2822## 2823 2824#Method SkColorFilter* getColorFilter() const 2825 2826#In Color_Filter_Methods 2827#Line # returns Color_Filter, how colors are altered ## 2828 Returns Color_Filter if set, or nullptr. 2829 Does not alter Color_Filter Reference_Count. 2830 2831 #Return Color_Filter if previously set, nullptr otherwise ## 2832 2833 #Example 2834 void draw(SkCanvas* canvas) { 2835 SkPaint paint; 2836 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '='); 2837 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn)); 2838 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '='); 2839 } 2840 2841 #StdOut 2842 nullptr == color filter 2843 nullptr != color filter 2844 ## 2845 ## 2846## 2847 2848#Method sk_sp<SkColorFilter> refColorFilter() const 2849 2850#In Color_Filter_Methods 2851#Line # references Color_Filter, how colors are altered ## 2852 Returns Color_Filter if set, or nullptr. 2853 Increases Color_Filter Reference_Count by one. 2854 2855 #Return Color_Filter if set, or nullptr ## 2856 2857 #Example 2858 void draw(SkCanvas* canvas) { 2859 SkPaint paint1, paint2; 2860 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop)); 2861 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false"); 2862 paint2.setColorFilter(paint1.refColorFilter()); 2863 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false"); 2864 } 2865 2866 #StdOut 2867 color filter unique: true 2868 color filter unique: false 2869 ## 2870 ## 2871## 2872 2873#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter) 2874 2875#In Color_Filter_Methods 2876#Line # sets Color_Filter, alters color ## 2877Sets Color_Filter to filter, decreasing Reference_Count of the previous 2878Color_Filter. Pass nullptr to clear Color_Filter. 2879 2880Increments filter Reference_Count by one. 2881 2882 #Param colorFilter Color_Filter to apply to subsequent draw ## 2883 2884 #Example 2885 #Height 64 2886 void draw(SkCanvas* canvas) { 2887 SkPaint paint; 2888 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn)); 2889 canvas->drawRect(SkRect::MakeWH(50, 50), paint); 2890 paint.setColorFilter(nullptr); 2891 canvas->translate(70, 0); 2892 canvas->drawRect(SkRect::MakeWH(50, 50), paint); 2893 } 2894 ## 2895 2896## 2897 2898#Subtopic Color_Filter_Methods ## 2899# ------------------------------------------------------------------------------ 2900#Subtopic Blend_Mode_Methods 2901#Line # get and set Blend_Mode ## 2902 2903Blend_Mode describes how Color combines with the destination color. 2904The default setting, SkBlendMode::kSrcOver, draws the source color 2905over the destination color. 2906 2907#Example 2908void draw(SkCanvas* canvas) { 2909 SkPaint normal, blender; 2910 normal.setColor(0xFF58a889); 2911 blender.setColor(0xFF8958a8); 2912 canvas->clear(0); 2913 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) { 2914 normal.setBlendMode(SkBlendMode::kSrcOver); 2915 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal); 2916 blender.setBlendMode(m); 2917 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender); 2918 canvas->translate(70, 70); 2919 } 2920} 2921## 2922 2923#SeeAlso Blend_Mode 2924 2925#Method SkBlendMode getBlendMode() const 2926 2927#In Blend_Mode_Methods 2928#Line # returns Blend_Mode, how colors combine with Device ## 2929 Returns Blend_Mode. 2930 By default, returns SkBlendMode::kSrcOver. 2931 2932 #Return mode used to combine source color with destination color ## 2933 2934 #Example 2935 void draw(SkCanvas* canvas) { 2936 SkPaint paint; 2937 SkDebugf("kSrcOver %c= getBlendMode\n", 2938 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!'); 2939 paint.setBlendMode(SkBlendMode::kSrc); 2940 SkDebugf("kSrcOver %c= getBlendMode\n", 2941 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!'); 2942 } 2943 2944 #StdOut 2945 kSrcOver == getBlendMode 2946 kSrcOver != getBlendMode 2947 ## 2948 ## 2949 2950## 2951 2952#Method bool isSrcOver() const 2953 2954#In Blend_Mode_Methods 2955#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ## 2956 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default. 2957 2958 #Return true if Blend_Mode is SkBlendMode::kSrcOver ## 2959 2960 #Example 2961 void draw(SkCanvas* canvas) { 2962 SkPaint paint; 2963 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 2964 paint.setBlendMode(SkBlendMode::kSrc); 2965 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 2966 } 2967 2968 #StdOut 2969 isSrcOver == true 2970 isSrcOver != true 2971 ## 2972 ## 2973 2974## 2975 2976#Method void setBlendMode(SkBlendMode mode) 2977 2978#In Blend_Mode_Methods 2979#Line # sets Blend_Mode, how colors combine with destination ## 2980 Sets Blend_Mode to mode. 2981 Does not check for valid input. 2982 2983 #Param mode SkBlendMode used to combine source color and destination ## 2984 2985 #Example 2986 void draw(SkCanvas* canvas) { 2987 SkPaint paint; 2988 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 2989 paint.setBlendMode(SkBlendMode::kSrc); 2990 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!'); 2991 } 2992 2993 #StdOut 2994 isSrcOver == true 2995 isSrcOver != true 2996 ## 2997 ## 2998 2999## 3000 3001#Subtopic Blend_Mode_Methods ## 3002# ------------------------------------------------------------------------------ 3003#Subtopic Path_Effect_Methods 3004#Line # get and set Path_Effect ## 3005 3006Path_Effect modifies the path geometry before drawing it. 3007Path_Effect may implement dashing, custom fill effects and custom stroke effects. 3008If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked. 3009 3010#Example 3011#Height 160 3012 void draw(SkCanvas* canvas) { 3013 SkPaint paint; 3014 paint.setStyle(SkPaint::kStroke_Style); 3015 paint.setStrokeWidth(16); 3016 SkScalar intervals[] = {30, 10}; 3017 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1)); 3018 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint); 3019 } 3020## 3021 3022#SeeAlso Path_Effect 3023 3024#Method SkPathEffect* getPathEffect() const 3025 3026#In Path_Effect_Methods 3027#Line # returns Path_Effect, modifications to path geometry; dashing ## 3028 Returns Path_Effect if set, or nullptr. 3029 Does not alter Path_Effect Reference_Count. 3030 3031 #Return Path_Effect if previously set, nullptr otherwise ## 3032 3033 #Example 3034 void draw(SkCanvas* canvas) { 3035 SkPaint paint; 3036 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '='); 3037 paint.setPathEffect(SkCornerPathEffect::Make(10)); 3038 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '='); 3039 } 3040 3041 #StdOut 3042 nullptr == path effect 3043 nullptr != path effect 3044 ## 3045 ## 3046 3047## 3048 3049 3050#Method sk_sp<SkPathEffect> refPathEffect() const 3051 3052#In Path_Effect_Methods 3053#Line # references Path_Effect, modifications to path geometry; dashing ## 3054 Returns Path_Effect if set, or nullptr. 3055 Increases Path_Effect Reference_Count by one. 3056 3057 #Return Path_Effect if previously set, nullptr otherwise ## 3058 3059 #Example 3060 void draw(SkCanvas* canvas) { 3061 SkPaint paint1, paint2; 3062 SkScalar intervals[] = {1, 2}; 3063 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10)); 3064 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false"); 3065 paint2.setPathEffect(paint1.refPathEffect()); 3066 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false"); 3067 } 3068 3069 #StdOut 3070 path effect unique: true 3071 path effect unique: false 3072 ## 3073 ## 3074 3075## 3076 3077 3078#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect) 3079 3080#In Path_Effect_Methods 3081#Line # sets Path_Effect, modifications to path geometry; dashing ## 3082Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous 3083Path_Effect. Pass nullptr to leave the path geometry unaltered. 3084 3085Increments pathEffect Reference_Count by one. 3086 3087 #Param pathEffect replace Path with a modification when drawn ## 3088 3089 #Example 3090 void draw(SkCanvas* canvas) { 3091 SkPaint paint; 3092 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5)); 3093 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint); 3094 } 3095 ## 3096 3097## 3098 3099#Subtopic Path_Effect_Methods ## 3100# ------------------------------------------------------------------------------ 3101#Subtopic Mask_Filter_Methods 3102#Line # get and set Mask_Filter ## 3103 3104Mask_Filter uses coverage of the shape drawn to create Mask_Alpha. 3105Mask_Filter takes a Mask, and returns a Mask. 3106 3107Mask_Filter may change the geometry and transparency of the shape, such as 3108creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from 3109modifying the draw. 3110 3111#Example 3112 void draw(SkCanvas* canvas) { 3113 SkPaint paint; 3114 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 3)); 3115 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint); 3116 } 3117## 3118 3119#Method SkMaskFilter* getMaskFilter() const 3120 3121#In Mask_Filter_Methods 3122#Line # returns Mask_Filter, alterations to Mask_Alpha ## 3123 Returns Mask_Filter if set, or nullptr. 3124 Does not alter Mask_Filter Reference_Count. 3125 3126 #Return Mask_Filter if previously set, nullptr otherwise ## 3127 3128 #Example 3129 void draw(SkCanvas* canvas) { 3130 SkPaint paint; 3131 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '='); 3132 paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3)); 3133 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '='); 3134 } 3135 3136 #StdOut 3137 nullptr == mask filter 3138 nullptr != mask filter 3139 ## 3140 ## 3141 3142## 3143 3144#Method sk_sp<SkMaskFilter> refMaskFilter() const 3145 3146#In Mask_Filter_Methods 3147#Line # references Mask_Filter, alterations to Mask_Alpha ## 3148 Returns Mask_Filter if set, or nullptr. 3149 3150 Increases Mask_Filter Reference_Count by one. 3151 3152 #Return Mask_Filter if previously set, nullptr otherwise ## 3153 3154 #Example 3155 void draw(SkCanvas* canvas) { 3156 SkPaint paint1, paint2; 3157 paint1.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 1)); 3158 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false"); 3159 paint2.setMaskFilter(paint1.refMaskFilter()); 3160 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false"); 3161 } 3162 3163 #StdOut 3164 mask filter unique: true 3165 mask filter unique: false 3166 ## 3167 ## 3168 3169## 3170 3171#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter) 3172 3173#In Mask_Filter_Methods 3174#Line # sets Mask_Filter, alterations to Mask_Alpha ## 3175Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous 3176Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on 3177Mask_Alpha unaltered. 3178 3179Increments maskFilter Reference_Count by one. 3180 3181 #Param maskFilter modifies clipping mask generated from drawn geometry ## 3182 3183 #Example 3184 void draw(SkCanvas* canvas) { 3185 SkPaint paint; 3186 paint.setStyle(SkPaint::kStroke_Style); 3187 paint.setStrokeWidth(10); 3188 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 10)); 3189 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint); 3190 } 3191 ## 3192 3193## 3194 3195#Subtopic Mask_Filter_Methods ## 3196# ------------------------------------------------------------------------------ 3197#Subtopic Typeface_Methods 3198#Line # get and set Typeface ## 3199 3200Typeface identifies the font used when drawing and measuring text. 3201Typeface may be specified by name, from a file, or from a data stream. 3202The default Typeface defers to the platform-specific default font 3203implementation. 3204 3205#Example 3206#Height 100 3207 void draw(SkCanvas* canvas) { 3208 SkPaint paint; 3209 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle())); 3210 paint.setAntiAlias(true); 3211 paint.setTextSize(36); 3212 canvas->drawString("A Big Hello!", 10, 40, paint); 3213 paint.setTypeface(nullptr); 3214 paint.setFakeBoldText(true); 3215 canvas->drawString("A Big Hello!", 10, 80, paint); 3216 } 3217## 3218 3219#Method SkTypeface* getTypeface() const 3220 3221#In Typeface_Methods 3222#Line # returns Typeface, font description ## 3223 Returns Typeface if set, or nullptr. 3224 Increments Typeface Reference_Count by one. 3225 3226 #Return Typeface if previously set, nullptr otherwise ## 3227 3228 #Example 3229 void draw(SkCanvas* canvas) { 3230 SkPaint paint; 3231 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '='); 3232 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle())); 3233 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '='); 3234 } 3235 3236 #StdOut 3237 nullptr == typeface 3238 nullptr != typeface 3239 ## 3240 ## 3241 3242## 3243 3244#Method sk_sp<SkTypeface> refTypeface() const 3245 3246#In Typeface_Methods 3247#Line # references Typeface, font description ## 3248 Increases Typeface Reference_Count by one. 3249 3250 #Return Typeface if previously set, nullptr otherwise ## 3251 3252 #Example 3253 void draw(SkCanvas* canvas) { 3254 SkPaint paint1, paint2; 3255 paint1.setTypeface(SkTypeface::MakeFromName("monospace", 3256 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, 3257 SkFontStyle::kItalic_Slant))); 3258 SkDebugf("typeface1 %c= typeface2\n", 3259 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!'); 3260 paint2.setTypeface(paint1.refTypeface()); 3261 SkDebugf("typeface1 %c= typeface2\n", 3262 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!'); 3263 } 3264 3265 #StdOut 3266 typeface1 != typeface2 3267 typeface1 == typeface2 3268 ## 3269 ## 3270 3271## 3272 3273#Method void setTypeface(sk_sp<SkTypeface> typeface) 3274 3275#In Typeface_Methods 3276#Line # sets Typeface, font description ## 3277Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface. 3278Pass nullptr to clear Typeface and use the default typeface. Increments 3279typeface Reference_Count by one. 3280 3281 #Param typeface font and style used to draw text ## 3282 3283 #Example 3284 #Height 64 3285 void draw(SkCanvas* canvas) { 3286 SkPaint paint; 3287 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle())); 3288 canvas->drawString("hamburgerfons", 10, 30, paint); 3289 paint.setTypeface(nullptr); 3290 canvas->drawString("hamburgerfons", 10, 50, paint); 3291 } 3292 ## 3293 3294## 3295 3296#Subtopic Typeface_Methods ## 3297# ------------------------------------------------------------------------------ 3298#Subtopic Image_Filter_Methods 3299#Line # get and set Image_Filter ## 3300 3301Image_Filter operates on the pixel representation of the shape, as modified by Paint 3302with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap, 3303which is drawn to the device using the set Blend_Mode. 3304 3305Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter 3306can operate on all channels of Color, while Mask_Filter generates Alpha only. 3307Image_Filter operates independently of and can be used in combination with 3308Mask_Filter. 3309 3310#Example 3311 #ToDo explain why the two draws are so different ## 3312 void draw(SkCanvas* canvas) { 3313 SkPaint paint; 3314 paint.setStyle(SkPaint::kStroke_Style); 3315 paint.setStrokeWidth(2); 3316 SkRegion region; 3317 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op); 3318 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op); 3319 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr)); 3320 canvas->drawRegion(region, paint); 3321 paint.setImageFilter(nullptr); 3322 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5)); 3323 canvas->translate(100, 100); 3324 canvas->drawRegion(region, paint); 3325 } 3326## 3327 3328#Method SkImageFilter* getImageFilter() const 3329 3330#In Image_Filter_Methods 3331#Line # returns Image_Filter, alter pixels; blur ## 3332 Returns Image_Filter if set, or nullptr. 3333 Does not alter Image_Filter Reference_Count. 3334 3335 #Return Image_Filter if previously set, nullptr otherwise ## 3336 3337 #Example 3338 void draw(SkCanvas* canvas) { 3339 SkPaint paint; 3340 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '='); 3341 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr)); 3342 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '='); 3343 } 3344 3345 #StdOut 3346 nullptr == image filter 3347 nullptr != image filter 3348 ## 3349 ## 3350 3351## 3352 3353#Method sk_sp<SkImageFilter> refImageFilter() const 3354 3355#In Image_Filter_Methods 3356#Line # references Image_Filter, alter pixels; blur ## 3357 Returns Image_Filter if set, or nullptr. 3358 Increases Image_Filter Reference_Count by one. 3359 3360 #Return Image_Filter if previously set, nullptr otherwise ## 3361 3362 #Example 3363 void draw(SkCanvas* canvas) { 3364 SkPaint paint1, paint2; 3365 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr)); 3366 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false"); 3367 paint2.setImageFilter(paint1.refImageFilter()); 3368 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false"); 3369 } 3370 3371 #StdOut 3372 image filter unique: true 3373 image filter unique: false 3374 ## 3375 ## 3376 3377## 3378 3379#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter) 3380 3381#In Image_Filter_Methods 3382#Line # sets Image_Filter, alter pixels; blur ## 3383Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous 3384Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect 3385on drawing. 3386 3387Increments imageFilter Reference_Count by one. 3388 3389 #Param imageFilter how Image is sampled when transformed ## 3390 3391 #Example 3392 #Height 160 3393 void draw(SkCanvas* canvas) { 3394 SkBitmap bitmap; 3395 bitmap.allocN32Pixels(100, 100); 3396 SkCanvas offscreen(bitmap); 3397 SkPaint paint; 3398 paint.setAntiAlias(true); 3399 paint.setColor(SK_ColorWHITE); 3400 paint.setTextSize(96); 3401 offscreen.clear(0); 3402 offscreen.drawString("e", 20, 70, paint); 3403 paint.setImageFilter( 3404 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10), 3405 SK_ColorWHITE, 1, 2, nullptr, nullptr)); 3406 canvas->drawBitmap(bitmap, 0, 0, &paint); 3407 } 3408 ## 3409 3410## 3411 3412#Subtopic Image_Filter_Methods ## 3413# ------------------------------------------------------------------------------ 3414#Subtopic Draw_Looper_Methods 3415#Line # get and set Draw_Looper ## 3416 3417Draw_Looper sets a modifier that communicates state from one Draw_Layer 3418to another to construct the draw. 3419 3420Draw_Looper draws one or more times, modifying the canvas and paint each time. 3421Draw_Looper may be used to draw multiple colors or create a colored shadow. 3422Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw. 3423 3424#Example 3425#Height 128 3426 void draw(SkCanvas* canvas) { 3427 SkLayerDrawLooper::LayerInfo info; 3428 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit; 3429 info.fColorMode = SkBlendMode::kSrc; 3430 SkLayerDrawLooper::Builder looperBuilder; 3431 SkPaint* loopPaint = looperBuilder.addLayer(info); 3432 loopPaint->setColor(SK_ColorRED); 3433 info.fOffset.set(20, 20); 3434 loopPaint = looperBuilder.addLayer(info); 3435 loopPaint->setColor(SK_ColorBLUE); 3436 SkPaint paint; 3437 paint.setDrawLooper(looperBuilder.detach()); 3438 canvas->drawCircle(50, 50, 50, paint); 3439 } 3440 3441## 3442 3443#Method SkDrawLooper* getDrawLooper() const 3444 3445#In Draw_Looper_Methods 3446#Line # returns Draw_Looper, multiple layers ## 3447 Returns Draw_Looper if set, or nullptr. 3448 Does not alter Draw_Looper Reference_Count. 3449 3450 #Return Draw_Looper if previously set, nullptr otherwise ## 3451 3452 #Example 3453 void draw(SkCanvas* canvas) { 3454 SkPaint paint; 3455 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '='); 3456 SkLayerDrawLooper::Builder looperBuilder; 3457 paint.setDrawLooper(looperBuilder.detach()); 3458 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '='); 3459 } 3460 3461 #StdOut 3462 nullptr == draw looper 3463 nullptr != draw looper 3464 ## 3465 ## 3466 3467## 3468 3469#Method sk_sp<SkDrawLooper> refDrawLooper() const 3470 3471#In Draw_Looper_Methods 3472#Line # references Draw_Looper, multiple layers ## 3473 Returns Draw_Looper if set, or nullptr. 3474 Increases Draw_Looper Reference_Count by one. 3475 3476 #Return Draw_Looper if previously set, nullptr otherwise ## 3477 3478 #Example 3479 void draw(SkCanvas* canvas) { 3480 SkPaint paint1, paint2; 3481 SkLayerDrawLooper::Builder looperBuilder; 3482 paint1.setDrawLooper(looperBuilder.detach()); 3483 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false"); 3484 paint2.setDrawLooper(paint1.refDrawLooper()); 3485 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false"); 3486 } 3487 3488 #StdOut 3489 draw looper unique: true 3490 draw looper unique: false 3491 ## 3492 ## 3493 3494## 3495 3496#Method SkDrawLooper* getLooper() const 3497#Bug 6259 3498#Deprecated 3499## 3500 3501#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper) 3502#In Draw_Looper_Methods 3503#Line # sets Draw_Looper, multiple layers ## 3504Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous 3505drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on 3506drawing unaltered. 3507 3508Increments drawLooper Reference_Count by one. 3509 3510 #Param drawLooper iterates through drawing one or more time, altering Paint ## 3511 3512 #Example 3513 #Height 128 3514 void draw(SkCanvas* canvas) { 3515 SkPaint paint; 3516 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10)); 3517 paint.setStyle(SkPaint::kStroke_Style); 3518 paint.setStrokeWidth(10); 3519 paint.setAntiAlias(true); 3520 paint.setColor(0x7f0000ff); 3521 canvas->drawCircle(70, 70, 50, paint); 3522 } 3523 ## 3524 3525## 3526 3527#Method void setLooper(sk_sp<SkDrawLooper> drawLooper) 3528#Bug 6259 3529#Deprecated 3530## 3531 3532#Subtopic Draw_Looper_Methods ## 3533 3534# ------------------------------------------------------------------------------ 3535#Subtopic Text_Align 3536#Line # text placement relative to position ## 3537 3538#Enum Align 3539#Line # glyph locations relative to text position ## 3540#Code 3541 enum Align { 3542 kLeft_Align, 3543 kCenter_Align, 3544 kRight_Align, 3545 }; 3546## 3547 3548Align adjusts the text relative to the text position. 3549Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText, 3550SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath, 3551SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob, 3552and SkCanvas::drawString; 3553as well as calls that place text Glyphs like getTextWidths and getTextPath. 3554 3555The text position is set by the font for both horizontal and vertical text. 3556Typically, for horizontal text, the position is to the left side of the glyph on the 3557base line; and for vertical text, the position is the horizontal center of the glyph 3558at the caps height. 3559 3560Align adjusts the glyph position to center it or move it to abut the position 3561using the metrics returned by the font. 3562 3563Align defaults to kLeft_Align. 3564 3565#Const kLeft_Align 0 3566 Leaves the glyph at the position computed by the font offset by the text position. 3567## 3568 3569#Const kCenter_Align 1 3570 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and 3571 half its height if Flags has kVerticalText_Flag set. 3572## 3573 3574#Const kRight_Align 2 3575 Moves the glyph by its width if Flags has kVerticalText_Flag clear, 3576 and by its height if Flags has kVerticalText_Flag set. 3577## 3578 3579#Enum ## 3580 3581#Enum 3582#Line # number of Text_Align values ## 3583 3584#Code 3585 enum { 3586 kAlignCount = 3, 3587 }; 3588## 3589 3590#Const kAlignCount 3 3591 The number of different Text_Align values defined. 3592## 3593 3594#Enum ## 3595 3596#Example 3597 #Height 160 3598 #Description 3599 Each position separately moves the glyph in drawPosText. 3600 ## 3601 void draw(SkCanvas* canvas) { 3602 SkPaint paint; 3603 paint.setTextSize(40); 3604 SkPoint position[] = {{100, 50}, {150, 40}}; 3605 for (SkPaint::Align a : { SkPaint::kLeft_Align, 3606 SkPaint::kCenter_Align, 3607 SkPaint::kRight_Align}) { 3608 paint.setTextAlign(a); 3609 canvas->drawPosText("Aa", 2, position, paint); 3610 canvas->translate(0, 50); 3611 } 3612 } 3613## 3614 3615#Example 3616 #Height 160 3617 #Description 3618 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align. 3619 ## 3620 void draw(SkCanvas* canvas) { 3621 SkPaint paint; 3622 paint.setTextSize(40); 3623 paint.setVerticalText(true); 3624 for (SkPaint::Align a : { SkPaint::kLeft_Align, 3625 SkPaint::kCenter_Align, 3626 SkPaint::kRight_Align }) { 3627 paint.setTextAlign(a); 3628 canvas->drawString("Aa", 50, 80, paint); 3629 canvas->translate(50, 0); 3630 } 3631 } 3632## 3633 3634#Method Align getTextAlign() const 3635 3636#In Text_Align 3637#Line # returns Align: left, center, or right ## 3638 Returns Text_Align. 3639 Returns kLeft_Align if Text_Align has not been set. 3640 3641 #Return text placement relative to position ## 3642 3643 #Example 3644 SkPaint paint; 3645 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!'); 3646 3647 #StdOut 3648 kLeft_Align == default 3649 ## 3650 ## 3651## 3652 3653#Method void setTextAlign(Align align) 3654 3655#In Text_Align 3656#Line # sets Align: left, center, or right ## 3657 Sets Text_Align to align. 3658 Has no effect if align is an invalid value. 3659 3660 #Param align text placement relative to position ## 3661 3662 #Example 3663 #Height 160 3664 #Description 3665 Text is left-aligned by default, and then set to center. Setting the 3666 alignment out of range has no effect. 3667 ## 3668 void draw(SkCanvas* canvas) { 3669 SkPaint paint; 3670 paint.setTextSize(40); 3671 canvas->drawString("Aa", 100, 50, paint); 3672 paint.setTextAlign(SkPaint::kCenter_Align); 3673 canvas->drawString("Aa", 100, 100, paint); 3674 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount); 3675 canvas->drawString("Aa", 100, 150, paint); 3676 } 3677 ## 3678 3679## 3680 3681#Subtopic Text_Align ## 3682# ------------------------------------------------------------------------------ 3683#Subtopic Text_Size 3684#Line # overall height in points ## 3685 3686Text_Size adjusts the overall text size in points. 3687Text_Size can be set to any positive value or zero. 3688Text_Size defaults to 12. 3689Set SkPaintDefaults_TextSize at compile time to change the default setting. 3690 3691#Example 3692#Height 135 3693 void draw(SkCanvas* canvas) { 3694 SkPaint paint; 3695 canvas->drawString("12 point", 10, 20, paint); 3696 paint.setTextSize(24); 3697 canvas->drawString("24 point", 10, 60, paint); 3698 paint.setTextSize(48); 3699 canvas->drawString("48 point", 10, 120, paint); 3700 } 3701## 3702 3703#Method SkScalar getTextSize() const 3704 3705#In Text_Size 3706#Line # returns text size in points ## 3707 Returns Text_Size in points. 3708 3709 #Return typographic height of text ## 3710 3711 #Example 3712 SkPaint paint; 3713 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!'); 3714 ## 3715 3716## 3717 3718#Method void setTextSize(SkScalar textSize) 3719 3720#In Text_Size 3721#Line # sets text size in points ## 3722 Sets Text_Size in points. 3723 Has no effect if textSize is not greater than or equal to zero. 3724 3725 #Param textSize typographic height of text ## 3726 3727 #Example 3728 SkPaint paint; 3729 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!'); 3730 paint.setTextSize(-20); 3731 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!'); 3732 ## 3733 3734## 3735 3736#Subtopic Text_Size ## 3737# ------------------------------------------------------------------------------ 3738#Subtopic Text_Scale_X 3739#Line # text horizontal scale ## 3740 3741Text_Scale_X adjusts the text horizontal scale. 3742Text scaling approximates condensed and expanded type faces when the actual face 3743is not available. 3744Text_Scale_X can be set to any value. 3745Text_Scale_X defaults to 1. 3746 3747#Example 3748#Height 128 3749 void draw(SkCanvas* canvas) { 3750 SkPaint paint; 3751 paint.setAntiAlias(true); 3752 paint.setTextSize(24); 3753 paint.setTextScaleX(.8f); 3754 canvas->drawString("narrow", 10, 20, paint); 3755 paint.setTextScaleX(1); 3756 canvas->drawString("normal", 10, 60, paint); 3757 paint.setTextScaleX(1.2f); 3758 canvas->drawString("wide", 10, 100, paint); 3759 } 3760## 3761 3762#Method SkScalar getTextScaleX() const 3763 3764#In Text_Scale_X 3765#Line # returns the text horizontal scale; condensed text ## 3766 Returns Text_Scale_X. 3767 Default value is 1. 3768 3769 #Return text horizontal scale ## 3770 3771 #Example 3772 SkPaint paint; 3773 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!'); 3774 ## 3775 3776## 3777 3778 3779#Method void setTextScaleX(SkScalar scaleX) 3780 3781#In Text_Scale_X 3782#Line # sets the text horizontal scale; condensed text ## 3783 Sets Text_Scale_X. 3784 Default value is 1. 3785 3786 #Param scaleX text horizontal scale ## 3787 3788 #Example 3789 SkPaint paint; 3790 paint.setTextScaleX(0.f / 0.f); 3791 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is"); 3792 ## 3793 3794## 3795 3796#Subtopic Text_Scale_X ## 3797 3798#Subtopic Text_Skew_X 3799#Line # text horizontal slant ## 3800 3801 3802Text_Skew_X adjusts the text horizontal slant. 3803Text skewing approximates italic and oblique type faces when the actual face 3804is not available. 3805Text_Skew_X can be set to any value. 3806Text_Skew_X defaults to 0. 3807 3808#Example 3809#Height 128 3810 void draw(SkCanvas* canvas) { 3811 SkPaint paint; 3812 paint.setAntiAlias(true); 3813 paint.setTextSize(24); 3814 paint.setTextSkewX(-.25f); 3815 canvas->drawString("right-leaning", 10, 100, paint); 3816 paint.setTextSkewX(0); 3817 canvas->drawString("normal", 10, 60, paint); 3818 paint.setTextSkewX(.25f); 3819 canvas->drawString("left-leaning", 10, 20, paint); 3820 } 3821## 3822 3823#Method SkScalar getTextSkewX() const 3824 3825#In Text_Skew_X 3826#Line # returns the text horizontal skew; oblique text ## 3827 Returns Text_Skew_X. 3828 Default value is zero. 3829 3830 #Return additional shear in x-axis relative to y-axis ## 3831 3832 #Example 3833 SkPaint paint; 3834 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!'); 3835 ## 3836 3837## 3838 3839#Method void setTextSkewX(SkScalar skewX) 3840 3841#In Text_Skew_X 3842#Line # sets the text horizontal skew; oblique text ## 3843 Sets Text_Skew_X. 3844 Default value is zero. 3845 3846 #Param skewX additional shear in x-axis relative to y-axis ## 3847 3848 #Example 3849 SkPaint paint; 3850 paint.setTextScaleX(1.f / 0.f); 3851 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not"); 3852 ## 3853 3854## 3855 3856#Subtopic Text_Skew_X ## 3857 3858# ------------------------------------------------------------------------------ 3859#Subtopic Text_Encoding 3860#Line # text encoded as characters or Glyphs ## 3861 3862#Enum TextEncoding 3863#Line # character or glyph encoded size ## 3864 3865#Code 3866 enum TextEncoding { 3867 kUTF8_TextEncoding, 3868 kUTF16_TextEncoding, 3869 kUTF32_TextEncoding, 3870 kGlyphID_TextEncoding, 3871 }; 3872## 3873 3874TextEncoding determines whether text specifies character codes and their encoded 3875size, or glyph indices. Characters are encoded as specified by the 3876#A Unicode standard # http://unicode.org/standard/standard.html ## 3877. 3878 3879Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32. 3880All character code formats are able to represent all of Unicode, differing only 3881in the total storage required. 3882 3883#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ## 3884 encodes each character as one or more 8-bit bytes. 3885 3886#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ## 3887 encodes each character as one or two 16-bit words. 3888 3889#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ## 3890 encodes each character as one 32-bit word. 3891 3892Font_Manager uses font data to convert character code points into glyph indices. 3893A glyph index is a 16-bit word. 3894 3895TextEncoding is set to kUTF8_TextEncoding by default. 3896 3897#Const kUTF8_TextEncoding 0 3898Uses bytes to represent UTF-8 or ASCII. 3899## 3900#Const kUTF16_TextEncoding 1 3901Uses two byte words to represent most of Unicode. 3902## 3903#Const kUTF32_TextEncoding 2 3904Uses four byte words to represent all of Unicode. 3905## 3906#Const kGlyphID_TextEncoding 3 3907Uses two byte words to represent glyph indices. 3908## 3909 3910#Enum ## 3911 3912#Example 3913#Height 128 3914#Description 3915First line is encoded in UTF-8. 3916Second line is encoded in UTF-16. 3917Third line is encoded in UTF-32. 3918Fourth line has 16 bit glyph indices. 3919## 3920void draw(SkCanvas* canvas) { 3921 SkPaint paint; 3922 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA"; 3923 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A }; 3924 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A }; 3925 paint.setTextSize(24); 3926 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint); 3927 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 3928 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint); 3929 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 3930 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint); 3931 uint16_t glyphs[SK_ARRAY_COUNT(hello32)]; 3932 paint.textToGlyphs(hello32, sizeof(hello32), glyphs); 3933 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 3934 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint); 3935} 3936## 3937 3938#Method TextEncoding getTextEncoding() const 3939 3940#In Text_Encoding 3941#Line # returns character or glyph encoded size ## 3942 Returns Text_Encoding. 3943 Text_Encoding determines how character code points are mapped to font glyph indices. 3944 3945 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or 3946 kGlyphID_TextEncoding 3947 ## 3948 3949 #Example 3950 SkPaint paint; 3951 SkDebugf("kUTF8_TextEncoding %c= text encoding\n", 3952 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!'); 3953 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 3954 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n", 3955 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!'); 3956 3957 #StdOut 3958 kUTF8_TextEncoding == text encoding 3959 kGlyphID_TextEncoding == text encoding 3960 ## 3961 ## 3962 3963## 3964 3965 3966#Method void setTextEncoding(TextEncoding encoding) 3967 3968#In Text_Encoding 3969#Line # sets character or glyph encoded size ## 3970 Sets Text_Encoding to encoding. 3971 Text_Encoding determines how character code points are mapped to font glyph indices. 3972 Invalid values for encoding are ignored. 3973 3974 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or 3975 kGlyphID_TextEncoding 3976 #Param ## 3977 3978 #Example 3979 SkPaint paint; 3980 paint.setTextEncoding((SkPaint::TextEncoding) 4); 3981 SkDebugf("4 %c= text encoding\n", 4 == paint.getTextEncoding() ? '=' : '!'); 3982 3983 #StdOut 3984 4 != text encoding 3985 ## 3986 ## 3987 3988## 3989 3990#Subtopic Text_Encoding ## 3991# ------------------------------------------------------------------------------ 3992#Subtopic Font_Metrics 3993#Line # common glyph dimensions ## 3994 3995Font_Metrics describe dimensions common to the Glyphs in Typeface. 3996The dimensions are computed by Font_Manager from font data and do not take 3997Paint settings other than Text_Size into account. 3998 3999Font dimensions specify the anchor to the left of the glyph at baseline as the origin. 4000X-axis values to the left of the glyph are negative, and to the right of the left glyph edge 4001are positive. 4002Y-axis values above the baseline are negative, and below the baseline are positive. 4003 4004#Example 4005#Width 512 4006void draw(SkCanvas* canvas) { 4007 SkPaint paint; 4008 paint.setAntiAlias(true); 4009 paint.setTextSize(120); 4010 SkPaint::FontMetrics fm; 4011 SkScalar lineHeight = paint.getFontMetrics(&fm); 4012 SkPoint pt = { 70, 180 }; 4013 canvas->drawString("M", pt.fX, pt.fY, paint); 4014 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint); 4015 SkScalar ascent = pt.fY + fm.fAscent; 4016 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint); 4017 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint); 4018 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint); 4019 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint); 4020 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint); 4021 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint); 4022 SkScalar xmin = pt.fX + fm.fXMin; 4023 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint); 4024 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint); 4025 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint); 4026 SkScalar upos = pt.fY + fm.fUnderlinePosition; 4027 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint); 4028 SkScalar ut = fm.fUnderlineThickness; 4029 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint); 4030 paint.setTextSize(12); 4031 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint); 4032 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint); 4033 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint); 4034 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint); 4035 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint); 4036 canvas->rotate(-90); 4037 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint); 4038 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint); 4039 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint); 4040 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint); 4041 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint); 4042 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint); 4043 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint); 4044} 4045## 4046 4047#Struct FontMetrics 4048#Line # values computed by Font_Manager using Typeface ## 4049 4050#Code 4051 struct FontMetrics { 4052 enum FontMetricsFlags { 4053 kUnderlineThicknessIsValid_Flag = 1 << 0, 4054 kUnderlinePositionIsValid_Flag = 1 << 1, 4055 kStrikeoutThicknessIsValid_Flag = 1 << 2, 4056 kStrikeoutPositionIsValid_Flag = 1 << 3, 4057 }; 4058 4059 uint32_t fFlags; 4060 SkScalar fTop; 4061 SkScalar fAscent; 4062 SkScalar fDescent; 4063 SkScalar fBottom; 4064 SkScalar fLeading; 4065 SkScalar fAvgCharWidth; 4066 SkScalar fMaxCharWidth; 4067 SkScalar fXMin; 4068 SkScalar fXMax; 4069 SkScalar fXHeight; 4070 SkScalar fCapHeight; 4071 SkScalar fUnderlineThickness; 4072 SkScalar fUnderlinePosition; 4073 SkScalar fStrikeoutThickness; 4074 SkScalar fStrikeoutPosition; 4075 4076 bool hasUnderlineThickness(SkScalar* thickness) const; 4077 bool hasUnderlinePosition(SkScalar* position) const; 4078 bool hasStrikeoutThickness(SkScalar* thickness) const; 4079 bool hasStrikeoutPosition(SkScalar* position) const; 4080 }; 4081## 4082 4083 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values 4084 computed by Font_Manager using Typeface. Values are set to zero if they are 4085 not available. 4086 4087 All vertical values relative to the baseline are given y-down. As such, zero is on the 4088 baseline, negative values are above the baseline, and positive values are below the 4089 baseline. 4090 4091 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values 4092 are valid, since their value may be zero. 4093 4094 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values 4095 are valid, since their value may be zero. 4096 4097 #Enum FontMetricsFlags 4098#Line # valid Font_Metrics ## 4099 4100 #Code 4101 enum FontMetricsFlags { 4102 kUnderlineThicknessIsValid_Flag = 1 << 0, 4103 kUnderlinePositionIsValid_Flag = 1 << 1, 4104 kStrikeoutThicknessIsValid_Flag = 1 << 2, 4105 kStrikeoutPositionIsValid_Flag = 1 << 3, 4106 }; 4107 ## 4108 4109 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid; 4110 the underline or strikeout metric may be valid and zero. 4111 Fonts with embedded bitmaps may not have valid underline or strikeout metrics. 4112 4113 #Const kUnderlineThicknessIsValid_Flag 0x0001 4114 Set if fUnderlineThickness is valid. 4115 ## 4116 #Const kUnderlinePositionIsValid_Flag 0x0002 4117 Set if fUnderlinePosition is valid. 4118 ## 4119 #Const kStrikeoutThicknessIsValid_Flag 0x0004 4120 Set if fStrikeoutThickness is valid. 4121 ## 4122 #Const kStrikeoutPositionIsValid_Flag 0x0008 4123 Set if fStrikeoutPosition is valid. 4124 ## 4125 4126 #Enum ## 4127 4128 #Member uint32_t fFlags 4129 fFlags is set when underline metrics are valid. 4130 ## 4131 4132 #Member SkScalar fTop 4133 Greatest extent above the baseline for any glyph. 4134 Typically less than zero. 4135 ## 4136 4137 #Member SkScalar fAscent 4138 Recommended distance above the baseline to reserve for a line of text. 4139 Typically less than zero. 4140 ## 4141 4142 #Member SkScalar fDescent 4143 Recommended distance below the baseline to reserve for a line of text. 4144 Typically greater than zero. 4145 ## 4146 4147 #Member SkScalar fBottom 4148 Greatest extent below the baseline for any glyph. 4149 Typically greater than zero. 4150 ## 4151 4152 #Member SkScalar fLeading 4153 Recommended distance to add between lines of text. 4154 Typically greater than or equal to zero. 4155 ## 4156 4157 #Member SkScalar fAvgCharWidth 4158 Average character width, if it is available. 4159 Zero if no average width is stored in the font. 4160 ## 4161 4162 #Member SkScalar fMaxCharWidth 4163 Maximum character width. 4164 ## 4165 4166 #Member SkScalar fXMin 4167 Minimum bounding box x value for all Glyphs. 4168 Typically less than zero. 4169 ## 4170 4171 #Member SkScalar fXMax 4172 Maximum bounding box x value for all Glyphs. 4173 Typically greater than zero. 4174 ## 4175 4176 #Member SkScalar fXHeight 4177 Height of a lower-case 'x'. 4178 May be zero if no lower-case height is stored in the font. 4179 ## 4180 4181 #Member SkScalar fCapHeight 4182 Height of an upper-case letter. 4183 May be zero if no upper-case height is stored in the font. 4184 ## 4185 4186 #Member SkScalar fUnderlineThickness 4187 Underline thickness. 4188 4189 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags. 4190 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero. 4191 ## 4192 4193 #Member SkScalar fUnderlinePosition 4194 Position of the top of the underline stroke relative to the baseline. 4195 Typically positive when valid. 4196 4197 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags. 4198 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero. 4199 ## 4200 4201 #Member SkScalar fStrikeoutThickness 4202 Strikeout thickness. 4203 4204 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags. 4205 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero. 4206 ## 4207 4208 #Member SkScalar fStrikeoutPosition 4209 Position of the bottom of the strikeout stroke relative to the baseline. 4210 Typically negative when valid. 4211 4212 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags. 4213 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero. 4214 ## 4215 4216 #Method bool hasUnderlineThickness(SkScalar* thickness) const 4217 4218 If Font_Metrics has a valid underline thickness, return true, and set 4219 thickness to that value. If the underline thickness is not valid, 4220 return false, and ignore thickness. 4221 4222 #Param thickness storage for underline width ## 4223 4224 #Return true if font specifies underline width ## 4225 4226 #NoExample 4227 ## 4228 ## 4229 4230 #Method bool hasUnderlinePosition(SkScalar* position) const 4231 4232 If Font_Metrics has a valid underline position, return true, and set 4233 position to that value. If the underline position is not valid, 4234 return false, and ignore position. 4235 4236 #Param position storage for underline position ## 4237 4238 #Return true if font specifies underline position ## 4239 4240 #NoExample 4241 ## 4242 ## 4243 4244 #Method bool hasStrikeoutThickness(SkScalar* thickness) const 4245 4246 If Font_Metrics has a valid strikeout thickness, return true, and set 4247 thickness to that value. If the underline thickness is not valid, 4248 return false, and ignore thickness. 4249 4250 #Param thickness storage for strikeout width ## 4251 4252 #Return true if font specifies strikeout width ## 4253 4254 #NoExample 4255 ## 4256 ## 4257 4258 #Method bool hasStrikeoutPosition(SkScalar* position) const 4259 4260 If Font_Metrics has a valid strikeout position, return true, and set 4261 position to that value. If the underline position is not valid, 4262 return false, and ignore position. 4263 4264 #Param position storage for strikeout position ## 4265 4266 #Return true if font specifies strikeout position ## 4267 4268 #NoExample 4269 ## 4270 ## 4271 4272#Struct ## 4273 4274#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const 4275 4276#In Font_Metrics 4277#Line # returns Typeface metrics scaled by text size ## 4278 Returns Font_Metrics associated with Typeface. 4279 The return value is the recommended spacing between lines: the sum of metrics 4280 descent, ascent, and leading. 4281 If metrics is not nullptr, Font_Metrics is copied to metrics. 4282 Results are scaled by Text_Size but does not take into account 4283 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold, 4284 Style_Stroke, and Path_Effect. 4285 Results can be additionally scaled by scale; a scale of zero 4286 is ignored. 4287 4288 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ## 4289 #Param scale additional multiplier for returned values ## 4290 4291 #Return recommended spacing between lines ## 4292 4293 #Example 4294 #Height 128 4295 void draw(SkCanvas* canvas) { 4296 SkPaint paint; 4297 paint.setTextSize(32); 4298 SkScalar lineHeight = paint.getFontMetrics(nullptr); 4299 canvas->drawString("line 1", 10, 40, paint); 4300 canvas->drawString("line 2", 10, 40 + lineHeight, paint); 4301 paint.setStyle(SkPaint::kStroke_Style); 4302 paint.setStrokeWidth(10); 4303 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height 4304 canvas->drawString("line 3", 120, 40, paint); 4305 canvas->drawString("line 4", 120, 40 + lineHeight, paint); 4306 } 4307 ## 4308 4309 #SeeAlso Text_Size Typeface Typeface_Methods 4310 4311## 4312 4313 4314#Method SkScalar getFontSpacing() const 4315 4316#In Font_Metrics 4317#Line # returns recommended spacing between lines ## 4318 Returns the recommended spacing between lines: the sum of metrics 4319 descent, ascent, and leading. 4320 Result is scaled by Text_Size but does not take into account 4321 dimensions required by stroking and Path_Effect. 4322 Returns the same result as getFontMetrics. 4323 4324 #Return recommended spacing between lines ## 4325 4326 #Example 4327 SkPaint paint; 4328 for (SkScalar textSize : { 12, 18, 24, 32 } ) { 4329 paint.setTextSize(textSize); 4330 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing()); 4331 } 4332 4333 #StdOut 4334 textSize: 12 fontSpacing: 13.9688 4335 textSize: 18 fontSpacing: 20.9531 4336 textSize: 24 fontSpacing: 27.9375 4337 textSize: 32 fontSpacing: 37.25 4338 ## 4339 ## 4340 4341## 4342 4343 4344#Method SkRect getFontBounds() const 4345 4346#In Font_Metrics 4347#Line # returns union all glyph bounds ## 4348Returns the union of bounds of all Glyphs. 4349Returned dimensions are computed by Font_Manager from font data, 4350ignoring Hinting. Includes Text_Size, Text_Scale_X, 4351and Text_Skew_X, but not Fake_Bold or Path_Effect. 4352 4353If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero, 4354returns the same bounds as Font_Metrics { FontMetrics::fXMin, 4355FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }. 4356 4357#Return union of bounds of all Glyphs ## 4358 4359#Example 4360 SkPaint paint; 4361 SkPaint::FontMetrics fm; 4362 paint.getFontMetrics(&fm); 4363 SkRect fb = paint.getFontBounds(); 4364 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom ); 4365 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom ); 4366 4367 #StdOut 4368 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 } 4369 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 } 4370 ## 4371## 4372 4373## 4374 4375#Subtopic Font_Metrics ## 4376# ------------------------------------------------------------------------------ 4377 4378#Method int textToGlyphs(const void* text, size_t byteLength, 4379 SkGlyphID glyphs[]) const 4380#In Utility 4381#Line # converts text into glyph indices ## 4382 4383Converts text into glyph indices. 4384Returns the number of glyph indices represented by text. 4385Text_Encoding specifies how text represents characters or glyphs. 4386glyphs may be nullptr, to compute the glyph count. 4387 4388Does not check text for valid character codes or valid glyph indices. 4389 4390If byteLength equals zero, returns zero. 4391If byteLength includes a partial character, the partial character is ignored. 4392 4393If Text_Encoding is kUTF8_TextEncoding and 4394text contains an invalid UTF-8 sequence, zero is returned. 4395 4396#Param text character storage encoded with Text_Encoding ## 4397#Param byteLength length of character storage in bytes ## 4398#Param glyphs storage for glyph indices; may be nullptr ## 4399 4400#Return number of glyphs represented by text of length byteLength ## 4401 4402 #Example 4403 #Height 64 4404 void draw(SkCanvas* canvas) { 4405 SkPaint paint; 4406 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 }; 4407 std::vector<SkGlyphID> glyphs; 4408 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr); 4409 glyphs.resize(count); 4410 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front()); 4411 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 4412 paint.setTextSize(32); 4413 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint); 4414 } 4415 ## 4416 4417## 4418 4419#Method int countText(const void* text, size_t byteLength) const 4420#In Utility 4421#Line # returns number of Glyphs in text ## 4422 Returns the number of Glyphs in text. 4423 Uses Text_Encoding to count the Glyphs. 4424 Returns the same result as textToGlyphs. 4425 4426#Param text character storage encoded with Text_Encoding ## 4427#Param byteLength length of character storage in bytes ## 4428 4429#Return number of Glyphs represented by text of length byteLength ## 4430 4431 #Example 4432 SkPaint paint; 4433 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 }; 4434 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8))); 4435 4436 #StdOut 4437 count = 5 4438 ## 4439 ## 4440## 4441 4442# ------------------------------------------------------------------------------ 4443 4444#Method bool containsText(const void* text, size_t byteLength) const 4445#In Utility 4446#Line # returns if all text corresponds to Glyphs ## 4447 Returns true if all text corresponds to a non-zero glyph index. 4448 Returns false if any characters in text are not supported in 4449 Typeface. 4450 4451 If Text_Encoding is kGlyphID_TextEncoding, 4452 returns true if all glyph indices in text are non-zero; 4453 does not check to see if text contains valid glyph indices for Typeface. 4454 4455 Returns true if byteLength is zero. 4456 4457 #Param text array of characters or Glyphs ## 4458 #Param byteLength number of bytes in text array ## 4459 4460 #Return true if all text corresponds to a non-zero glyph index ## 4461 4462 #Example 4463 #Description 4464 containsText succeeds for degree symbol, but cannot find a glyph index 4465 corresponding to the Unicode surrogate code point. 4466 ## 4467 SkPaint paint; 4468 const uint16_t goodChar = 0x00B0; // degree symbol 4469 const uint16_t badChar = 0xD800; // Unicode surrogate 4470 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 4471 SkDebugf("0x%04x %c= has char\n", goodChar, 4472 paint.containsText(&goodChar, 2) ? '=' : '!'); 4473 SkDebugf("0x%04x %c= has char\n", badChar, 4474 paint.containsText(&badChar, 2) ? '=' : '!'); 4475 4476 #StdOut 4477 0x00b0 == has char 4478 0xd800 != has char 4479 ## 4480 ## 4481 4482 #Example 4483 #Description 4484 containsText returns true that glyph index is greater than zero, not 4485 that it corresponds to an entry in Typeface. 4486 ## 4487 SkPaint paint; 4488 const uint16_t goodGlyph = 511; 4489 const uint16_t zeroGlyph = 0; 4490 const uint16_t badGlyph = 65535; // larger than glyph count in font 4491 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 4492 SkDebugf("0x%04x %c= has glyph\n", goodGlyph, 4493 paint.containsText(&goodGlyph, 2) ? '=' : '!'); 4494 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph, 4495 paint.containsText(&zeroGlyph, 2) ? '=' : '!'); 4496 SkDebugf("0x%04x %c= has glyph\n", badGlyph, 4497 paint.containsText(&badGlyph, 2) ? '=' : '!'); 4498 4499 #StdOut 4500 0x01ff == has glyph 4501 0x0000 != has glyph 4502 0xffff == has glyph 4503 ## 4504 ## 4505 4506#SeeAlso setTextEncoding Typeface 4507 4508## 4509 4510# ------------------------------------------------------------------------------ 4511 4512#Method void glyphsToUnichars(const SkGlyphID glyphs[], 4513 int count, SkUnichar text[]) const 4514#In Utility 4515#Line # converts Glyphs into text ## 4516 4517 Converts glyphs into text if possible. 4518 Glyph values without direct Unicode equivalents are mapped to zero. 4519 Uses the Typeface, but is unaffected 4520 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding. 4521 4522 Only supported on platforms that use FreeType as the Font_Engine. 4523 4524 #Param glyphs array of indices into font ## 4525 #Param count length of glyph array ## 4526 #Param text storage for character codes, one per glyph ## 4527 4528 #Example 4529 #Height 64 4530 #Description 4531 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points. 4532 ## 4533 void draw(SkCanvas* canvas) { 4534 SkPaint paint; 4535 const char hello[] = "Hello!"; 4536 const int count = sizeof(hello) - 1; 4537 SkGlyphID glyphs[count]; 4538 if (count != paint.textToGlyphs(hello, count, glyphs)) { 4539 return; 4540 } 4541 SkUnichar unichars[count]; 4542 paint.glyphsToUnichars(glyphs, count, unichars); 4543 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 4544 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint); 4545 } 4546 ## 4547 4548## 4549 4550# ------------------------------------------------------------------------------ 4551#Subtopic Measure_Text 4552#Line # width, height, bounds of text ## 4553 4554#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const 4555 4556#In Measure_Text 4557#Line # returns advance width and bounds of text ## 4558 Returns the advance width of text if kVerticalText_Flag is clear, 4559 and the height of text if kVerticalText_Flag is set. 4560 The advance is the normal distance to move before drawing additional text. 4561 Uses Text_Encoding to decode text, Typeface to get the font metrics, 4562 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and 4563 Path_Effect to scale the metrics and bounds. 4564 Returns the bounding box of text if bounds is not nullptr. 4565 The bounding box is computed as if the text was drawn at the origin. 4566 4567 #Param text character codes or glyph indices to be measured ## 4568 #Param length number of bytes of text to measure ## 4569 #Param bounds returns bounding box relative to (0, 0) if not nullptr ## 4570 4571 #Return advance width or height ## 4572 4573 #Example 4574 #Height 64 4575 void draw(SkCanvas* canvas) { 4576 SkPaint paint; 4577 paint.setAntiAlias(true); 4578 paint.setTextSize(50); 4579 const char str[] = "ay^jZ"; 4580 const int count = sizeof(str) - 1; 4581 canvas->drawText(str, count, 25, 50, paint); 4582 SkRect bounds; 4583 paint.measureText(str, count, &bounds); 4584 canvas->translate(25, 50); 4585 paint.setStyle(SkPaint::kStroke_Style); 4586 canvas->drawRect(bounds, paint); 4587 } 4588 ## 4589 4590## 4591 4592#Method SkScalar measureText(const void* text, size_t length) const 4593 4594#In Measure_Text 4595 Returns the advance width of text if kVerticalText_Flag is clear, 4596 and the height of text if kVerticalText_Flag is set. 4597 The advance is the normal distance to move before drawing additional text. 4598 Uses Text_Encoding to decode text, Typeface to get the font metrics, 4599 and Text_Size to scale the metrics. 4600 Does not scale the advance or bounds by Fake_Bold or Path_Effect. 4601 4602 #Param text character codes or glyph indices to be measured ## 4603 #Param length number of bytes of text to measure ## 4604 4605 #Return advance width or height ## 4606 4607 #Example 4608 SkPaint paint; 4609 SkDebugf("default width = %g\n", paint.measureText("!", 1)); 4610 paint.setTextSize(paint.getTextSize() * 2); 4611 SkDebugf("double width = %g\n", paint.measureText("!", 1)); 4612 4613 #StdOut 4614 default width = 5 4615 double width = 10 4616 ## 4617 ## 4618 4619## 4620 4621#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth, 4622 SkScalar* measuredWidth = nullptr) const 4623#In Measure_Text 4624#Line # returns text that fits in a width ## 4625 4626 Returns the bytes of text that fit within maxWidth. 4627 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or 4628 equal to maxWidth. 4629 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or 4630 equal to maxWidth. 4631 Measures only while the advance is less than or equal to maxWidth. 4632 Returns the advance or the text fragment in measuredWidth if it not nullptr. 4633 Uses Text_Encoding to decode text, Typeface to get the font metrics, 4634 and Text_Size to scale the metrics. 4635 Does not scale the advance or bounds by Fake_Bold or Path_Effect. 4636 4637 #Param text character codes or glyph indices to be measured ## 4638 #Param length number of bytes of text to measure ## 4639 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ## 4640 #Param measuredWidth returns the width of the text less than or equal to maxWidth ## 4641 #Return bytes of text that fit, always less than or equal to length ## 4642 4643 #Example 4644 #Description 4645 Line under "Breakfast" shows desired width, shorter than available characters. 4646 Line under "Bre" shows measured width after breaking text. 4647 ## 4648 #Height 128 4649 #Width 280 4650 void draw(SkCanvas* canvas) { 4651 SkPaint paint; 4652 paint.setAntiAlias(true); 4653 paint.setTextSize(50); 4654 const char str[] = "Breakfast"; 4655 const int count = sizeof(str) - 1; 4656 canvas->drawText(str, count, 25, 50, paint); 4657 SkScalar measuredWidth; 4658 int partialBytes = paint.breakText(str, count, 100, &measuredWidth); 4659 canvas->drawText(str, partialBytes, 25, 100, paint); 4660 canvas->drawLine(25, 60, 25 + 100, 60, paint); 4661 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint); 4662 } 4663 ## 4664 4665## 4666 4667#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[], 4668 SkRect bounds[] = nullptr) const 4669#In Measure_Text 4670#Line # returns advance and bounds for each glyph in text ## 4671 4672 Retrieves the advance and bounds for each glyph in text, and returns 4673 the glyph count in text. 4674 Both widths and bounds may be nullptr. 4675 If widths is not nullptr, widths must be an array of glyph count entries. 4676 if bounds is not nullptr, bounds must be an array of glyph count entries. 4677 If kVerticalText_Flag is clear, widths returns the horizontal advance. 4678 If kVerticalText_Flag is set, widths returns the vertical advance. 4679 Uses Text_Encoding to decode text, Typeface to get the font metrics, 4680 and Text_Size to scale the widths and bounds. 4681 Does not scale the advance by Fake_Bold or Path_Effect. 4682 Does include Fake_Bold and Path_Effect in the bounds. 4683 4684 #Param text character codes or glyph indices to be measured ## 4685 #Param byteLength number of bytes of text to measure ## 4686 #Param widths returns text advances for each glyph; may be nullptr ## 4687 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ## 4688 4689 #Return glyph count in text ## 4690 4691 #Example 4692 #Height 160 4693 #Description 4694 Bounds of Glyphs increase for stroked text, but text advance remains the same. 4695 The underlines show the text advance, spaced to keep them distinct. 4696 ## 4697 void draw(SkCanvas* canvas) { 4698 SkPaint paint; 4699 paint.setAntiAlias(true); 4700 paint.setTextSize(50); 4701 const char str[] = "abc"; 4702 const int bytes = sizeof(str) - 1; 4703 int count = paint.getTextWidths(str, bytes, nullptr); 4704 std::vector<SkScalar> widths; 4705 std::vector<SkRect> bounds; 4706 widths.resize(count); 4707 bounds.resize(count); 4708 for (int loop = 0; loop < 2; ++loop) { 4709 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front()); 4710 SkPoint loc = { 25, 50 }; 4711 canvas->drawText(str, bytes, loc.fX, loc.fY, paint); 4712 paint.setStyle(SkPaint::kStroke_Style); 4713 paint.setStrokeWidth(0); 4714 SkScalar advanceY = loc.fY + 10; 4715 for (int index = 0; index < count; ++index) { 4716 bounds[index].offset(loc.fX, loc.fY); 4717 canvas->drawRect(bounds[index], paint); 4718 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint); 4719 loc.fX += widths[index]; 4720 advanceY += 5; 4721 } 4722 canvas->translate(0, 80); 4723 paint.setStrokeWidth(3); 4724 } 4725 } 4726 ## 4727 4728## 4729 4730#Subtopic Measure_Text ## 4731# ------------------------------------------------------------------------------ 4732#Subtopic Text_Path 4733#Line # geometry of Glyphs ## 4734 4735Text_Path describes the geometry of Glyphs used to draw text. 4736 4737#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y, 4738 SkPath* path) const 4739#In Text_Path 4740#Line # returns Path equivalent to text ## 4741 4742Returns the geometry as Path equivalent to the drawn text. 4743Uses Text_Encoding to decode text, Typeface to get the glyph paths, 4744and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths. 4745All of the glyph paths are stored in path. 4746Uses x, y, and Text_Align to position path. 4747 4748 #Param text character codes or glyph indices ## 4749 #Param length number of bytes of text ## 4750 #Param x x-coordinate of the origin of the text ## 4751 #Param y y-coordinate of the origin of the text ## 4752 #Param path geometry of the Glyphs ## 4753 4754 #Example 4755 #Description 4756 Text is added to Path, offset, and subtracted from Path, then added at 4757 the offset location. The result is rendered with one draw call. 4758 ## 4759 #Height 128 4760 void draw(SkCanvas* canvas) { 4761 SkPaint paint; 4762 paint.setTextSize(80); 4763 SkPath path, path2; 4764 paint.getTextPath("ABC", 3, 20, 80, &path); 4765 path.offset(20, 20, &path2); 4766 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path); 4767 path.addPath(path2); 4768 paint.setStyle(SkPaint::kStroke_Style); 4769 canvas->drawPath(path, paint); 4770 } 4771 ## 4772 4773## 4774 4775#Method void getPosTextPath(const void* text, size_t length, 4776 const SkPoint pos[], SkPath* path) const 4777#In Text_Path 4778#Line # returns Path equivalent to positioned text ## 4779 4780Returns the geometry as Path equivalent to the drawn text. 4781Uses Text_Encoding to decode text, Typeface to get the glyph paths, 4782and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths. 4783All of the glyph paths are stored in path. 4784Uses pos array and Text_Align to position path. 4785pos contains a position for each glyph. 4786 4787 #Param text character codes or glyph indices ## 4788 #Param length number of bytes of text ## 4789 #Param pos positions of each glyph ## 4790 #Param path geometry of the Glyphs ## 4791 4792 #Example 4793 #Height 85 4794 #Description 4795 Simplifies three Glyphs to eliminate overlaps, and strokes the result. 4796 ## 4797 void draw(SkCanvas* canvas) { 4798 SkPaint paint; 4799 paint.setTextSize(80); 4800 SkPath path, path2; 4801 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}}; 4802 paint.getPosTextPath("ABC", 3, pos, &path); 4803 Simplify(path, &path); 4804 paint.setStyle(SkPaint::kStroke_Style); 4805 canvas->drawPath(path, paint); 4806 } 4807 ## 4808 4809## 4810 4811#Subtopic Text_Path ## 4812# ------------------------------------------------------------------------------ 4813#Subtopic Text_Intercepts 4814#Line # advanced underline, strike through ## 4815 4816Text_Intercepts describe the intersection of drawn text Glyphs with a pair 4817of lines parallel to the text advance. Text_Intercepts permits creating a 4818underline that skips Descenders. 4819 4820#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y, 4821 const SkScalar bounds[2], SkScalar* intervals) const 4822#In Text_Intercepts 4823#Line # returns where lines intersect text; underlines ## 4824 4825 Returns the number of intervals that intersect bounds. 4826 bounds describes a pair of lines parallel to the text advance. 4827 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in 4828 the string. 4829 Uses Text_Encoding to decode text, Typeface to get the glyph paths, 4830 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths. 4831 Uses x, y, and Text_Align to position intervals. 4832 4833 Pass nullptr for intervals to determine the size of the interval array. 4834 4835 intervals are cached to improve performance for multiple calls. 4836 4837 #Param text character codes or glyph indices ## 4838 #Param length number of bytes of text ## 4839 #Param x x-coordinate of the origin of the text ## 4840 #Param y y-coordinate of the origin of the text ## 4841 #Param bounds lower and upper line parallel to the advance ## 4842 #Param intervals returned intersections; may be nullptr ## 4843 4844 #Return number of intersections; may be zero ## 4845 4846#Example 4847#Height 128 4848#Description 4849Underline uses intercepts to draw on either side of the glyph Descender. 4850## 4851void draw(SkCanvas* canvas) { 4852 SkPaint paint; 4853 paint.setTextSize(120); 4854 SkPoint textOrigin = { 20, 100 }; 4855 SkScalar bounds[] = { 100, 108 }; 4856 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr); 4857 std::vector<SkScalar> intervals; 4858 intervals.resize(count); 4859 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, 4860 &intervals.front()); 4861 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint); 4862 paint.setColor(SK_ColorRED); 4863 SkScalar x = textOrigin.fX; 4864 for (int i = 0; i < count; i += 2) { 4865 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint); 4866 x = intervals[i + 1]; 4867 } 4868 canvas->drawRect({intervals[count - 1], bounds[0], 4869 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint); 4870} 4871## 4872 4873## 4874 4875#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[], 4876 const SkScalar bounds[2], SkScalar* intervals) const 4877#In Text_Intercepts 4878#Line # returns where lines intersect positioned text; underlines ## 4879 4880 Returns the number of intervals that intersect bounds. 4881 bounds describes a pair of lines parallel to the text advance. 4882 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in 4883 the string. 4884 Uses Text_Encoding to decode text, Typeface to get the glyph paths, 4885 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths. 4886 Uses pos array and Text_Align to position intervals. 4887 4888 Pass nullptr for intervals to determine the size of the interval array. 4889 4890 intervals are cached to improve performance for multiple calls. 4891 4892 #Param text character codes or glyph indices ## 4893 #Param length number of bytes of text ## 4894 #Param pos positions of each glyph ## 4895 #Param bounds lower and upper line parallel to the advance ## 4896 #Param intervals returned intersections; may be nullptr ## 4897 4898 #Return number of intersections; may be zero ## 4899 4900 #Example 4901 #Description 4902 Text intercepts draw on either side of, but not inside, Glyphs in a run. 4903 ## 4904 void draw(SkCanvas* canvas) { 4905 SkPaint paint; 4906 paint.setTextSize(120); 4907 paint.setVerticalText(true); 4908 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }}; 4909 SkScalar bounds[] = { 56, 64 }; 4910 const char str[] = "A-"; 4911 int len = sizeof(str) - 1; 4912 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr); 4913 std::vector<SkScalar> intervals; 4914 intervals.resize(count); 4915 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front()); 4916 canvas->drawPosText(str, len, textPos, paint); 4917 paint.setColor(SK_ColorRED); 4918 SkScalar y = textPos[0].fY; 4919 for (int i = 0; i < count; i+= 2) { 4920 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint); 4921 y = intervals[i + 1]; 4922 } 4923 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint); 4924 } 4925 ## 4926 4927## 4928 4929#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[], 4930 SkScalar constY, const SkScalar bounds[2], 4931 SkScalar* intervals) const 4932#In Text_Intercepts 4933#Line # returns where lines intersect horizontally positioned text; underlines ## 4934 4935 Returns the number of intervals that intersect bounds. 4936 bounds describes a pair of lines parallel to the text advance. 4937 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in 4938 the string. 4939 Uses Text_Encoding to decode text, Typeface to get the glyph paths, 4940 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths. 4941 Uses xpos array, constY, and Text_Align to position intervals. 4942 4943 Pass nullptr for intervals to determine the size of the interval array. 4944 4945 intervals are cached to improve performance for multiple calls. 4946 4947 #Param text character codes or glyph indices ## 4948 #Param length number of bytes of text ## 4949 #Param xpos positions of each glyph in x ## 4950 #Param constY position of each glyph in y ## 4951 #Param bounds lower and upper line parallel to the advance ## 4952 #Param intervals returned intersections; may be nullptr ## 4953 4954 #Return number of intersections; may be zero ## 4955 4956 #Example 4957 #Height 128 4958 #Description 4959 Text intercepts do not take stroke thickness into consideration. 4960 ## 4961 void draw(SkCanvas* canvas) { 4962 SkPaint paint; 4963 paint.setTextSize(120); 4964 paint.setStyle(SkPaint::kStroke_Style); 4965 paint.setStrokeWidth(4); 4966 SkScalar textPosH[] = { 20, 80, 140 }; 4967 SkScalar y = 100; 4968 SkScalar bounds[] = { 56, 78 }; 4969 const char str[] = "\\-/"; 4970 int len = sizeof(str) - 1; 4971 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr); 4972 std::vector<SkScalar> intervals; 4973 intervals.resize(count); 4974 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front()); 4975 canvas->drawPosTextH(str, len, textPosH, y, paint); 4976 paint.setColor(0xFFFF7777); 4977 paint.setStyle(SkPaint::kFill_Style); 4978 SkScalar x = textPosH[0]; 4979 for (int i = 0; i < count; i+= 2) { 4980 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint); 4981 x = intervals[i + 1]; 4982 } 4983 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint); 4984 } 4985 ## 4986 4987## 4988 4989 4990#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2], 4991 SkScalar* intervals) const 4992#In Text_Intercepts 4993#Line # returns where lines intersect Text_Blob; underlines ## 4994 4995 Returns the number of intervals that intersect bounds. 4996 bounds describes a pair of lines parallel to the text advance. 4997 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in 4998 the string. 4999 Uses Typeface to get the glyph paths, 5000 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths. 5001 Uses run array and Text_Align to position intervals. 5002 5003 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding. 5004 5005 Pass nullptr for intervals to determine the size of the interval array. 5006 5007 intervals are cached to improve performance for multiple calls. 5008 5009 #Param blob Glyphs, positions, and text paint attributes ## 5010 #Param bounds lower and upper line parallel to the advance ## 5011 #Param intervals returned intersections; may be nullptr ## 5012 5013 #Return number of intersections; may be zero ## 5014 5015 #Example 5016 #Height 143 5017 void draw(SkCanvas* canvas) { 5018 SkPaint paint; 5019 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 5020 paint.setTextSize(120); 5021 SkPoint textPos = { 20, 110 }; 5022 int len = 3; 5023 SkTextBlobBuilder textBlobBuilder; 5024 const SkTextBlobBuilder::RunBuffer& run = 5025 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY); 5026 run.glyphs[0] = 10; 5027 run.glyphs[1] = 20; 5028 run.glyphs[2] = 30; 5029 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 5030 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint); 5031 SkScalar bounds[] = { 116, 134 }; 5032 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr); 5033 std::vector<SkScalar> intervals; 5034 intervals.resize(count); 5035 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front()); 5036 canvas->drawTextBlob(blob.get(), 0, 0, paint); 5037 paint.setColor(0xFFFF7777); 5038 SkScalar x = textPos.fX; 5039 for (int i = 0; i < count; i+= 2) { 5040 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint); 5041 x = intervals[i + 1]; 5042 } 5043 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint); 5044 } 5045 ## 5046 5047## 5048 5049#Subtopic Text_Intercepts ## 5050# ------------------------------------------------------------------------------ 5051 5052#Method bool nothingToDraw() const 5053#In Utility 5054#Line # returns true if Paint prevents all drawing ## 5055 Returns true if Paint prevents all drawing; 5056 otherwise, the Paint may or may not allow drawing. 5057 5058 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a 5059 new Alpha of zero. 5060 5061 #Return true if Paint prevents all drawing ## 5062 5063 #Example 5064 void draw(SkCanvas* canvas) { 5065 auto debugster = [](const char* prefix, const SkPaint& p) -> void { 5066 SkDebugf("%s nothing to draw: %s\n", prefix, 5067 p.nothingToDraw() ? "true" : "false"); 5068 }; 5069 SkPaint paint; 5070 debugster("initial", paint); 5071 paint.setBlendMode(SkBlendMode::kDst); 5072 debugster("blend dst", paint); 5073 paint.setBlendMode(SkBlendMode::kSrcOver); 5074 debugster("blend src over", paint); 5075 paint.setAlpha(0); 5076 debugster("alpha 0", paint); 5077 } 5078 5079 #StdOut 5080 initial nothing to draw: false 5081 blend dst nothing to draw: true 5082 blend src over nothing to draw: false 5083 alpha 0 nothing to draw: true 5084 #StdOut ## 5085 ## 5086 5087## 5088 5089# ------------------------------------------------------------------------------ 5090#Subtopic Fast_Bounds 5091#Line # approximate area required by Paint ## 5092 #Private 5093 To be made private. 5094 ## 5095 5096Fast_Bounds methods conservatively outset a drawing bounds by additional area 5097Paint may draw to. 5098 5099#Method bool canComputeFastBounds() const 5100 5101#In Fast_Bounds 5102#Line # returns true if settings allow for fast bounds computation ###Private 5103 (to be made private) 5104 ## 5105 5106 Returns true if Paint does not include elements requiring extensive computation 5107 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect 5108 always returns false. 5109 5110 #Return true if Paint allows for fast computation of bounds ## 5111## 5112 5113#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const 5114 5115#In Fast_Bounds 5116#Line # returns fill bounds for quick reject tests ###Private 5117 (to be made private) 5118 ## 5119 5120 Only call this if canComputeFastBounds returned true. This takes a 5121 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic 5122 effects in the paint (e.g. stroking). If needed, it uses the storage 5123 parameter. It returns the adjusted bounds that can then be used 5124 for SkCanvas::quickReject tests. 5125 5126 The returned Rect will either be orig or storage, thus the caller 5127 should not rely on storage being set to the result, but should always 5128 use the returned value. It is legal for orig and storage to be the same 5129 Rect. 5130 5131 #Private 5132 e.g. 5133 if (paint.canComputeFastBounds()) { 5134 SkRect r, storage; 5135 path.computeBounds(&r, SkPath::kFast_BoundsType); 5136 const SkRect& fastR = paint.computeFastBounds(r, &storage); 5137 if (canvas->quickReject(fastR, ...)) { 5138 // don't draw the path 5139 } 5140 } 5141 ## 5142 5143 #Param orig geometry modified by Paint when drawn ## 5144 #Param storage computed bounds of geometry; may not be nullptr ## 5145 5146 #Return fast computed bounds ## 5147## 5148 5149#Method const SkRect& computeFastStrokeBounds(const SkRect& orig, 5150 SkRect* storage) const 5151#In Fast_Bounds 5152#Line # returns stroke bounds for quick reject tests ## 5153 #Private 5154 (to be made private) 5155 ## 5156 5157 #Param orig geometry modified by Paint when drawn ## 5158 #Param storage computed bounds of geometry ## 5159 5160 #Return fast computed bounds ## 5161## 5162 5163#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage, 5164 Style style) const 5165#In Fast_Bounds 5166#Line # returns bounds for quick reject tests ## 5167 #Private 5168 (to be made private) 5169 ## 5170 5171 Computes the bounds, overriding the Paint Style. This can be used to 5172 account for additional width required by stroking orig, without 5173 altering Style set to fill. 5174 5175 #Param orig geometry modified by Paint when drawn ## 5176 #Param storage computed bounds of geometry ## 5177 #Param style overrides Style ## 5178 5179 #Return fast computed bounds ## 5180## 5181 5182#Subtopic Fast_Bounds Fast_Bounds ## 5183 5184# ------------------------------------------------------------------------------ 5185#Subtopic Utility 5186#Populate 5187#Line # rarely called management functions ## 5188## 5189 5190#Method void toString(SkString* str) const 5191#In Utility 5192#Line # converts Paint to machine readable form ## 5193#DefinedBy SK_TO_STRING_NONVIRT() ## 5194 5195#Private 5196macro expands to: void toString(SkString* str) const; 5197## 5198 5199Creates string representation of Paint. The representation is read by 5200internal debugging tools. The interface and implementation may be 5201suppressed by defining SK_IGNORE_TO_STRING. 5202 5203#Param str storage for string representation of Paint ## 5204 5205#Example 5206 SkPaint paint; 5207 SkString str; 5208 paint.toString(&str); 5209 const char textSize[] = "TextSize:"; 5210 const int trailerSize = strlen("</dd><dt>"); 5211 int textSizeLoc = str.find(textSize) + strlen(textSize) + trailerSize; 5212 const char* sizeStart = &str.c_str()[textSizeLoc]; 5213 int textSizeEnd = SkStrFind(sizeStart, "</dd>"); 5214 SkDebugf("text size = %.*s\n", textSizeEnd, sizeStart); 5215 5216 #StdOut 5217 text size = 12 5218 ## 5219 5220## 5221 5222#SeeAlso SkPathEffect::toString SkMaskFilter::toString SkColorFilter::toString SkImageFilter::toString 5223 5224## 5225 5226# ------------------------------------------------------------------------------ 5227 5228#Class SkPaint ## 5229 5230#Topic Paint ## 5231 5232