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