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