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