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