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