blob: 8316c9e17e6c36c979ac45a51f29a10ef78cee9e [file] [log] [blame]
Cary Clark0c5f5462017-12-15 11:21:51 -05001#Topic Paint
Cary Clark137b8742018-05-30 09:21:49 -04002#Alias Paint_Reference ##
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clark61313f32018-10-08 14:57:48 -04004#PhraseDef paint_font_metrics
5Typeface, Paint_Text_Size, Paint_Text_Scale_X,
6Paint_Text_Skew_X, Paint_Text_Align, Paint_Hinting, Anti_Alias, Paint_Fake_Bold,
7Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
8and Subpixel_Text
9##
10
Cary Clarke4aa3712017-09-15 02:56:12 -040011#Class SkPaint
12
Cary Clark61313f32018-10-08 14:57:48 -040013#Code
14#Populate
15##
16
Cary Clark8032b982017-07-28 11:04:54 -040017Paint controls options applied when drawing and measuring. Paint collects all
18options outside of the Canvas_Clip and Canvas_Matrix.
19
Herb Derbyfcac00f2018-05-01 11:57:56 -040020Various options apply to text, strokes and fills, and images.
Cary Clark8032b982017-07-28 11:04:54 -040021
22Some options may not be implemented on all platforms; in these cases, setting
23the option has no effect. Some options are conveniences that duplicate Canvas
24functionality; for instance, text size is identical to matrix scale.
25
26Paint options are rarely exclusive; each option modifies a stage of the drawing
27pipeline and multiple pipeline stages may be affected by a single Paint.
28
Herb Derbyfcac00f2018-05-01 11:57:56 -040029Paint collects effects and filters that describe single-pass and multiple-pass
Cary Clark8032b982017-07-28 11:04:54 -040030algorithms that alter the drawing geometry, color, and transparency. For instance,
Herb Derbyfcac00f2018-05-01 11:57:56 -040031Paint does not directly implement dashing or blur, but contains the objects that do so.
Cary Clark8032b982017-07-28 11:04:54 -040032
33The objects contained by Paint are opaque, and cannot be edited outside of the Paint
34to affect it. The implementation is free to defer computations associated with the
35Paint, or ignore them altogether. For instance, some GPU implementations draw all
Cary Clarkffb3d682018-05-17 12:17:28 -040036Path geometries with Anti_Aliasing, regardless of how SkPaint::kAntiAlias_Flag
Cary Clarkbad5ad72017-08-03 17:14:08 -040037is set in Paint.
Cary Clark8032b982017-07-28 11:04:54 -040038
39Paint describes a single color, a single font, a single image quality, and so on.
40Multiple colors are drawn either by using multiple paints or with objects like
41Shader attached to Paint.
42
Cary Clark8032b982017-07-28 11:04:54 -040043#Method SkPaint()
Cary Clarkab2621d2018-01-30 10:08:57 -050044#Line # constructs with default values ##
Cary Clark8032b982017-07-28 11:04:54 -040045Constructs Paint with default values.
46
47#Table
48#Legend
49# attribute # default value ##
50#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -040051# Anti_Alias # false ##
Cary Clarkce101242017-09-01 15:51:02 -040052# Blend_Mode # SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -040053# Color # SK_ColorBLACK ##
54# Color_Alpha # 255 ##
55# Color_Filter # nullptr ##
56# Dither # false ##
57# Draw_Looper # nullptr ##
58# Fake_Bold # false ##
59# Filter_Quality # kNone_SkFilterQuality ##
60# Font_Embedded_Bitmaps # false ##
61# Automatic_Hinting # false ##
62# Full_Hinting_Spacing # false ##
63# Hinting # kNormal_Hinting ##
64# Image_Filter # nullptr ##
65# LCD_Text # false ##
66# Linear_Text # false ##
67# Miter_Limit # 4 ##
68# Mask_Filter # nullptr ##
69# Path_Effect # nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -040070# Shader # nullptr ##
71# Style # kFill_Style ##
72# Text_Align # kLeft_Align ##
73# Text_Encoding # kUTF8_TextEncoding ##
74# Text_Scale_X # 1 ##
75# Text_Size # 12 ##
76# Text_Skew_X # 0 ##
77# Typeface # nullptr ##
78# Stroke_Cap # kButt_Cap ##
79# Stroke_Join # kMiter_Join ##
80# Stroke_Width # 0 ##
81# Subpixel_Text # false ##
82# Vertical_Text # false ##
83#Table ##
84
85The flags, text size, hinting, and miter limit may be overridden at compile time by defining
Herb Derbyfcac00f2018-05-01 11:57:56 -040086paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
Cary Clark8032b982017-07-28 11:04:54 -040087build system.
88
89#Return default initialized Paint ##
90
91#Example
92#ToDo mark this as no output ##
93#Height 1
94###$ $ redefine markup character so preprocessor commands appear normally
95#ifndef SkUserConfig_DEFINED
96#define SkUserConfig_DEFINED
97
98#define SkPaintDefaults_Flags 0x01 // always enable antialiasing
99#define SkPaintDefaults_TextSize 24.f // double default font size
100#define SkPaintDefaults_Hinting 3 // use full hinting
101#define SkPaintDefaults_MiterLimit 10.f // use HTML Canvas miter limit setting
102
103#endif
104$$$# # restore original markup character
105##
106
107
108##
109
110#Method SkPaint(const SkPaint& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500111#Line # makes a shallow copy ##
Cary Clark8032b982017-07-28 11:04:54 -0400112Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500113Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400114between the original paint and the copy. Objects containing Reference_Count increment
115their references by one.
Cary Clark8032b982017-07-28 11:04:54 -0400116
Mike Reed8ad91a92018-01-19 19:09:32 -0500117The referenced objects Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400118Draw_Looper, and Image_Filter cannot be modified after they are created.
119This prevents objects with Reference_Count from being modified once Paint refers to them.
120
121#Param paint original to copy ##
122
123#Return shallow copy of paint ##
124
125#Example
126#ToDo why is this double-spaced on Fiddle? ##
127 SkPaint paint1;
128 paint1.setColor(SK_ColorRED);
129 SkPaint paint2(paint1);
130 paint2.setColor(SK_ColorBLUE);
131 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
132 SkDebugf("SK_ColorBLUE %c= paint2.getColor()\n", SK_ColorBLUE == paint2.getColor() ? '=' : '!');
133
134 #StdOut
135 SK_ColorRED == paint1.getColor()
136 SK_ColorBLUE == paint2.getColor()
137 ##
138##
139
140##
141
142#Method SkPaint(SkPaint&& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500143#Line # moves paint without copying it ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400144 Implements a move constructor to avoid increasing the reference counts
Cary Clark8032b982017-07-28 11:04:54 -0400145 of objects referenced by the paint.
146
147 After the call, paint is undefined, and can be safely destructed.
148
149 #Param paint original to move ##
150
151 #Return content of paint ##
152
153 #Example
154 SkPaint paint;
155 float intervals[] = { 5, 5 };
156 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 2.5f));
157 SkPaint dashed(std::move(paint));
158 SkDebugf("path effect unique: %s\n", dashed.getPathEffect()->unique() ? "true" : "false");
159
160 #StdOut
161 path effect unique: true
162 ##
163 ##
164
165##
166
167# ------------------------------------------------------------------------------
168
169#Method void reset()
Cary Clarka90ea222018-10-16 10:30:28 -0400170#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -0500171#Line # sets to default values ##
Cary Clarkbc5697d2017-10-04 14:31:33 -0400172Sets all Paint contents to their initial values. This is equivalent to replacing
173Paint with the result of SkPaint().
Cary Clark8032b982017-07-28 11:04:54 -0400174
175#Example
176 SkPaint paint1, paint2;
177 paint1.setColor(SK_ColorRED);
178 paint1.reset();
179 SkDebugf("paint1 %c= paint2", paint1 == paint2 ? '=' : '!');
180
181 #StdOut
182 paint1 == paint2
183 ##
184##
185
186##
187
Cary Clark8032b982017-07-28 11:04:54 -0400188# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -0400189
190#Method ~SkPaint()
Cary Clarkab2621d2018-01-30 10:08:57 -0500191#Line # decreases Reference_Count of owned objects ##
Cary Clark8032b982017-07-28 11:04:54 -0400192Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500193Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400194objects containing Reference_Count go to zero, they are deleted.
Cary Clark8032b982017-07-28 11:04:54 -0400195
Herb Derbyfcac00f2018-05-01 11:57:56 -0400196#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400197##
198
199##
200
Cary Clark08895c42018-02-01 09:37:32 -0500201
Cary Clark8032b982017-07-28 11:04:54 -0400202# ------------------------------------------------------------------------------
Cary Clark61313f32018-10-08 14:57:48 -0400203
Cary Clark08895c42018-02-01 09:37:32 -0500204#Subtopic Management
205#Line # paint copying, moving, comparing ##
Cary Clarka90ea222018-10-16 10:30:28 -0400206##
Cary Clark8032b982017-07-28 11:04:54 -0400207
208#Method SkPaint& operator=(const SkPaint& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500209#In Management
210#Line # makes a shallow copy ##
Cary Clark8032b982017-07-28 11:04:54 -0400211Makes a shallow copy of Paint. Typeface, Path_Effect, Shader,
Mike Reed8ad91a92018-01-19 19:09:32 -0500212Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter are shared
Cary Clarkbad5ad72017-08-03 17:14:08 -0400213between the original paint and the copy. Objects containing Reference_Count in the
Cary Clark8032b982017-07-28 11:04:54 -0400214prior destination are decreased by one, and the referenced objects are deleted if the
Cary Clarkbad5ad72017-08-03 17:14:08 -0400215resulting count is zero. Objects containing Reference_Count in the parameter paint
216are increased by one. paint is unmodified.
Cary Clark8032b982017-07-28 11:04:54 -0400217
218#Param paint original to copy ##
219
220#Return content of paint ##
221
222#Example
223 SkPaint paint1, paint2;
224 paint1.setColor(SK_ColorRED);
225 paint2 = paint1;
226 SkDebugf("SK_ColorRED %c= paint1.getColor()\n", SK_ColorRED == paint1.getColor() ? '=' : '!');
227 SkDebugf("SK_ColorRED %c= paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
228
229 #StdOut
230 SK_ColorRED == paint1.getColor()
231 SK_ColorRED == paint2.getColor()
232 ##
233##
234
235##
236
237# ------------------------------------------------------------------------------
238
239#Method SkPaint& operator=(SkPaint&& paint)
Cary Clarkab2621d2018-01-30 10:08:57 -0500240#In Management
241#Line # moves paint without copying it ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400242Moves the paint to avoid increasing the reference counts
Cary Clarkbad5ad72017-08-03 17:14:08 -0400243of objects referenced by the paint parameter. Objects containing Reference_Count in the
244prior destination are decreased by one; those objects are deleted if the resulting count
245is zero.
Cary Clark8032b982017-07-28 11:04:54 -0400246
247After the call, paint is undefined, and can be safely destructed.
248
249 #Param paint original to move ##
250
251 #Return content of paint ##
252
253#Example
254 SkPaint paint1, paint2;
255 paint1.setColor(SK_ColorRED);
256 paint2 = std::move(paint1);
257 SkDebugf("SK_ColorRED == paint2.getColor()\n", SK_ColorRED == paint2.getColor() ? '=' : '!');
258
259 #StdOut
260 SK_ColorRED == paint2.getColor()
261 ##
262##
263
264##
265
266# ------------------------------------------------------------------------------
267
268#Method bool operator==(const SkPaint& a, const SkPaint& b)
Cary Clarkab2621d2018-01-30 10:08:57 -0500269#Line # compares paints for equality ##
Cary Clark8032b982017-07-28 11:04:54 -0400270 Compares a and b, and returns true if a and b are equivalent. May return false
Mike Reed8ad91a92018-01-19 19:09:32 -0500271 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400272 Draw_Looper, or Image_Filter have identical contents but different pointers.
273
274 #Param a Paint to compare ##
275 #Param b Paint to compare ##
276
277 #Return true if Paint pair are equivalent ##
278
279 #Example
280 SkPaint paint1, paint2;
281 paint1.setColor(SK_ColorRED);
282 paint2.setColor(0xFFFF0000);
283 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
284 float intervals[] = { 5, 5 };
285 paint1.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
286 paint2.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
287 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
288
289 #StdOut
290 paint1 == paint2
291 paint1 != paint2
292 ##
293 ##
Cary Clark06c20f32018-03-20 15:53:27 -0400294#SeeAlso operator!=(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400295##
296
297# ------------------------------------------------------------------------------
298
299#Method bool operator!=(const SkPaint& a, const SkPaint& b)
Cary Clarkab2621d2018-01-30 10:08:57 -0500300#Line # compares paints for inequality ##
Cary Clark8032b982017-07-28 11:04:54 -0400301 Compares a and b, and returns true if a and b are not equivalent. May return true
Mike Reed8ad91a92018-01-19 19:09:32 -0500302 if Typeface, Path_Effect, Shader, Mask_Filter, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -0400303 Draw_Looper, or Image_Filter have identical contents but different pointers.
304
305 #Param a Paint to compare ##
306 #Param b Paint to compare ##
307
308 #Return true if Paint pair are not equivalent ##
309
310#Example
311 SkPaint paint1, paint2;
312 paint1.setColor(SK_ColorRED);
313 paint2.setColor(0xFFFF0000);
314 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
315 SkDebugf("paint1 %c= paint2\n", paint1 != paint2 ? '!' : '=');
316
317 #StdOut
318 paint1 == paint2
319 paint1 == paint2
320 ##
321##
Cary Clark06c20f32018-03-20 15:53:27 -0400322#SeeAlso operator==(const SkPaint& a, const SkPaint& b)
Cary Clark8032b982017-07-28 11:04:54 -0400323##
324
325# ------------------------------------------------------------------------------
326
327#Method uint32_t getHash() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500328#In Management
329#Line # returns a shallow hash for equality checks ##
Cary Clark8032b982017-07-28 11:04:54 -0400330Returns a hash generated from Paint values and pointers.
331Identical hashes guarantee that the paints are
332equivalent, but differing hashes do not guarantee that the paints have differing
333contents.
334
335If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
336their hashes are also equal.
337
338The hash returned is platform and implementation specific.
339
340#Return a shallow hash ##
341
342#Example
343 SkPaint paint1, paint2;
344 paint1.setColor(SK_ColorRED);
345 paint2.setColor(0xFFFF0000);
346 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
347 SkDebugf("paint1.getHash() %c= paint2.getHash()\n",
348 paint1.getHash() == paint2.getHash() ? '=' : '!');
349
350 #StdOut
351 paint1 == paint2
352 paint1.getHash() == paint2.getHash()
353 ##
354##
355
356##
357
Cary Clark8032b982017-07-28 11:04:54 -0400358# ------------------------------------------------------------------------------
Cary Clark61313f32018-10-08 14:57:48 -0400359
Cary Clark08895c42018-02-01 09:37:32 -0500360#Subtopic Hinting
361#Line # glyph outline adjustment ##
Cary Clarka90ea222018-10-16 10:30:28 -0400362##
Cary Clark8032b982017-07-28 11:04:54 -0400363
364#Enum Hinting
Cary Clark08895c42018-02-01 09:37:32 -0500365#Line # level of glyph outline adjustment ##
Cary Clark8032b982017-07-28 11:04:54 -0400366
367#Code
Cary Clarka90ea222018-10-16 10:30:28 -0400368#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400369##
370
371Hinting adjusts the glyph outlines so that the shape provides a uniform
372look at a given point size on font engines that support it. Hinting may have a
373muted effect or no effect at all depending on the platform.
374
375The four levels roughly control corresponding features on platforms that use FreeType
376as the Font_Engine.
377
378#Const kNo_Hinting 0
Cary Clark682c58d2018-05-16 07:07:07 -0400379#Line # glyph outlines unchanged ##
Cary Clark8032b982017-07-28 11:04:54 -0400380 Leaves glyph outlines unchanged from their native representation.
381 With FreeType, this is equivalent to the FT_LOAD_NO_HINTING
382 bit-field constant supplied to FT_Load_Glyph, which indicates that the vector
383 outline being loaded should not be fitted to the pixel grid but simply scaled
384 to 26.6 fractional pixels.
385##
386#Const kSlight_Hinting 1
Cary Clark682c58d2018-05-16 07:07:07 -0400387#Line # minimal modification to improve constrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400388 Modifies glyph outlines minimally to improve constrast.
389 With FreeType, this is equivalent in spirit to the
Herb Derbyfcac00f2018-05-01 11:57:56 -0400390 FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
Cary Clark8032b982017-07-28 11:04:54 -0400391 lighter hinting algorithm for non-monochrome modes.
Cary Clarkce101242017-09-01 15:51:02 -0400392 Generated Glyphs may be fuzzy but better resemble their original shape.
Cary Clark8032b982017-07-28 11:04:54 -0400393##
394#Const kNormal_Hinting 2
Cary Clark682c58d2018-05-16 07:07:07 -0400395#Line # glyph outlines modified to improve constrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400396 Modifies glyph outlines to improve constrast. This is the default.
Cary Clark6fc50412017-09-21 12:31:06 -0400397 With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
Herb Derbyfcac00f2018-05-01 11:57:56 -0400398 choosing the default hinting algorithm, which is optimized for standard
399 gray-level rendering.
Cary Clark8032b982017-07-28 11:04:54 -0400400##
401#Const kFull_Hinting 3
Cary Clark137b8742018-05-30 09:21:49 -0400402#Line # modifies glyph outlines for maximum constrast ##
403 Modifies glyph outlines for maximum constrast. With FreeType, this selects
Herb Derbyfcac00f2018-05-01 11:57:56 -0400404 FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
405 FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
406 horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
Cary Clark8032b982017-07-28 11:04:54 -0400407 variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
408##
409
Cary Clark4855f782018-02-06 09:41:53 -0500410#Bug 915
Cary Clark8032b982017-07-28 11:04:54 -0400411On OS_X and iOS, hinting controls whether Core_Graphics dilates the font outlines
Cary Clark137b8742018-05-30 09:21:49 -0400412to account for LCD text. No hinting uses Core_Text Grayscale output.
Cary Clark8032b982017-07-28 11:04:54 -0400413Normal hinting uses Core_Text LCD output. If kLCDRenderText_Flag is clear,
Cary Clark137b8742018-05-30 09:21:49 -0400414the LCD output is reduced to a single Grayscale channel.
Cary Clark8032b982017-07-28 11:04:54 -0400415
416On Windows with DirectWrite, Hinting has no effect.
417
418Hinting defaults to kNormal_Hinting.
419Set SkPaintDefaults_Hinting at compile time to change the default setting.
420
421#ToDo add an illustration? linux running GM:typefacerendering is best for this
422 the hinting variations are every other character horizontally
423#ToDo ##
424
425#Enum ##
426
427#Method Hinting getHinting() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500428#In Hinting
429#Line # returns Hinting, glyph outline adjustment level ##
Cary Clark8032b982017-07-28 11:04:54 -0400430 Returns level of glyph outline adjustment.
431
432 #Return one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
433
434 #Example
435 SkPaint paint;
436 SkDebugf("SkPaint::kNormal_Hinting %c= paint.getHinting()\n",
437 SkPaint::kNormal_Hinting == paint.getHinting() ? '=' : ':');
438
439 #StdOut
440 SkPaint::kNormal_Hinting == paint.getHinting()
441 ##
442 ##
443##
444
445#Method void setHinting(Hinting hintingLevel)
446
Cary Clarkab2621d2018-01-30 10:08:57 -0500447#In Hinting
448#Line # sets Hinting, glyph outline adjustment level ##
Cary Clark8032b982017-07-28 11:04:54 -0400449 Sets level of glyph outline adjustment.
450 Does not check for valid values of hintingLevel.
451
452 #Table
453 #Legend
454 # Hinting # value # effect on generated glyph outlines ##
455 ##
456 # kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
Cary Clarkce101242017-09-01 15:51:02 -0400457 # kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
458 # kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
Herb Derbyfcac00f2018-05-01 11:57:56 -0400459 # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
Cary Clark8032b982017-07-28 11:04:54 -0400460 ##
461
462 #Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
463
464 #Example
465 SkPaint paint1, paint2;
466 paint2.setHinting(SkPaint::kNormal_Hinting);
467 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
468
469 #StdOut
470 paint1 == paint2
471 ##
472 ##
473##
474
Cary Clark8032b982017-07-28 11:04:54 -0400475# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500476#Subtopic Flags
477#Line # attributes represented by single bits ##
Cary Clarka90ea222018-10-16 10:30:28 -0400478##
Cary Clark8032b982017-07-28 11:04:54 -0400479
480#Enum Flags
Cary Clark08895c42018-02-01 09:37:32 -0500481#Line # values described by bits and masks ##
Cary Clark8032b982017-07-28 11:04:54 -0400482
483#Code
Cary Clarka90ea222018-10-16 10:30:28 -0400484#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400485##
486
487The bit values stored in Flags.
488The default value for Flags, normally zero, can be changed at compile time
489with a custom definition of SkPaintDefaults_Flags.
490All flags can be read and written explicitly; Flags allows manipulating
491multiple settings at once.
492
Herb Derbyfcac00f2018-05-01 11:57:56 -0400493 #Const kAntiAlias_Flag 0x0001
Cary Clarkffb3d682018-05-17 12:17:28 -0400494 #Line # mask for setting Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400495 ##
496 #Const kDither_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -0400497 #Line # mask for setting Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400498 ##
Cary Clark8032b982017-07-28 11:04:54 -0400499 #Const kFakeBoldText_Flag 0x0020
Cary Clark682c58d2018-05-16 07:07:07 -0400500 #Line # mask for setting Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -0400501 ##
502 #Const kLinearText_Flag 0x0040
Cary Clark682c58d2018-05-16 07:07:07 -0400503 #Line # mask for setting Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400504 ##
505 #Const kSubpixelText_Flag 0x0080
Cary Clark682c58d2018-05-16 07:07:07 -0400506 #Line # mask for setting Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400507 ##
Cary Clark8032b982017-07-28 11:04:54 -0400508 #Const kLCDRenderText_Flag 0x0200
Cary Clark682c58d2018-05-16 07:07:07 -0400509 #Line # mask for setting LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400510 ##
511 #Const kEmbeddedBitmapText_Flag 0x0400
Cary Clark682c58d2018-05-16 07:07:07 -0400512 #Line # mask for setting Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -0400513 ##
514 #Const kAutoHinting_Flag 0x0800
Cary Clark682c58d2018-05-16 07:07:07 -0400515 #Line # mask for setting Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -0400516 ##
517 #Const kVerticalText_Flag 0x1000
Cary Clark682c58d2018-05-16 07:07:07 -0400518 #Line # mask for setting Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400519 ##
Cary Clark8032b982017-07-28 11:04:54 -0400520 #Const kAllFlags 0xFFFF
Cary Clark682c58d2018-05-16 07:07:07 -0400521 #Line # mask of all Flags ##
Cary Clark8032b982017-07-28 11:04:54 -0400522 mask of all Flags, including private flags and flags reserved for future use
523 ##
524
525Flags default to all flags clear, disabling the associated feature.
526
527#Enum ##
528
529#Enum ReserveFlags
Cary Clark4855f782018-02-06 09:41:53 -0500530#Deprecated soon
Cary Clark8032b982017-07-28 11:04:54 -0400531
Cary Clark4855f782018-02-06 09:41:53 -0500532Only valid for Android framework.
Cary Clark8032b982017-07-28 11:04:54 -0400533
534#Code
Cary Clarka90ea222018-10-16 10:30:28 -0400535#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400536##
537
Cary Clark4855f782018-02-06 09:41:53 -0500538#Const kUnderlineText_ReserveFlag 0x0008
539#Deprecated soon
540##
541#Const kStrikeThruText_ReserveFlag 0x0010
542#Deprecated soon
543##
544##
Cary Clark8032b982017-07-28 11:04:54 -0400545
546#Method uint32_t getFlags() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500547#In Flags
548#Line # returns Flags stored in a bit field ##
Cary Clark8032b982017-07-28 11:04:54 -0400549Returns paint settings described by Flags. Each setting uses one
550bit, and can be tested with Flags members.
551
552#Return zero, one, or more bits described by Flags ##
553
554#Example
555 SkPaint paint;
556 paint.setAntiAlias(true);
557 SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
558 SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
559
560 #StdOut
561 (SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
562 ##
563##
564
565##
566
567#Method void setFlags(uint32_t flags)
Cary Clarkab2621d2018-01-30 10:08:57 -0500568#In Flags
569#Line # sets multiple Flags in a bit field ##
Cary Clark8032b982017-07-28 11:04:54 -0400570Replaces Flags with flags, the union of the Flags members.
571All Flags members may be cleared, or one or more may be set.
572
573#Param flags union of Flags for Paint ##
574
575#Example
576 SkPaint paint;
577 paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
578 SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
579 SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
580
581 #StdOut
582 paint.isAntiAlias()
583 paint.isDither()
584 ##
585##
586
587##
588
Cary Clark8032b982017-07-28 11:04:54 -0400589# ------------------------------------------------------------------------------
Cary Clarkffb3d682018-05-17 12:17:28 -0400590#Subtopic Anti_Alias
591#Alias Anti_Alias
Cary Clark137b8742018-05-30 09:21:49 -0400592#Substitute anti-alias
593##
Cary Clarkffb3d682018-05-17 12:17:28 -0400594#Alias Anti_Aliased
Cary Clark137b8742018-05-30 09:21:49 -0400595#Substitute anti-aliased
596##
Cary Clarkffb3d682018-05-17 12:17:28 -0400597#Alias Anti_Aliasing
Cary Clark137b8742018-05-30 09:21:49 -0400598#Substitute anti-aliasing
599##
Cary Clark4855f782018-02-06 09:41:53 -0500600#In Related_Function
Cary Clarkab2621d2018-01-30 10:08:57 -0500601#Line # approximating coverage with transparency ##
Cary Clark8032b982017-07-28 11:04:54 -0400602
Cary Clarkffb3d682018-05-17 12:17:28 -0400603Anti_Alias drawing approximates partial pixel coverage with transparency.
Cary Clark8032b982017-07-28 11:04:54 -0400604If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
605If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
606
Herb Derbyfcac00f2018-05-01 11:57:56 -0400607The rule for Aliased pixels is inconsistent across platforms. A shape edge
Cary Clark8032b982017-07-28 11:04:54 -0400608passing through the pixel center may, but is not required to, draw the pixel.
609
Cary Clarkce101242017-09-01 15:51:02 -0400610Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
Cary Clark8032b982017-07-28 11:04:54 -0400611active Path edge, and whose center is to the left of the end of the active Path edge.
612
613#ToDo add illustration of raster pixels ##
614
Cary Clarkffb3d682018-05-17 12:17:28 -0400615A platform may only support Anti_Aliased drawing. Some GPU-backed platforms use
616Supersampling to Anti_Alias all drawing, and have no mechanism to selectively
Cary Clarkce101242017-09-01 15:51:02 -0400617Alias.
Cary Clark8032b982017-07-28 11:04:54 -0400618
Cary Clarkffb3d682018-05-17 12:17:28 -0400619The amount of coverage computed for Anti_Aliased pixels also varies across platforms.
Cary Clark8032b982017-07-28 11:04:54 -0400620
Cary Clarkffb3d682018-05-17 12:17:28 -0400621Anti_Alias is disabled by default.
622Anti_Alias can be enabled by default by setting SkPaintDefaults_Flags to kAntiAlias_Flag
Cary Clark8032b982017-07-28 11:04:54 -0400623at compile time.
624
Cary Clarkab2621d2018-01-30 10:08:57 -0500625#Example
Cary Clark8032b982017-07-28 11:04:54 -0400626 #Width 512
627 #Description
628 A red line is drawn with transparency on the edges to make it look smoother.
629 A blue line draws only where the pixel centers are contained.
Cary Clarkce101242017-09-01 15:51:02 -0400630 The lines are drawn into Bitmap, then drawn magnified to make the
631 Aliasing easier to see.
Cary Clark8032b982017-07-28 11:04:54 -0400632 ##
633
634 void draw(SkCanvas* canvas) {
635 SkBitmap bitmap;
636 bitmap.allocN32Pixels(50, 50);
637 SkCanvas offscreen(bitmap);
638 SkPaint paint;
639 paint.setStyle(SkPaint::kStroke_Style);
640 paint.setStrokeWidth(10);
641 for (bool antialias : { false, true }) {
642 paint.setColor(antialias ? SK_ColorRED : SK_ColorBLUE);
643 paint.setAntiAlias(antialias);
644 bitmap.eraseColor(0);
645 offscreen.drawLine(5, 5, 15, 30, paint);
646 canvas->drawLine(5, 5, 15, 30, paint);
647 canvas->save();
648 canvas->scale(10, 10);
649 canvas->drawBitmap(bitmap, antialias ? 12 : 0, 0);
650 canvas->restore();
651 canvas->translate(15, 0);
652 }
653 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500654##
Cary Clarka90ea222018-10-16 10:30:28 -0400655#Subtopic Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400656
657#Method bool isAntiAlias() const
Cary Clark78de7512018-02-07 07:27:09 -0500658#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400659#Line # returns true if Anti_Alias is set ##
Cary Clark8032b982017-07-28 11:04:54 -0400660
Cary Clark80247e52018-07-11 16:18:41 -0400661 Returns true if pixels on the active edges of Path may be drawn with partial transparency.
Cary Clark8032b982017-07-28 11:04:54 -0400662
663 Equivalent to getFlags masked with kAntiAlias_Flag.
664
665 #Return kAntiAlias_Flag state ##
666
667 #Example
668 SkPaint paint;
669 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
670 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
671 paint.setAntiAlias(true);
672 SkDebugf("paint.isAntiAlias() %c= !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)\n",
673 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag) ? '=' : '!');
674
675 #StdOut
676 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
677 paint.isAntiAlias() == !!(paint.getFlags() & SkPaint::kAntiAlias_Flag)
678 ##
679 ##
680##
681
682#Method void setAntiAlias(bool aa)
Cary Clark78de7512018-02-07 07:27:09 -0500683#In Anti_alias
Cary Clarkffb3d682018-05-17 12:17:28 -0400684#Line # sets or clears Anti_Alias ##
Cary Clark8032b982017-07-28 11:04:54 -0400685 Requests, but does not require, that Path edge pixels draw opaque or with
686 partial transparency.
687
688 Sets kAntiAlias_Flag if aa is true.
689 Clears kAntiAlias_Flag if aa is false.
690
691 #Param aa setting for kAntiAlias_Flag ##
692
693 #Example
694 SkPaint paint1, paint2;
695 paint1.setAntiAlias(true);
696 paint2.setFlags(paint2.getFlags() | SkPaint::kAntiAlias_Flag);
697 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
698
699 #StdOut
700 paint1 == paint2
701 ##
702 ##
703
704##
705
Cary Clark8032b982017-07-28 11:04:54 -0400706# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500707#Subtopic Dither
708#Line # distributing color error ##
Cary Clark8032b982017-07-28 11:04:54 -0400709
Herb Derbyfcac00f2018-05-01 11:57:56 -0400710Dither increases fidelity by adjusting the color of adjacent pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400711This can help to smooth color transitions and reducing banding in gradients.
712Dithering lessens visible banding from kRGB_565_SkColorType
Herb Derbyfcac00f2018-05-01 11:57:56 -0400713and kRGBA_8888_SkColorType gradients,
Cary Clark8032b982017-07-28 11:04:54 -0400714and improves rendering into a kRGB_565_SkColorType Surface.
715
716Dithering is always enabled for linear gradients drawing into
717kRGB_565_SkColorType Surface and kRGBA_8888_SkColorType Surface.
718Dither cannot be enabled for kAlpha_8_SkColorType Surface and
719kRGBA_F16_SkColorType Surface.
720
721Dither is disabled by default.
722Dither can be enabled by default by setting SkPaintDefaults_Flags to kDither_Flag
723at compile time.
724
Cary Clark2be81cf2018-09-13 12:04:30 -0400725Some platform implementations may ignore dithering. Set #Formula # SK_IGNORE_GPU_DITHER ##
Cary Clark8032b982017-07-28 11:04:54 -0400726to ignore Dither on GPU_Surface.
727
728#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400729#Description
Cary Clark8032b982017-07-28 11:04:54 -0400730Dithering in the bottom half more closely approximates the requested color by
731alternating nearby colors from pixel to pixel.
732##
733void draw(SkCanvas* canvas) {
734 SkBitmap bm16;
735 bm16.allocPixels(SkImageInfo::Make(32, 32, kRGB_565_SkColorType, kOpaque_SkAlphaType));
736 SkCanvas c16(bm16);
737 SkPaint colorPaint;
738 for (auto dither : { false, true } ) {
739 colorPaint.setDither(dither);
740 for (auto colors : { 0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC } ) {
741 for (auto mask : { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFFFF } ) {
742 colorPaint.setColor(colors & mask);
743 c16.drawRect({0, 0, 8, 4}, colorPaint);
744 c16.translate(8, 0);
745 }
746 c16.translate(-32, 4);
747 }
748 }
749 canvas->scale(8, 8);
750 canvas->drawBitmap(bm16, 0, 0);
751}
752##
753
754#Example
Herb Derbyfcac00f2018-05-01 11:57:56 -0400755#Description
Cary Clark8032b982017-07-28 11:04:54 -0400756Dithering introduces subtle adjustments to color to smooth gradients.
757Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
758dither, making it easier to see.
759##
760void draw(SkCanvas* canvas) {
761 canvas->clear(0);
762 SkBitmap bm32;
763 bm32.allocPixels(SkImageInfo::Make(20, 10, kN32_SkColorType, kPremul_SkAlphaType));
764 SkCanvas c32(bm32);
765 SkPoint points[] = {{0, 0}, {20, 0}};
766 SkColor colors[] = {0xFF334455, 0xFF662211 };
767 SkPaint paint;
768 paint.setShader(SkGradientShader::MakeLinear(
769 points, colors, nullptr, SK_ARRAY_COUNT(colors),
770 SkShader::kClamp_TileMode, 0, nullptr));
771 paint.setDither(true);
772 c32.drawPaint(paint);
773 canvas->scale(12, 12);
774 canvas->drawBitmap(bm32, 0, 0);
775 paint.setBlendMode(SkBlendMode::kPlus);
776 canvas->drawBitmap(bm32, 0, 11, &paint);
777 canvas->drawBitmap(bm32, 0, 11, &paint);
778 canvas->drawBitmap(bm32, 0, 11, &paint);
779}
780##
Cary Clarka90ea222018-10-16 10:30:28 -0400781#SeeAlso Gradient kRGB_565_SkColorType
782#Subtopic Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400783
784#Method bool isDither() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500785#In Dither
786#Line # returns true if Dither is set ##
Cary Clark80247e52018-07-11 16:18:41 -0400787 Returns true if color error may be distributed to smooth color transition.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400788
Cary Clark8032b982017-07-28 11:04:54 -0400789 Equivalent to getFlags masked with kDither_Flag.
790
791 #Return kDither_Flag state ##
792
793 #Example
794 SkPaint paint;
795 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
796 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
797 paint.setDither(true);
798 SkDebugf("paint.isDither() %c= !!(paint.getFlags() & SkPaint::kDither_Flag)\n",
799 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag) ? '=' : '!');
800
801 #StdOut
802 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
803 paint.isDither() == !!(paint.getFlags() & SkPaint::kDither_Flag)
804 ##
805 ##
806
807##
808
809#Method void setDither(bool dither)
Cary Clarkab2621d2018-01-30 10:08:57 -0500810#In Dither
811#Line # sets or clears Dither ##
Cary Clark8032b982017-07-28 11:04:54 -0400812 Requests, but does not require, to distribute color error.
813
814 Sets kDither_Flag if dither is true.
815 Clears kDither_Flag if dither is false.
816
817 #Param dither setting for kDither_Flag ##
818
819 #Example
820 SkPaint paint1, paint2;
821 paint1.setDither(true);
822 paint2.setFlags(paint2.getFlags() | SkPaint::kDither_Flag);
823 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
824
825 #StdOut
826 paint1 == paint2
827 ##
828 ##
829
830 #SeeAlso kRGB_565_SkColorType
831
832##
833
Cary Clark8032b982017-07-28 11:04:54 -0400834# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500835#Subtopic Device_Text
836#Line # increase precision of glyph position ##
Cary Clark8032b982017-07-28 11:04:54 -0400837
838LCD_Text and Subpixel_Text increase the precision of glyph position.
839
Cary Clarkffb3d682018-05-17 12:17:28 -0400840When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -0400841create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -0400842on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -0400843LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -0400844the color components as RGB or BGR.
Cary Clark8032b982017-07-28 11:04:54 -0400845
Herb Derbyfcac00f2018-05-01 11:57:56 -0400846Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400847As the opaqueness
848of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
849
850Either or both techniques can be enabled.
851kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
Herb Derbyfcac00f2018-05-01 11:57:56 -0400852LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
Cary Clark8032b982017-07-28 11:04:54 -0400853kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
854
855#Example
856 #Description
857 Four commas are drawn normally and with combinations of LCD_Text and Subpixel_Text.
Cary Clarkce101242017-09-01 15:51:02 -0400858 When Subpixel_Text is disabled, the comma Glyphs are identical, but not evenly spaced.
859 When Subpixel_Text is enabled, the comma Glyphs are unique, but appear evenly spaced.
Cary Clark8032b982017-07-28 11:04:54 -0400860 ##
861
862 SkBitmap bitmap;
863 bitmap.allocN32Pixels(24, 33);
864 SkCanvas offscreen(bitmap);
865 offscreen.clear(SK_ColorWHITE);
866 SkPaint paint;
867 paint.setAntiAlias(true);
868 paint.setTextSize(20);
869 for (bool lcd : { false, true }) {
870 paint.setLCDRenderText(lcd);
871 for (bool subpixel : { false, true }) {
872 paint.setSubpixelText(subpixel);
873 offscreen.drawString(",,,,", 0, 4, paint);
874 offscreen.translate(0, 7);
875 }
876 }
877 canvas->drawBitmap(bitmap, 4, 12);
878 canvas->scale(9, 9);
879 canvas->drawBitmap(bitmap, 4, -1);
880##
Cary Clark08895c42018-02-01 09:37:32 -0500881#Subtopic Device_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400882
883#Subtopic Linear_Text
Cary Clark137b8742018-05-30 09:21:49 -0400884#Alias Linear_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500885#Line # selects text rendering as Glyph or Path ##
Cary Clark8032b982017-07-28 11:04:54 -0400886
887Linear_Text selects whether text is rendered as a Glyph or as a Path.
888If kLinearText_Flag is set, it has the same effect as setting Hinting to kNormal_Hinting.
Cary Clarkd0530ba2017-09-14 11:25:39 -0400889If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
Cary Clarka90ea222018-10-16 10:30:28 -0400890#Subtopic Linear_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400891
892#Method bool isLinearText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500893#In Linear_Text
Cary Clarka90ea222018-10-16 10:30:28 -0400894#Line # returns true if text is converted to Path ##
Cary Clark80247e52018-07-11 16:18:41 -0400895 Returns true if text is converted to Path before drawing and measuring.
Cary Clark8032b982017-07-28 11:04:54 -0400896
897 Equivalent to getFlags masked with kLinearText_Flag.
898
899 #Return kLinearText_Flag state ##
900
901 #Example
902 #Height 128
903 void draw(SkCanvas* canvas) {
904 SkPaint paint;
905 paint.setAntiAlias(true);
906 const char testStr[] = "xxxx xxxx";
907 for (auto linearText : { false, true } ) {
908 paint.setLinearText(linearText);
909 paint.setTextSize(24);
910 canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
911 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
912 paint.setTextSize(textSize);
913 canvas->translate(0, textSize);
914 canvas->drawString(testStr, 10, 0, paint);
915 }
916 }
917 }
918 ##
919
920 #SeeAlso setLinearText Hinting
921##
922
923#Method void setLinearText(bool linearText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500924#In Linear_Text
Cary Clarka90ea222018-10-16 10:30:28 -0400925#Line # converts to Path before draw or measure ##
Cary Clark80247e52018-07-11 16:18:41 -0400926 Returns true if text is converted to Path before drawing and measuring.
Cary Clark8032b982017-07-28 11:04:54 -0400927 By default, kLinearText_Flag is clear.
928
929 Sets kLinearText_Flag if linearText is true.
930 Clears kLinearText_Flag if linearText is false.
931
932 #Param linearText setting for kLinearText_Flag ##
933
934 #Example
935 #Height 128
936 void draw(SkCanvas* canvas) {
937 SkPaint paint;
938 paint.setAntiAlias(true);
939 const char testStr[] = "abcd efgh";
940 for (int textSize : { 12, 24 } ) {
941 paint.setTextSize(textSize);
942 for (auto linearText : { false, true } ) {
943 paint.setLinearText(linearText);
944 SkString width;
945 width.appendScalar(paint.measureText(testStr, SK_ARRAY_COUNT(testStr), nullptr));
946 canvas->translate(0, textSize + 4);
947 canvas->drawString(testStr, 10, 0, paint);
948 canvas->drawString(width, 128, 0, paint);
949 }
950 }
Herb Derbyfcac00f2018-05-01 11:57:56 -0400951 }
Cary Clark8032b982017-07-28 11:04:54 -0400952 ##
953
954 #SeeAlso isLinearText Hinting
955##
956
Cary Clark8032b982017-07-28 11:04:54 -0400957#Subtopic Subpixel_Text
Cary Clark137b8742018-05-30 09:21:49 -0400958#Alias Subpixel_Text ##
Cary Clark08895c42018-02-01 09:37:32 -0500959#Line # uses pixel transparency to represent fractional offset ##
Cary Clark8032b982017-07-28 11:04:54 -0400960
Herb Derbyfcac00f2018-05-01 11:57:56 -0400961Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
Cary Clark8032b982017-07-28 11:04:54 -0400962As the opaqueness
963of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
Cary Clarka90ea222018-10-16 10:30:28 -0400964#Subtopic Subpixel_Text ##
Cary Clark8032b982017-07-28 11:04:54 -0400965
966#Method bool isSubpixelText() const
Cary Clarkab2621d2018-01-30 10:08:57 -0500967#In Subpixel_Text
968#Line # returns true if Subpixel_Text is set ##
Cary Clark80247e52018-07-11 16:18:41 -0400969 Returns true if Glyphs at different sub-pixel positions may differ on pixel edge coverage.
Cary Clark8032b982017-07-28 11:04:54 -0400970
971 Equivalent to getFlags masked with kSubpixelText_Flag.
972
973 #Return kSubpixelText_Flag state ##
974
975 #Example
976SkPaint paint;
977SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
978 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
979paint.setSubpixelText(true);
980SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
981 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
982
983 #StdOut
984 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
985 paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
986 ##
987 ##
988
989##
990
991#Method void setSubpixelText(bool subpixelText)
Cary Clarkab2621d2018-01-30 10:08:57 -0500992#In Subpixel_Text
993#Line # sets or clears Subpixel_Text ##
Cary Clarkce101242017-09-01 15:51:02 -0400994 Requests, but does not require, that Glyphs respect sub-pixel positioning.
Cary Clark8032b982017-07-28 11:04:54 -0400995
996 Sets kSubpixelText_Flag if subpixelText is true.
997 Clears kSubpixelText_Flag if subpixelText is false.
998
999 #Param subpixelText setting for kSubpixelText_Flag ##
1000
1001 #Example
1002 SkPaint paint1, paint2;
1003 paint1.setSubpixelText(true);
1004 paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
1005 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1006
1007 #StdOut
1008 paint1 == paint2
1009 ##
1010 ##
1011
1012##
1013
Cary Clark8032b982017-07-28 11:04:54 -04001014#Subtopic LCD_Text
Cary Clarkffb3d682018-05-17 12:17:28 -04001015#Line # text relying on the order of RGB stripes ##
Cary Clark137b8742018-05-30 09:21:49 -04001016
1017# make this a top level name, since it is under subtopic Device_Text
1018#Alias LCD_Text
1019#Substitute LCD text
1020##
Cary Clark8032b982017-07-28 11:04:54 -04001021
Cary Clarkffb3d682018-05-17 12:17:28 -04001022When set, Flags kLCDRenderText_Flag takes advantage of the organization of RGB stripes that
Cary Clark8032b982017-07-28 11:04:54 -04001023create a color, and relies
Cary Clarkce101242017-09-01 15:51:02 -04001024on the small size of the stripe and visual perception to make the color fringing imperceptible.
Cary Clark8032b982017-07-28 11:04:54 -04001025LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
Cary Clarkffb3d682018-05-17 12:17:28 -04001026the color components as RGB or BGR.
Cary Clarka90ea222018-10-16 10:30:28 -04001027#Subtopic LCD_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001028
1029#Method bool isLCDRenderText() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001030#In LCD_Text
1031#Line # returns true if LCD_Text is set ##
Cary Clark80247e52018-07-11 16:18:41 -04001032 Returns true if Glyphs may use LCD striping to improve glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001033
1034 Returns true if Flags kLCDRenderText_Flag is set.
1035
1036 #Return kLCDRenderText_Flag state ##
1037
1038 #Example
1039SkPaint paint;
1040SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1041 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1042paint.setLCDRenderText(true);
1043SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
1044 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
1045
1046 #StdOut
1047 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1048 paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
1049 ##
1050 ##
1051
1052##
1053
1054#Method void setLCDRenderText(bool lcdText)
Cary Clarkab2621d2018-01-30 10:08:57 -05001055#In LCD_Text
1056#Line # sets or clears LCD_Text ##
Cary Clarkce101242017-09-01 15:51:02 -04001057 Requests, but does not require, that Glyphs use LCD striping for glyph edges.
Cary Clark8032b982017-07-28 11:04:54 -04001058
1059 Sets kLCDRenderText_Flag if lcdText is true.
1060 Clears kLCDRenderText_Flag if lcdText is false.
1061
1062 #Param lcdText setting for kLCDRenderText_Flag ##
1063
1064 #Example
1065 SkPaint paint1, paint2;
1066 paint1.setLCDRenderText(true);
1067 paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
1068 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1069
1070 #StdOut
1071 paint1 == paint2
1072 ##
1073 ##
1074
1075
1076##
1077
Cary Clark8032b982017-07-28 11:04:54 -04001078# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001079#Subtopic Font_Embedded_Bitmaps
1080#Line # custom sized bitmap Glyphs ##
Cary Clark137b8742018-05-30 09:21:49 -04001081#Alias Font_Embedded_Bitmaps ## # long-winded enough, alias so I don't type Paint_Font_...
Cary Clark8032b982017-07-28 11:04:54 -04001082
Cary Clarkce101242017-09-01 15:51:02 -04001083Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001084Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
Herb Derbyfcac00f2018-05-01 11:57:56 -04001085in a font if the platform supports this option.
Cary Clark8032b982017-07-28 11:04:54 -04001086
1087FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
1088the outline glyph if kEmbeddedBitmapText_Flag is clear.
1089Windows may select the bitmap glyph but is not required to do so.
1090OS_X and iOS do not support this option.
1091
1092Font_Embedded_Bitmaps is disabled by default.
1093Font_Embedded_Bitmaps can be enabled by default by setting SkPaintDefaults_Flags to
1094kEmbeddedBitmapText_Flag at compile time.
1095
1096#Example
1097 #ToDo image will only output on Ubuntu ... how to handle that in fiddle? ##
1098 #Platform !fiddle
1099 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001100 The "hintgasp" TrueType font in the Skia resources/fonts directory
1101 includes an embedded bitmap Glyph at odd font sizes. This example works
1102 on platforms that use FreeType as their Font_Engine.
1103 Windows may, but is not required to, return a bitmap glyph if
1104 kEmbeddedBitmapText_Flag is set.
Cary Clark8032b982017-07-28 11:04:54 -04001105 ##
1106 #Image embeddedbitmap.png
1107
1108 SkBitmap bitmap;
1109 bitmap.allocN32Pixels(30, 15);
1110 bitmap.eraseColor(0);
1111 SkCanvas offscreen(bitmap);
1112 SkPaint paint;
1113 paint.setAntiAlias(true);
1114 paint.setTextSize(13);
Hal Canary53e5e7d2017-12-08 14:25:14 -05001115 paint.setTypeface(MakeResourceAsTypeface("fonts/hintgasp.ttf"));
Cary Clark8032b982017-07-28 11:04:54 -04001116 for (bool embedded : { false, true}) {
1117 paint.setEmbeddedBitmapText(embedded);
1118 offscreen.drawString("A", embedded ? 5 : 15, 15, paint);
1119 }
1120 canvas->drawBitmap(bitmap, 0, 0);
1121 canvas->scale(10, 10);
1122 canvas->drawBitmap(bitmap, -2, 1);
1123##
Cary Clarka90ea222018-10-16 10:30:28 -04001124#Subtopic Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001125
1126#Method bool isEmbeddedBitmapText() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001127#In Font_Embedded_Bitmaps
1128#Line # returns true if Font_Embedded_Bitmaps is set ##
Cary Clark80247e52018-07-11 16:18:41 -04001129 Returns true if Font_Engine may return Glyphs from font bitmaps instead of from outlines.
Cary Clark8032b982017-07-28 11:04:54 -04001130
1131 Equivalent to getFlags masked with kEmbeddedBitmapText_Flag.
1132
1133 #Return kEmbeddedBitmapText_Flag state ##
1134
1135 #Example
1136 SkPaint paint;
1137 SkDebugf("paint.isEmbeddedBitmapText() %c="
1138 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1139 paint.isEmbeddedBitmapText() ==
1140 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1141 paint.setEmbeddedBitmapText(true);
1142 SkDebugf("paint.isEmbeddedBitmapText() %c="
1143 " !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
1144 paint.isEmbeddedBitmapText() ==
1145 !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
1146
1147 #StdOut
1148 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1149 paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
1150 ##
1151 ##
1152
1153##
1154
1155#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
Cary Clarkab2621d2018-01-30 10:08:57 -05001156#In Font_Embedded_Bitmaps
1157#Line # sets or clears Font_Embedded_Bitmaps ##
Cary Clark8032b982017-07-28 11:04:54 -04001158 Requests, but does not require, to use bitmaps in fonts instead of outlines.
1159
1160 Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
1161 Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
1162
1163 #Param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag ##
1164
1165 #Example
1166 SkPaint paint1, paint2;
1167 paint1.setEmbeddedBitmapText(true);
1168 paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
1169 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1170
1171 #StdOut
1172 paint1 == paint2
1173 ##
1174 ##
1175
1176##
1177
Cary Clark8032b982017-07-28 11:04:54 -04001178# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001179#Subtopic Automatic_Hinting
1180#Line # always adjust glyph paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001181#Substitute auto-hinting
1182
1183If Hinting is set to kNormal_Hinting or kFull_Hinting, Automatic_Hinting
Cary Clarkce101242017-09-01 15:51:02 -04001184instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001185Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1186kSlight_Hinting.
1187
1188Automatic_Hinting only affects platforms that use FreeType as the Font_Manager.
Cary Clarka90ea222018-10-16 10:30:28 -04001189#Subtopic Automatic_Hinting ##
Cary Clark8032b982017-07-28 11:04:54 -04001190
1191#Method bool isAutohinted() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001192#In Automatic_Hinting
1193#Line # returns true if Glyphs are always hinted ##
Cary Clark80247e52018-07-11 16:18:41 -04001194 Returns true if Hinting is set to kNormal_Hinting or kFull_Hinting, and if
1195 platform uses FreeType as the Font_Manager. If true, instructs
1196 the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001197
1198 Equivalent to getFlags masked with kAutoHinting_Flag.
1199
1200 #Return kAutoHinting_Flag state ##
1201
1202 #Example
1203 SkPaint paint;
1204 for (auto forceAutoHinting : { false, true} ) {
1205 paint.setAutohinted(forceAutoHinting);
1206 SkDebugf("paint.isAutohinted() %c="
1207 " !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
1208 paint.isAutohinted() ==
1209 !!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
1210 }
1211 #StdOut
1212 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1213 paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
1214 ##
1215 ##
1216
1217 #SeeAlso setAutohinted Hinting
1218
1219##
1220
1221#Method void setAutohinted(bool useAutohinter)
Cary Clarkab2621d2018-01-30 10:08:57 -05001222#In Automatic_Hinting
1223#Line # sets Glyphs to always be hinted ##
Cary Clark80247e52018-07-11 16:18:41 -04001224 Sets whether to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001225 If Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,
Cary Clark80247e52018-07-11 16:18:41 -04001226 instructs the Font_Manager to always hint Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04001227 Automatic_Hinting has no effect if Hinting is set to kNo_Hinting or
1228 kSlight_Hinting.
1229
Cary Clark579985c2017-07-31 11:48:27 -04001230 Only affects platforms that use FreeType as the Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001231
1232 Sets kAutoHinting_Flag if useAutohinter is true.
1233 Clears kAutoHinting_Flag if useAutohinter is false.
1234
1235 #Param useAutohinter setting for kAutoHinting_Flag ##
1236
1237 #Example
1238 void draw(SkCanvas* canvas) {
1239 SkPaint paint;
1240 paint.setAntiAlias(true);
1241 const char testStr[] = "xxxx xxxx";
1242 for (auto forceAutoHinting : { false, true} ) {
1243 paint.setAutohinted(forceAutoHinting);
1244 paint.setTextSize(24);
1245 canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
1246 for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
1247 paint.setTextSize(textSize);
1248 canvas->translate(0, textSize);
1249 canvas->drawString(testStr, 10, 0, paint);
1250 }
1251 }
1252 }
1253 ##
1254
1255 #SeeAlso isAutohinted Hinting
1256
1257##
1258
Cary Clark8032b982017-07-28 11:04:54 -04001259# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001260#Subtopic Vertical_Text
1261#Line # orient text from top to bottom ##
Cary Clark8032b982017-07-28 11:04:54 -04001262
1263Text may be drawn by positioning each glyph, or by positioning the first glyph and
Cary Clarkce101242017-09-01 15:51:02 -04001264using Font_Advance to position subsequent Glyphs. By default, each successive glyph
1265is positioned to the right of the preceding glyph. Vertical_Text sets successive
1266Glyphs to position below the preceding glyph.
Cary Clark8032b982017-07-28 11:04:54 -04001267
Cary Clarkce101242017-09-01 15:51:02 -04001268Skia can translate text character codes as a series of Glyphs, but does not implement
Herb Derbyfcac00f2018-05-01 11:57:56 -04001269font substitution,
Cary Clarkce101242017-09-01 15:51:02 -04001270textual substitution, line layout, or contextual spacing like Kerning pairs. Use
Cary Clark6fc50412017-09-21 12:31:06 -04001271a text shaping engine like
Cary Clark682c58d2018-05-16 07:07:07 -04001272#A HarfBuzz # https://harfbuzz.org/ ##
Cary Clark6fc50412017-09-21 12:31:06 -04001273 to translate text runs
Cary Clark8032b982017-07-28 11:04:54 -04001274into glyph series.
1275
1276Vertical_Text is clear if text is drawn left to right or set if drawn from top to bottom.
1277
1278Flags kVerticalText_Flag if clear draws text left to right.
1279Flags kVerticalText_Flag if set draws text top to bottom.
1280
1281Vertical_Text is clear by default.
1282Vertical_Text can be set by default by setting SkPaintDefaults_Flags to
1283kVerticalText_Flag at compile time.
1284
1285#Example
1286
1287void draw(SkCanvas* canvas) {
1288 SkPaint paint;
1289 paint.setAntiAlias(true);
1290 paint.setTextSize(50);
1291 for (bool vertical : { false, true } ) {
1292 paint.setVerticalText(vertical);
1293 canvas->drawString("aAlL", 25, 50, paint);
1294 }
1295}
1296
1297##
Cary Clarka90ea222018-10-16 10:30:28 -04001298#Subtopic Vertical_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04001299
1300#Method bool isVerticalText() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001301#In Vertical_Text
1302#Line # returns true if Vertical_Text is set ##
Cary Clark80247e52018-07-11 16:18:41 -04001303 Returns true if Glyphs are drawn top to bottom instead of left to right.
Cary Clark8032b982017-07-28 11:04:54 -04001304
1305 Equivalent to getFlags masked with kVerticalText_Flag.
1306
1307 #Return kVerticalText_Flag state ##
1308
1309 #Example
1310 SkPaint paint;
1311 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1312 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1313 paint.setVerticalText(true);
1314 SkDebugf("paint.isVerticalText() %c= !!(paint.getFlags() & SkPaint::kVerticalText_Flag)\n",
1315 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag) ? '=' : '!');
1316
1317 #StdOut
1318 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1319 paint.isVerticalText() == !!(paint.getFlags() & SkPaint::kVerticalText_Flag)
1320 ##
1321 ##
1322
1323##
1324
1325#Method void setVerticalText(bool verticalText)
Cary Clarkab2621d2018-01-30 10:08:57 -05001326#In Vertical_Text
1327#Line # sets or clears Vertical_Text ##
Cary Clark80247e52018-07-11 16:18:41 -04001328 Returns true if text advance positions the next glyph below the previous glyph instead of to the
Cary Clark8032b982017-07-28 11:04:54 -04001329 right of previous glyph.
1330
1331 Sets kVerticalText_Flag if vertical is true.
1332 Clears kVerticalText_Flag if vertical is false.
1333
1334 #Param verticalText setting for kVerticalText_Flag ##
1335
1336 #Example
1337 SkPaint paint1, paint2;
1338 paint1.setVerticalText(true);
1339 paint2.setFlags(paint2.getFlags() | SkPaint::kVerticalText_Flag);
1340 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1341
1342 #StdOut
1343 paint1 == paint2
1344 ##
1345 ##
1346
1347##
1348
Cary Clark8032b982017-07-28 11:04:54 -04001349# ------------------------------------------------------------------------------
1350
Cary Clark08895c42018-02-01 09:37:32 -05001351#Subtopic Fake_Bold
1352#Line # approximate font styles ##
Cary Clark8032b982017-07-28 11:04:54 -04001353
1354Fake_Bold approximates the bold font style accompanying a normal font when a bold font face
1355is not available. Skia does not provide font substitution; it is up to the client to find the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001356bold font face using the platform Font_Manager.
Cary Clark8032b982017-07-28 11:04:54 -04001357
Herb Derbyfcac00f2018-05-01 11:57:56 -04001358Use Text_Skew_X to approximate an italic font style when the italic font face
Cary Clark8032b982017-07-28 11:04:54 -04001359is not available.
1360
Cary Clarkce101242017-09-01 15:51:02 -04001361A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
1362the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
Herb Derbyfcac00f2018-05-01 11:57:56 -04001363by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Cary Clark8032b982017-07-28 11:04:54 -04001364
1365Fake_Bold is disabled by default.
1366
1367#Example
1368#Height 128
1369void draw(SkCanvas* canvas) {
1370 SkPaint paint;
1371 paint.setAntiAlias(true);
1372 paint.setTextSize(40);
1373 canvas->drawString("OjYy_-", 10, 35, paint);
1374 paint.setFakeBoldText(true);
1375 canvas->drawString("OjYy_-", 10, 75, paint);
1376 // create a custom fake bold by varying the stroke width
1377 paint.setFakeBoldText(false);
1378 paint.setStyle(SkPaint::kStrokeAndFill_Style);
1379 paint.setStrokeWidth(40.f / 48);
1380 canvas->drawString("OjYy_-", 10, 115, paint);
1381}
1382##
Cary Clarka90ea222018-10-16 10:30:28 -04001383#Subtopic Fake_Bold ##
Cary Clark8032b982017-07-28 11:04:54 -04001384
1385#Method bool isFakeBoldText() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001386#In Fake_Bold
1387#Line # returns true if Fake_Bold is set ##
Cary Clark80247e52018-07-11 16:18:41 -04001388 Returns true if approximate bold by increasing the stroke width when creating glyph bitmaps
Cary Clark8032b982017-07-28 11:04:54 -04001389 from outlines.
1390
1391 Equivalent to getFlags masked with kFakeBoldText_Flag.
1392
1393 #Return kFakeBoldText_Flag state ##
1394
1395 #Example
1396 SkPaint paint;
1397 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1398 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1399 paint.setFakeBoldText(true);
1400 SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
1401 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
1402
1403 #StdOut
1404 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1405 paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
1406 ##
1407 ##
1408
1409##
1410
1411#Method void setFakeBoldText(bool fakeBoldText)
Cary Clarkab2621d2018-01-30 10:08:57 -05001412#In Fake_Bold
1413#Line # sets or clears Fake_Bold ##
Cary Clark80247e52018-07-11 16:18:41 -04001414 Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
Cary Clark8032b982017-07-28 11:04:54 -04001415
1416 Sets kFakeBoldText_Flag if fakeBoldText is true.
1417 Clears kFakeBoldText_Flag if fakeBoldText is false.
1418
1419 #Param fakeBoldText setting for kFakeBoldText_Flag ##
1420
1421 #Example
1422 SkPaint paint1, paint2;
1423 paint1.setFakeBoldText(true);
1424 paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
1425 SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
1426
1427 #StdOut
1428 paint1 == paint2
1429 ##
1430 ##
1431
1432##
1433
Cary Clark8032b982017-07-28 11:04:54 -04001434# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001435#Subtopic Full_Hinting_Spacing
1436#Line # glyph spacing affected by hinting ##
Cary Clark137b8742018-05-30 09:21:49 -04001437#Alias Full_Hinting_Spacing ## # long winded enough -- maybe things with two underscores auto-aliased?
Cary Clark8032b982017-07-28 11:04:54 -04001438
Cary Clarkce101242017-09-01 15:51:02 -04001439if Hinting is set to kFull_Hinting, Full_Hinting_Spacing adjusts the character
1440spacing by the difference of the hinted and Unhinted Left_Side_Bearing and
1441Right_Side_Bearing. Full_Hinting_Spacing only applies to platforms that use
1442FreeType as their Font_Engine.
Cary Clark8032b982017-07-28 11:04:54 -04001443
Cary Clarkce101242017-09-01 15:51:02 -04001444Full_Hinting_Spacing is not related to text Kerning, where the space between
Cary Clarkbc5697d2017-10-04 14:31:33 -04001445a specific pair of characters is adjusted using data in the font Kerning tables.
Cary Clarka90ea222018-10-16 10:30:28 -04001446#Subtopic Full_Hinting_Spacing ##
Cary Clark8032b982017-07-28 11:04:54 -04001447
1448#Method bool isDevKernText() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04001449#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001450##
1451
Herb Derbyfcac00f2018-05-01 11:57:56 -04001452#Method void setDevKernText(bool)
1453#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04001454##
1455
Cary Clark8032b982017-07-28 11:04:54 -04001456# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001457#Subtopic Filter_Quality_Methods
1458#Line # get and set Filter_Quality ##
Cary Clark8032b982017-07-28 11:04:54 -04001459
1460Filter_Quality trades speed for image filtering when the image is scaled.
1461A lower Filter_Quality draws faster, but has less fidelity.
1462A higher Filter_Quality draws slower, but looks better.
Cary Clarkce101242017-09-01 15:51:02 -04001463If the image is drawn without scaling, the Filter_Quality choice will not result
1464in a noticeable difference.
Cary Clark8032b982017-07-28 11:04:54 -04001465
1466Filter_Quality is used in Paint passed as a parameter to
1467#List
1468# SkCanvas::drawBitmap ##
1469# SkCanvas::drawBitmapRect ##
1470# SkCanvas::drawImage ##
1471# SkCanvas::drawImageRect ##
1472 #ToDo probably more... ##
1473#List ##
1474and when Paint has a Shader specialization that uses Image or Bitmap.
1475
1476Filter_Quality is kNone_SkFilterQuality by default.
1477
1478#Example
1479#Image 3
1480void draw(SkCanvas* canvas) {
1481 SkPaint paint;
1482 canvas->scale(.2f, .2f);
Herb Derbyfcac00f2018-05-01 11:57:56 -04001483 for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001484 kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
1485 paint.setFilterQuality(q);
1486 canvas->drawImage(image.get(), 0, 0, &paint);
1487 canvas->translate(550, 0);
1488 if (kLow_SkFilterQuality == q) canvas->translate(-1100, 550);
1489 }
1490}
1491##
Cary Clarka90ea222018-10-16 10:30:28 -04001492#Subtopic Filter_Quality_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001493
1494#Method SkFilterQuality getFilterQuality() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001495#In Filter_Quality_Methods
1496#Line # returns Filter_Quality, image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001497Returns Filter_Quality, the image filtering level. A lower setting
1498draws faster; a higher setting looks better when the image is scaled.
1499
Herb Derbyfcac00f2018-05-01 11:57:56 -04001500#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001501 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1502#Return ##
1503
1504#Example
1505 SkPaint paint;
1506 SkDebugf("kNone_SkFilterQuality %c= paint.getFilterQuality()\n",
1507 kNone_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1508
1509 #StdOut
1510 kNone_SkFilterQuality == paint.getFilterQuality()
1511 ##
1512##
1513
1514##
1515
1516
1517#Method void setFilterQuality(SkFilterQuality quality)
Cary Clarkab2621d2018-01-30 10:08:57 -05001518#In Filter_Quality_Methods
1519#Line # sets Filter_Quality, the image filtering level ##
Cary Clark8032b982017-07-28 11:04:54 -04001520Sets Filter_Quality, the image filtering level. A lower setting
1521draws faster; a higher setting looks better when the image is scaled.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001522Does not check to see if quality is valid.
Cary Clark8032b982017-07-28 11:04:54 -04001523
Herb Derbyfcac00f2018-05-01 11:57:56 -04001524#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
Cary Clark8032b982017-07-28 11:04:54 -04001525 kMedium_SkFilterQuality, kHigh_SkFilterQuality
1526##
1527
1528#Example
1529 SkPaint paint;
1530 paint.setFilterQuality(kHigh_SkFilterQuality);
1531 SkDebugf("kHigh_SkFilterQuality %c= paint.getFilterQuality()\n",
1532 kHigh_SkFilterQuality == paint.getFilterQuality() ? '=' : '!');
1533
1534 #StdOut
1535 kHigh_SkFilterQuality == paint.getFilterQuality()
1536 ##
1537##
1538
1539#SeeAlso SkFilterQuality Image_Scaling
1540
1541##
1542
Cary Clark8032b982017-07-28 11:04:54 -04001543# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001544#Subtopic Color_Methods
1545#Line # get and set Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001546
Cary Clarkab2621d2018-01-30 10:08:57 -05001547#Table
1548#Legend
1549# name # description ##
1550#Legend ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001551# getColor # returns Color_Alpha and RGB, one drawing color ##
1552# setColor # sets Color_Alpha and RGB, one drawing color ##
Cary Clarkab2621d2018-01-30 10:08:57 -05001553#Table ##
Cary Clark8032b982017-07-28 11:04:54 -04001554
Cary Clarkffb3d682018-05-17 12:17:28 -04001555Color specifies the red, blue, green, and Color_Alpha
Cary Clarkab2621d2018-01-30 10:08:57 -05001556values used to draw a filled or stroked shape in a 32-bit value. Each component
1557occupies 8-bits, ranging from zero: no contribution; to 255: full intensity.
1558All values in any combination are valid.
Cary Clark8032b982017-07-28 11:04:54 -04001559
Cary Clarkab2621d2018-01-30 10:08:57 -05001560Color is not Premultiplied; Color_Alpha sets the transparency independent of
Cary Clarkffb3d682018-05-17 12:17:28 -04001561RGB: red, blue, and green.
Cary Clarkab2621d2018-01-30 10:08:57 -05001562
Cary Clarkffb3d682018-05-17 12:17:28 -04001563The bit positions of Color_Alpha and RGB are independent of the bit
Cary Clarkab2621d2018-01-30 10:08:57 -05001564positions on the output device, which may have more or fewer bits, and may have
1565a different arrangement.
Cary Clark8032b982017-07-28 11:04:54 -04001566
1567#Table
1568#Legend
Cary Clarkffb3d682018-05-17 12:17:28 -04001569# bit positions # Color_Alpha # red # blue # green ##
Cary Clark8032b982017-07-28 11:04:54 -04001570#Legend ##
1571# # 31 - 24 # 23 - 16 # 15 - 8 # 7 - 0 ##
1572#Table ##
1573
1574#Example
1575#Height 128
1576 void draw(SkCanvas* canvas) {
1577 SkPaint paint;
1578 paint.setColor(0x8000FF00); // transparent green
1579 canvas->drawCircle(50, 50, 40, paint);
1580 paint.setARGB(128, 255, 0, 0); // transparent red
1581 canvas->drawCircle(80, 50, 40, paint);
1582 paint.setColor(SK_ColorBLUE);
1583 paint.setAlpha(0x80);
1584 canvas->drawCircle(65, 65, 40, paint);
1585 }
1586##
Cary Clarka90ea222018-10-16 10:30:28 -04001587#Subtopic Color_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001588
1589#Method SkColor getColor() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001590#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001591#Line # returns Color_Alpha and RGB, one drawing color ##
1592 Retrieves Alpha and RGB, Unpremultiplied, packed into 32 bits.
Cary Clark8032b982017-07-28 11:04:54 -04001593 Use helpers SkColorGetA, SkColorGetR, SkColorGetG, and SkColorGetB to extract
1594 a color component.
1595
Cary Clarkffb3d682018-05-17 12:17:28 -04001596 #Return Unpremultiplied ARGB ##
Cary Clark8032b982017-07-28 11:04:54 -04001597
1598 #Example
1599 SkPaint paint;
1600 paint.setColor(SK_ColorYELLOW);
1601 SkColor y = paint.getColor();
1602 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (SkColorGetR(y) / 2.55f),
1603 (int) (SkColorGetG(y) / 2.55f), (int) (SkColorGetB(y) / 2.55f));
1604
1605 #StdOut
1606 Yellow is 100% red, 100% green, and 0% blue.
1607 ##
1608 ##
1609
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001610 #SeeAlso getColor4f SkColor
Cary Clark8032b982017-07-28 11:04:54 -04001611
1612##
1613
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001614#Method SkColor4f getColor4f() const
1615#In Color_Methods
1616#Line # returns Color_Alpha and RGB, one drawing color ##
1617 Retrieves alpha and RGB, unpmreultiplied, as four floating point values. RGB are
1618 are extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function).
Brian Osman3f70d172018-09-04 19:50:28 +00001619
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001620 #Return Unpremultiplied RGBA ##
1621
1622 #ToDo enable and correct example once fiddle picks up getColor4f ##
1623 #Example
1624 SkPaint paint;
1625 paint.setColor(SK_ColorYELLOW);
1626 SkColor4f y = paint.getColor4f();
1627 SkDebugf("Yellow is %d%% red, %d%% green, and %d%% blue.\n", (int) (y.fR * 100),
1628 (int) (y.fG * 100), (int) (y.fB * 100));
1629
1630 #StdOut
1631 Yellow is 100% red, 100% green, and 0% blue.
1632 ##
1633 ##
1634
1635 #SeeAlso getColor SkColor
1636##
1637
1638
1639#Method void setColor(SkColor color)
Cary Clarkab2621d2018-01-30 10:08:57 -05001640#In Color_Methods
Cary Clarkffb3d682018-05-17 12:17:28 -04001641#Line # sets Color_Alpha and RGB, one drawing color ##
1642 Sets Alpha and RGB used when stroking and filling. The color is a 32-bit value,
1643 Unpremultiplied, packing 8-bit components for Alpha, red, blue, and green.
Cary Clark8032b982017-07-28 11:04:54 -04001644
Cary Clarkffb3d682018-05-17 12:17:28 -04001645 #Param color Unpremultiplied ARGB ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001646
Cary Clark0c5f5462017-12-15 11:21:51 -05001647 #Example
Cary Clark8032b982017-07-28 11:04:54 -04001648 SkPaint green1, green2;
1649 unsigned a = 255;
1650 unsigned r = 0;
1651 unsigned g = 255;
1652 unsigned b = 0;
1653 green1.setColor((a << 24) + (r << 16) + (g << 8) + (b << 0));
1654 green2.setColor(0xFF00FF00);
1655 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1656
1657 #StdOut
1658 green1 == green2
1659 ##
1660 ##
1661
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001662 #SeeAlso SkColor setColor4f setARGB SkColorSetARGB
Cary Clark8032b982017-07-28 11:04:54 -04001663
1664##
Cary Clarkbbe8ff92018-09-05 11:39:01 -04001665
1666#Method void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace)
1667#In Color_Methods
1668#Line # sets Color_Alpha and RGB, one drawing color ##
1669 Sets alpha and RGB used when stroking and filling. The color is four floating
1670 point values, unpremultiplied. The color values are interpreted as being in
1671 the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
1672 sRGB color space.
1673
1674 #Param color Unpremultiplied RGBA ##
1675 #Param colorSpace Color_Space describing the encoding of color ##
1676
1677 #ToDo enable and correct example once fiddle picks up setColor4f ##
1678 #Example
1679 SkPaint green1, green2;
1680 green1.setColor4f({0, 1, 0, 1}, nullptr); // R=0 G=1 B=0 A=1
1681 green2.setColor(0xFF00FF00); // A=255 R=0 G=255 B=0
1682 SkDebugf("green1 %c= green2\n", green1 == green2 ? '=' : '!');
1683
1684 #StdOut
1685 green1 == green2
1686 ##
1687 ##
1688
1689 #SeeAlso SkColor setColor setARGB SkColorSetARGB
1690
1691##
1692
Cary Clark8032b982017-07-28 11:04:54 -04001693#Subtopic Alpha_Methods
Cary Clark08895c42018-02-01 09:37:32 -05001694#Line # get and set Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04001695
Cary Clarkffb3d682018-05-17 12:17:28 -04001696Color_Alpha sets the transparency independent of RGB: red, blue, and green.
Cary Clarka90ea222018-10-16 10:30:28 -04001697#Subtopic Alpha_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04001698
1699#Method uint8_t getAlpha() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001700#In Alpha_Methods
1701#Line # returns Color_Alpha, color opacity ##
Cary Clarkce101242017-09-01 15:51:02 -04001702 Retrieves Alpha from the Color used when stroking and filling.
Cary Clark8032b982017-07-28 11:04:54 -04001703
Cary Clarkce101242017-09-01 15:51:02 -04001704 #Return Alpha ranging from zero, fully transparent, to 255, fully opaque ##
Cary Clark8032b982017-07-28 11:04:54 -04001705
1706 #Example
1707 SkPaint paint;
1708 SkDebugf("255 %c= paint.getAlpha()\n", 255 == paint.getAlpha() ? '=' : '!');
1709
1710 #StdOut
1711 255 == paint.getAlpha()
1712 ##
1713 ##
1714
1715##
1716
1717#Method void setAlpha(U8CPU a)
Cary Clarkab2621d2018-01-30 10:08:57 -05001718#In Alpha_Methods
1719#Line # sets Color_Alpha, color opacity ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001720 Replaces Alpha, leaving RGB
Cary Clark8032b982017-07-28 11:04:54 -04001721 unchanged. An out of range value triggers an assert in the debug
1722 build. a is a value from zero to 255.
1723 a set to zero makes Color fully transparent; a set to 255 makes Color
1724 fully opaque.
1725
Cary Clarkce101242017-09-01 15:51:02 -04001726 #Param a Alpha component of Color ##
Cary Clark8032b982017-07-28 11:04:54 -04001727
1728 #Example
1729 SkPaint paint;
1730 paint.setColor(0x00112233);
1731 paint.setAlpha(0x44);
1732 SkDebugf("0x44112233 %c= paint.getColor()\n", 0x44112233 == paint.getColor() ? '=' : '!');
1733
1734 #StdOut
1735 0x44112233 == paint.getColor()
1736 ##
1737 ##
1738
1739##
1740
Cary Clark8032b982017-07-28 11:04:54 -04001741#Method void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Cary Clarkab2621d2018-01-30 10:08:57 -05001742#In Color_Methods
1743#Line # sets color by component ##
Cary Clark8032b982017-07-28 11:04:54 -04001744 Sets Color used when drawing solid fills. The color components range from 0 to 255.
Cary Clarkffb3d682018-05-17 12:17:28 -04001745 The color is Unpremultiplied; Alpha sets the transparency independent of RGB.
Cary Clark8032b982017-07-28 11:04:54 -04001746
1747 #Param a amount of Color_Alpha, from fully transparent (0) to fully opaque (255) ##
Cary Clarkffb3d682018-05-17 12:17:28 -04001748 #Param r amount of red, from no red (0) to full red (255) ##
1749 #Param g amount of green, from no green (0) to full green (255) ##
1750 #Param b amount of blue, from no blue (0) to full blue (255) ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001751
Cary Clark8032b982017-07-28 11:04:54 -04001752 #Example
1753 SkPaint transRed1, transRed2;
1754 transRed1.setARGB(255 / 2, 255, 0, 0);
1755 transRed2.setColor(SkColorSetARGB(255 / 2, 255, 0, 0));
1756 SkDebugf("transRed1 %c= transRed2", transRed1 == transRed2 ? '=' : '!');
1757
1758 #StdOut
1759 transRed1 == transRed2
1760 ##
1761 ##
1762
1763 #SeeAlso setColor SkColorSetARGB
1764
1765##
1766
Cary Clark8032b982017-07-28 11:04:54 -04001767# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001768#Subtopic Style
1769#Line # geometry filling, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04001770
1771Style specifies if the geometry is filled, stroked, or both filled and stroked.
1772Some shapes ignore Style and are always drawn filled or stroked.
1773
Cary Clarka90ea222018-10-16 10:30:28 -04001774#Subtopic Fill
Cary Clark8032b982017-07-28 11:04:54 -04001775Set Style to kFill_Style to fill the shape.
1776The fill covers the area inside the geometry for most shapes.
Cary Clark08895c42018-02-01 09:37:32 -05001777#Subtopic Fill ##
Cary Clark8032b982017-07-28 11:04:54 -04001778
1779#Subtopic Stroke
Cary Clarka90ea222018-10-16 10:30:28 -04001780Set Style to kStroke_Style to stroke the shape.
1781
Cary Clarkbc5697d2017-10-04 14:31:33 -04001782The stroke covers the area described by following the shape edge with a pen or brush of
Cary Clark8032b982017-07-28 11:04:54 -04001783Stroke_Width. The area covered where the shape starts and stops is described by Stroke_Cap.
1784The area covered where the shape turns a corner is described by Stroke_Join.
Cary Clarkbc5697d2017-10-04 14:31:33 -04001785The stroke is centered on the shape; it extends equally on either side of the shape edge.
Cary Clarka90ea222018-10-16 10:30:28 -04001786#Subtopic Stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001787
1788As Stroke_Width gets smaller, the drawn path frame is thinner. Stroke_Width less than one
1789may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visually decrease coverage.
Cary Clarka90ea222018-10-16 10:30:28 -04001790
1791#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
1792#Subtopic Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001793
1794#Subtopic Hairline
Cary Clark8032b982017-07-28 11:04:54 -04001795Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
Herb Derbyfcac00f2018-05-01 11:57:56 -04001796Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
1797flow horizontally, vertically,or diagonally.
Cary Clark8032b982017-07-28 11:04:54 -04001798
Cary Clarkffb3d682018-05-17 12:17:28 -04001799#ToDo what is the description of Anti_Aliased hairlines? ##
Cary Clark8032b982017-07-28 11:04:54 -04001800
1801Path drawing with Hairline may hit the same pixel more than once. For instance, Path containing
1802two lines in one Path_Contour will draw the corner point once, but may both lines may draw the adjacent
1803pixel. If kAntiAlias_Flag is set, transparency is applied twice, resulting in a darker pixel. Some
1804GPU-backed implementations apply transparency at a later drawing stage, avoiding double hit pixels
1805while stroking.
1806
Cary Clarka90ea222018-10-16 10:30:28 -04001807#SeeAlso Path_Fill_Type Path_Effect Style_Fill Style_Stroke
Cary Clark08895c42018-02-01 09:37:32 -05001808#Subtopic Hairline ##
Cary Clark8032b982017-07-28 11:04:54 -04001809
1810#Enum Style
Cary Clark08895c42018-02-01 09:37:32 -05001811#Line # stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001812
1813#Code
Cary Clarka90ea222018-10-16 10:30:28 -04001814#Populate
1815##
Cary Clarkd98f78c2018-04-26 08:32:37 -04001816
Cary Clarka90ea222018-10-16 10:30:28 -04001817#Code
1818#In Constant
1819#Filter kStyle
1820#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001821##
1822
1823Set Style to fill, stroke, or both fill and stroke geometry.
1824The stroke and fill
1825share all paint attributes; for instance, they are drawn with the same color.
1826
1827Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
1828a fill draw.
1829
1830#Const kFill_Style 0
Cary Clark682c58d2018-05-16 07:07:07 -04001831#Line # set to fill geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001832 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clarkce101242017-09-01 15:51:02 -04001833 Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
Cary Clark8032b982017-07-28 11:04:54 -04001834 kFill_Style is set, and ignore the set Style.
1835 The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
1836 and to create an unfilled hole inside the shape.
1837 Style is set to kFill_Style by default.
1838##
1839
1840#Const kStroke_Style 1
Cary Clark682c58d2018-05-16 07:07:07 -04001841#Line # set to stroke geometry ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001842 Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Cary Clark56356312018-02-08 14:45:18 -05001843 Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
Cary Clark8032b982017-07-28 11:04:54 -04001844 and ignore the set Style.
1845 The stroke construction is unaffected by the Path_Fill_Type.
1846##
1847
1848#Const kStrokeAndFill_Style 2
Cary Clark682c58d2018-05-16 07:07:07 -04001849#Line # sets to stroke and fill geometry ##
Cary Clarkce101242017-09-01 15:51:02 -04001850 Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Cary Clark8032b982017-07-28 11:04:54 -04001851 Path is treated as if it is set to SkPath::kWinding_FillType,
Herb Derbyfcac00f2018-05-01 11:57:56 -04001852 and the set Path_Fill_Type is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04001853##
1854
Cary Clark8032b982017-07-28 11:04:54 -04001855#Const kStyleCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04001856#Line # number of different Style values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04001857May be used to verify that Style is a legal value.
1858##
1859
Cary Clarkd98f78c2018-04-26 08:32:37 -04001860#Enum Style ##
Cary Clark8032b982017-07-28 11:04:54 -04001861
1862#Method Style getStyle() const
Cary Clarkab2621d2018-01-30 10:08:57 -05001863#In Style
1864#Line # returns Style: stroke, fill, or both ##
Cary Clark80247e52018-07-11 16:18:41 -04001865 Returns whether the geometry is filled, stroked, or filled and stroked.
Cary Clark8032b982017-07-28 11:04:54 -04001866
1867 #Return one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style ##
1868
1869 #Example
1870 SkPaint paint;
1871 SkDebugf("SkPaint::kFill_Style %c= paint.getStyle()\n",
1872 SkPaint::kFill_Style == paint.getStyle() ? '=' : '!');
1873
1874 #StdOut
1875 SkPaint::kFill_Style == paint.getStyle()
1876 ##
1877 ##
1878
1879#SeeAlso Style setStyle
1880##
1881
1882#Method void setStyle(Style style)
Cary Clarkab2621d2018-01-30 10:08:57 -05001883#In Style
1884#Line # sets Style: stroke, fill, or both ##
Cary Clark8032b982017-07-28 11:04:54 -04001885 Sets whether the geometry is filled, stroked, or filled and stroked.
1886 Has no effect if style is not a legal Style value.
1887
1888 #Param style one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
1889 ##
1890
1891 #Example
1892 void draw(SkCanvas* canvas) {
1893 SkPaint paint;
1894 paint.setStrokeWidth(5);
1895 SkRegion region;
1896 region.op(140, 10, 160, 30, SkRegion::kUnion_Op);
1897 region.op(170, 40, 190, 60, SkRegion::kUnion_Op);
1898 SkBitmap bitmap;
1899 bitmap.setInfo(SkImageInfo::MakeA8(50, 50), 50);
1900 uint8_t pixels[50][50];
1901 for (int x = 0; x < 50; ++x) {
1902 for (int y = 0; y < 50; ++y) {
1903 pixels[y][x] = (x + y) % 5 ? 0xFF : 0x00;
1904 }
1905 }
1906 bitmap.setPixels(pixels);
1907 for (auto style : { SkPaint::kFill_Style,
1908 SkPaint::kStroke_Style,
1909 SkPaint::kStrokeAndFill_Style }) {
1910 paint.setStyle(style);
1911 canvas->drawLine(10, 10, 60, 60, paint);
1912 canvas->drawRect({80, 10, 130, 60}, paint);
1913 canvas->drawRegion(region, paint);
1914 canvas->drawBitmap(bitmap, 200, 10, &paint);
1915 canvas->translate(0, 80);
1916 }
1917 }
1918 ##
1919
1920#SeeAlso Style getStyle
1921##
1922
Cary Clark8032b982017-07-28 11:04:54 -04001923# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001924#Subtopic Stroke_Width
1925#Line # thickness perpendicular to geometry ##
Cary Clark8032b982017-07-28 11:04:54 -04001926
1927Stroke_Width sets the width for stroking. The width is the thickness
Herb Derbyfcac00f2018-05-01 11:57:56 -04001928of the stroke perpendicular to the path direction when the paint style is
Cary Clark8032b982017-07-28 11:04:54 -04001929set to kStroke_Style or kStrokeAndFill_Style.
1930
1931When width is greater than zero, the stroke encompasses as many pixels partially
1932or fully as needed. When the width equals zero, the paint enables hairlines;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001933the stroke is always one pixel wide.
Cary Clark8032b982017-07-28 11:04:54 -04001934
Cary Clarkbc5697d2017-10-04 14:31:33 -04001935The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
Cary Clark8032b982017-07-28 11:04:54 -04001936remains one pixel wide regardless of scaling.
1937
1938The default width for the paint is zero.
1939
1940#Example
1941#Height 170
1942 #Platform raster gpu
1943 #Description
Herb Derbyfcac00f2018-05-01 11:57:56 -04001944 The pixels hit to represent thin lines vary with the angle of the
Cary Clarkbc5697d2017-10-04 14:31:33 -04001945 line and the platform implementation.
Cary Clark8032b982017-07-28 11:04:54 -04001946 ##
1947 void draw(SkCanvas* canvas) {
1948 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04001949 for (bool antialias : { false, true }) {
Cary Clark8032b982017-07-28 11:04:54 -04001950 paint.setAntiAlias(antialias);
1951 for (int width = 0; width <= 4; ++width) {
1952 SkScalar offset = antialias * 100 + width * 20;
1953 paint.setStrokeWidth(width * 0.25f);
1954 canvas->drawLine(10 + offset, 10, 20 + offset, 60, paint);
1955 canvas->drawLine(10 + offset, 110, 60 + offset, 160, paint);
1956 }
1957 }
1958 }
1959##
1960
1961#Method SkScalar getStrokeWidth() const
1962
Cary Clarkab2621d2018-01-30 10:08:57 -05001963#In Stroke_Width
1964#Line # returns thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001965 Returns the thickness of the pen used by Paint to
1966 outline the shape.
1967
1968 #Return zero for Hairline, greater than zero for pen thickness ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04001969
Cary Clark8032b982017-07-28 11:04:54 -04001970 #Example
1971 SkPaint paint;
1972 SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
1973
1974 #StdOut
1975 0 == paint.getStrokeWidth()
1976 ##
1977 ##
1978
1979##
1980
1981#Method void setStrokeWidth(SkScalar width)
1982
Cary Clarkab2621d2018-01-30 10:08:57 -05001983#In Stroke_Width
1984#Line # sets thickness of the stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04001985 Sets the thickness of the pen used by the paint to
Herb Derbyfcac00f2018-05-01 11:57:56 -04001986 outline the shape.
1987 Has no effect if width is less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04001988
Herb Derbyfcac00f2018-05-01 11:57:56 -04001989 #Param width zero thickness for Hairline; greater than zero for pen thickness
Cary Clark8032b982017-07-28 11:04:54 -04001990 ##
1991
1992 #Example
1993 SkPaint paint;
1994 paint.setStrokeWidth(5);
1995 paint.setStrokeWidth(-1);
1996 SkDebugf("5 %c= paint.getStrokeWidth()\n", 5 == paint.getStrokeWidth() ? '=' : '!');
1997
1998 #StdOut
1999 5 == paint.getStrokeWidth()
2000 ##
2001 ##
2002
2003##
2004
Cary Clark08895c42018-02-01 09:37:32 -05002005#Subtopic Stroke_Width ##
Cary Clark8032b982017-07-28 11:04:54 -04002006# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002007#Subtopic Miter_Limit
2008#Line # maximum length of stroked corners ##
Cary Clark8032b982017-07-28 11:04:54 -04002009
2010Miter_Limit specifies the maximum miter length,
2011relative to the stroke width.
2012
2013Miter_Limit is used when the Stroke_Join
2014is set to kMiter_Join, and the Style is either kStroke_Style
2015or kStrokeAndFill_Style.
2016
2017If the miter at a corner exceeds this limit, kMiter_Join
2018is replaced with kBevel_Join.
2019
Cary Clark2be81cf2018-09-13 12:04:30 -04002020Miter_Limit can be computed from the corner angle using:
2021#Formula # miter limit = 1 / sin ( angle / 2 ) ##.
Cary Clark8032b982017-07-28 11:04:54 -04002022
2023Miter_Limit default value is 4.
2024The default may be changed at compile time by setting SkPaintDefaults_MiterLimit
Cary Clarkce101242017-09-01 15:51:02 -04002025in "SkUserConfig.h" or as a define supplied by the build environment.
Cary Clark8032b982017-07-28 11:04:54 -04002026
2027Here are some miter limits and the angles that triggers them.
2028#Table
2029#Legend
2030 # miter limit # angle in degrees ##
2031#Legend ##
2032 # 10 # 11.48 ##
2033 # 9 # 12.76 ##
2034 # 8 # 14.36 ##
2035 # 7 # 16.43 ##
2036 # 6 # 19.19 ##
2037 # 5 # 23.07 ##
2038 # 4 # 28.96 ##
2039 # 3 # 38.94 ##
2040 # 2 # 60 ##
2041 # 1 # 180 ##
2042#Table ##
2043
2044#Example
2045 #Height 170
2046 #Width 384
2047 #Description
2048 This example draws a stroked corner and the miter length beneath.
2049 When the miter limit is decreased slightly, the miter join is replaced
2050 by a bevel join.
2051 ##
2052 void draw(SkCanvas* canvas) {
2053 SkPoint pts[] = {{ 10, 50 }, { 110, 80 }, { 10, 110 }};
2054 SkVector v[] = { pts[0] - pts[1], pts[2] - pts[1] };
2055 SkScalar angle1 = SkScalarATan2(v[0].fY, v[0].fX);
2056 SkScalar angle2 = SkScalarATan2(v[1].fY, v[1].fX);
2057 const SkScalar strokeWidth = 20;
2058 SkScalar miterLimit = 1 / SkScalarSin((angle2 - angle1) / 2);
2059 SkScalar miterLength = strokeWidth * miterLimit;
2060 SkPath path;
2061 path.moveTo(pts[0]);
2062 path.lineTo(pts[1]);
2063 path.lineTo(pts[2]);
2064 SkPaint paint; // set to default kMiter_Join
2065 paint.setAntiAlias(true);
2066 paint.setStyle(SkPaint::kStroke_Style);
2067 paint.setStrokeMiter(miterLimit);
2068 paint.setStrokeWidth(strokeWidth);
2069 canvas->drawPath(path, paint);
2070 paint.setStrokeWidth(1);
2071 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2072 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2073 canvas->translate(200, 0);
2074 miterLimit *= 0.99f;
2075 paint.setStrokeMiter(miterLimit);
2076 paint.setStrokeWidth(strokeWidth);
2077 canvas->drawPath(path, paint);
2078 paint.setStrokeWidth(1);
2079 canvas->drawLine(pts[1].fX - miterLength / 2, pts[1].fY + 50,
2080 pts[1].fX + miterLength / 2, pts[1].fY + 50, paint);
2081 }
2082##
2083
2084#Method SkScalar getStrokeMiter() const
2085
Cary Clarkab2621d2018-01-30 10:08:57 -05002086#In Miter_Limit
2087#Line # returns Miter_Limit, angles with sharp corners ##
Cary Clark80247e52018-07-11 16:18:41 -04002088 Returns the limit at which a sharp corner is drawn beveled.
Cary Clark8032b982017-07-28 11:04:54 -04002089
2090 #Return zero and greater Miter_Limit ##
2091
2092 #Example
2093 SkPaint paint;
2094 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2095
2096 #StdOut
2097 default miter limit == 4
2098 ##
2099 ##
2100
2101 #SeeAlso Miter_Limit setStrokeMiter Join
2102
2103##
2104
2105#Method void setStrokeMiter(SkScalar miter)
2106
Cary Clarkab2621d2018-01-30 10:08:57 -05002107#In Miter_Limit
2108#Line # sets Miter_Limit, angles with sharp corners ##
Cary Clark80247e52018-07-11 16:18:41 -04002109 Sets the limit at which a sharp corner is drawn beveled.
Cary Clark8032b982017-07-28 11:04:54 -04002110 Valid values are zero and greater.
2111 Has no effect if miter is less than zero.
2112
2113 #Param miter zero and greater Miter_Limit
2114 ##
2115
2116 #Example
2117 SkPaint paint;
2118 paint.setStrokeMiter(8);
2119 paint.setStrokeMiter(-1);
2120 SkDebugf("default miter limit == %g\n", paint.getStrokeMiter());
2121
2122 #StdOut
2123 default miter limit == 8
2124 ##
2125 ##
2126
2127 #SeeAlso Miter_Limit getStrokeMiter Join
2128
2129##
2130
Cary Clark08895c42018-02-01 09:37:32 -05002131#Subtopic Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002132# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002133#Subtopic Stroke_Cap
2134#Line # decorations at ends of open strokes ##
Cary Clarka90ea222018-10-16 10:30:28 -04002135#Subtopic Stroke_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002136
2137#Enum Cap
Cary Clark08895c42018-02-01 09:37:32 -05002138#Line # start and end geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002139
2140#Code
Cary Clarka90ea222018-10-16 10:30:28 -04002141#Populate
2142##
Cary Clark8032b982017-07-28 11:04:54 -04002143
Cary Clarka90ea222018-10-16 10:30:28 -04002144#Code
2145#In Constant
2146#Filter kCap
2147#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002148##
2149
2150Stroke_Cap draws at the beginning and end of an open Path_Contour.
2151
2152 #Const kButt_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04002153 #Line # no stroke extension ##
Cary Clark8032b982017-07-28 11:04:54 -04002154 Does not extend the stroke past the beginning or the end.
2155 ##
2156 #Const kRound_Cap 1
Cary Clark682c58d2018-05-16 07:07:07 -04002157 #Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04002158 Adds a circle with a diameter equal to Stroke_Width at the beginning
2159 and end.
2160 ##
2161 #Const kSquare_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04002162 #Line # adds square ##
Cary Clark8032b982017-07-28 11:04:54 -04002163 Adds a square with sides equal to Stroke_Width at the beginning
2164 and end. The square sides are parallel to the initial and final direction
2165 of the stroke.
2166 ##
2167 #Const kLast_Cap 2
Cary Clark682c58d2018-05-16 07:07:07 -04002168 #Line # largest Stroke_Cap value ##
Cary Clark8032b982017-07-28 11:04:54 -04002169 Equivalent to the largest value for Stroke_Cap.
2170 ##
2171 #Const kDefault_Cap 0
Cary Clark682c58d2018-05-16 07:07:07 -04002172 #Line # equivalent to kButt_Cap ##
Cary Clark8032b982017-07-28 11:04:54 -04002173 Stroke_Cap is set to kButt_Cap by default.
2174 ##
2175
2176 #Const kCapCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04002177 #Line # number of different Stroke_Cap values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04002178 May be used to verify that Stroke_Cap is a legal value.
2179 ##
2180#Enum ##
2181
Herb Derbyfcac00f2018-05-01 11:57:56 -04002182Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002183follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002184
2185If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
2186visible beginning and end.
2187
2188Path_Contour may start and end at the same point; defining Zero_Length_Contour.
2189
2190kButt_Cap and Zero_Length_Contour is not drawn.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002191kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
Cary Clark8032b982017-07-28 11:04:54 -04002192at the contour point.
2193kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
2194Stroke_Width at the contour point.
2195
2196Stroke_Cap is kButt_Cap by default.
2197
2198#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002199#Height 200
Cary Clark8032b982017-07-28 11:04:54 -04002200 SkPaint paint;
2201 paint.setStyle(SkPaint::kStroke_Style);
2202 paint.setStrokeWidth(20);
2203 SkPath path;
2204 path.moveTo(30, 30);
2205 path.lineTo(30, 30);
2206 path.moveTo(70, 30);
2207 path.lineTo(90, 40);
2208 for (SkPaint::Cap c : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap } ) {
2209 paint.setStrokeCap(c);
2210 canvas->drawPath(path, paint);
2211 canvas->translate(0, 70);
2212 }
2213##
2214
2215#Method Cap getStrokeCap() const
2216
Cary Clarkab2621d2018-01-30 10:08:57 -05002217#In Stroke_Cap
2218#Line # returns Cap, the area drawn at path ends ##
Cary Clark80247e52018-07-11 16:18:41 -04002219 Returns the geometry drawn at the beginning and end of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002220
2221 #Return one of: kButt_Cap, kRound_Cap, kSquare_Cap ##
2222
2223 #Example
2224 SkPaint paint;
2225 SkDebugf("kButt_Cap %c= default stroke cap\n",
2226 SkPaint::kButt_Cap == paint.getStrokeCap() ? '=' : '!');
2227
2228 #StdOut
2229 kButt_Cap == default stroke cap
2230 ##
2231 ##
2232
2233 #SeeAlso Stroke_Cap setStrokeCap
2234##
2235
2236#Method void setStrokeCap(Cap cap)
2237
Cary Clarkab2621d2018-01-30 10:08:57 -05002238#In Stroke_Cap
2239#Line # sets Cap, the area drawn at path ends ##
Cary Clark80247e52018-07-11 16:18:41 -04002240 Sets the geometry drawn at the beginning and end of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002241
2242 #Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
2243 has no effect if cap is not valid
Herb Derbyfcac00f2018-05-01 11:57:56 -04002244 ##
Cary Clark8032b982017-07-28 11:04:54 -04002245
2246 #Example
2247 SkPaint paint;
2248 paint.setStrokeCap(SkPaint::kRound_Cap);
2249 paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
2250 SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
2251 SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
Herb Derbyfcac00f2018-05-01 11:57:56 -04002252
Cary Clark8032b982017-07-28 11:04:54 -04002253 #StdOut
2254 kRound_Cap == paint.getStrokeCap()
2255 ##
2256 ##
2257
2258 #SeeAlso Stroke_Cap getStrokeCap
2259##
2260
Cary Clark8032b982017-07-28 11:04:54 -04002261# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002262#Subtopic Stroke_Join
2263#Line # decoration at corners of strokes ##
Cary Clarka90ea222018-10-16 10:30:28 -04002264#Subtopic Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002265
2266Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
2267
Herb Derbyfcac00f2018-05-01 11:57:56 -04002268Stroke describes the area covered by a pen of Stroke_Width as it
Cary Clarkbc5697d2017-10-04 14:31:33 -04002269follows the Path_Contour, moving parallel to the contour direction.
Cary Clark8032b982017-07-28 11:04:54 -04002270
2271If the contour direction changes abruptly, because the tangent direction leading
2272to the end of a curve within the contour does not match the tangent direction of
2273the following curve, the pair of curves meet at Stroke_Join.
2274
2275#Example
Cary Clark2ade9972017-11-02 17:49:34 -04002276#Height 200
Cary Clarka560c472017-11-27 10:44:06 -05002277 SkPaint paint;
2278 paint.setStyle(SkPaint::kStroke_Style);
2279 paint.setStrokeWidth(20);
2280 SkPath path;
2281 path.moveTo(30, 20);
2282 path.lineTo(40, 40);
2283 path.conicTo(70, 20, 100, 20, .707f);
2284 for (SkPaint::Join j : { SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join } ) {
2285 paint.setStrokeJoin(j);
2286 canvas->drawPath(path, paint);
2287 canvas->translate(0, 70);
2288 }
Cary Clark8032b982017-07-28 11:04:54 -04002289##
2290
2291#Enum Join
Cary Clark08895c42018-02-01 09:37:32 -05002292#Line # corner geometry on stroked shapes ##
Cary Clark8032b982017-07-28 11:04:54 -04002293#Code
Cary Clarka90ea222018-10-16 10:30:28 -04002294#Populate
2295##
Cary Clark8032b982017-07-28 11:04:54 -04002296
Cary Clarka90ea222018-10-16 10:30:28 -04002297#Code
2298#In Constant
2299#Filter kJoin
2300#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002301##
2302
Cary Clark1eace2d2017-07-31 07:52:43 -04002303Join specifies how corners are drawn when a shape is stroked. Join
Cary Clark8032b982017-07-28 11:04:54 -04002304affects the four corners of a stroked rectangle, and the connected segments in a
2305stroked path.
2306
2307Choose miter join to draw sharp corners. Choose round join to draw a circle with a
2308radius equal to the stroke width on top of the corner. Choose bevel join to minimally
2309connect the thick strokes.
2310
Herb Derbyfcac00f2018-05-01 11:57:56 -04002311The fill path constructed to describe the stroked path respects the join setting but may
Cary Clark8032b982017-07-28 11:04:54 -04002312not contain the actual join. For instance, a fill path constructed with round joins does
2313not necessarily include circles at each connected segment.
2314
2315#Const kMiter_Join 0
Cary Clark682c58d2018-05-16 07:07:07 -04002316#Line # extends to Miter_Limit ##
Cary Clark8032b982017-07-28 11:04:54 -04002317 Extends the outside corner to the extent allowed by Miter_Limit.
2318 If the extension exceeds Miter_Limit, kBevel_Join is used instead.
2319##
2320
2321#Const kRound_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04002322#Line # adds circle ##
Cary Clark8032b982017-07-28 11:04:54 -04002323 Adds a circle with a diameter of Stroke_Width at the sharp corner.
2324##
2325
2326#Const kBevel_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04002327#Line # connects outside edges ##
Cary Clark8032b982017-07-28 11:04:54 -04002328 Connects the outside edges of the sharp corner.
2329##
2330
2331#Const kLast_Join 2
Cary Clark682c58d2018-05-16 07:07:07 -04002332#Line # equivalent to the largest value for Stroke_Join ##
Cary Clark8032b982017-07-28 11:04:54 -04002333##
2334
2335#Const kDefault_Join 1
Cary Clark682c58d2018-05-16 07:07:07 -04002336#Line # equivalent to kMiter_Join ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002337 Stroke_Join is set to kMiter_Join by default.
Cary Clark8032b982017-07-28 11:04:54 -04002338##
2339
2340#Const kJoinCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04002341#Line # number of different Stroke_Join values defined ##
Cary Clark8032b982017-07-28 11:04:54 -04002342 May be used to verify that Stroke_Join is a legal value.
2343##
2344
2345#Example
2346#Width 462
2347void draw(SkCanvas* canvas) {
2348 SkPath path;
2349 path.moveTo(10, 50);
2350 path.quadTo(35, 110, 60, 210);
2351 path.quadTo(105, 110, 130, 10);
2352 SkPaint paint; // set to default kMiter_Join
2353 paint.setAntiAlias(true);
2354 paint.setStyle(SkPaint::kStroke_Style);
2355 paint.setStrokeWidth(20);
2356 canvas->drawPath(path, paint);
2357 canvas->translate(150, 0);
2358 paint.setStrokeJoin(SkPaint::kBevel_Join);
2359 canvas->drawPath(path, paint);
2360 canvas->translate(150, 0);
2361 paint.setStrokeJoin(SkPaint::kRound_Join);
2362 canvas->drawPath(path, paint);
2363}
2364##
2365
2366#SeeAlso setStrokeJoin getStrokeJoin setStrokeMiter getStrokeMiter
2367
2368#Enum ##
2369
2370#Method Join getStrokeJoin() const
2371
Cary Clarkab2621d2018-01-30 10:08:57 -05002372#In Stroke_Join
2373#Line # returns Join, geometry on path corners ##
Cary Clark80247e52018-07-11 16:18:41 -04002374 Returns the geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002375
2376 #Return one of: kMiter_Join, kRound_Join, kBevel_Join ##
2377
2378 #Example
2379 SkPaint paint;
2380 SkDebugf("kMiter_Join %c= default stroke join\n",
2381 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2382
2383 #StdOut
2384 kMiter_Join == default stroke join
2385 ##
2386 ##
2387
2388 #SeeAlso Stroke_Join setStrokeJoin
2389##
2390
2391#Method void setStrokeJoin(Join join)
2392
Cary Clarkab2621d2018-01-30 10:08:57 -05002393#In Stroke_Join
2394#Line # sets Join, geometry on path corners ##
Cary Clark80247e52018-07-11 16:18:41 -04002395 Sets the geometry drawn at the corners of strokes.
Cary Clark8032b982017-07-28 11:04:54 -04002396
2397 #Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002398 otherwise, has no effect
Cary Clark8032b982017-07-28 11:04:54 -04002399 ##
2400
2401 #Example
2402 SkPaint paint;
2403 paint.setStrokeJoin(SkPaint::kMiter_Join);
2404 paint.setStrokeJoin((SkPaint::Join) SkPaint::kJoinCount);
2405 SkDebugf("kMiter_Join %c= paint.getStrokeJoin()\n",
2406 SkPaint::kMiter_Join == paint.getStrokeJoin() ? '=' : '!');
2407
2408 #StdOut
2409 kMiter_Join == paint.getStrokeJoin()
2410 ##
2411 ##
2412
2413 #SeeAlso Stroke_Join getStrokeJoin
2414##
2415
2416#SeeAlso Miter_Limit
2417
Cary Clark8032b982017-07-28 11:04:54 -04002418# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002419#Subtopic Fill_Path
2420#Line # make Path from Path_Effect, stroking ##
Cary Clark8032b982017-07-28 11:04:54 -04002421
2422Fill_Path creates a Path by applying the Path_Effect, followed by the Style_Stroke.
2423
2424If Paint contains Path_Effect, Path_Effect operates on the source Path; the result
2425replaces the destination Path. Otherwise, the source Path is replaces the
2426destination Path.
2427
2428Fill Path can request the Path_Effect to restrict to a culling rectangle, but
2429the Path_Effect is not required to do so.
2430
Herb Derbyfcac00f2018-05-01 11:57:56 -04002431If Style is kStroke_Style or kStrokeAndFill_Style,
Cary Clark8032b982017-07-28 11:04:54 -04002432and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
2433and Miter_Limit operate on the destination Path, replacing it.
2434
Herb Derbyfcac00f2018-05-01 11:57:56 -04002435Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
Cary Clark8032b982017-07-28 11:04:54 -04002436
2437If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
2438returns false since Hairline has no filled equivalent.
2439
Cary Clarka90ea222018-10-16 10:30:28 -04002440#SeeAlso Style_Stroke Stroke_Width Path_Effect
2441
2442#Subtopic Fill_Path ##
2443
Cary Clark8032b982017-07-28 11:04:54 -04002444#Method bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2445 SkScalar resScale = 1) const
Cary Clarkab2621d2018-01-30 10:08:57 -05002446#In Fill_Path
2447#Line # returns fill path equivalent to stroke ##
Cary Clark8032b982017-07-28 11:04:54 -04002448
Cary Clark80247e52018-07-11 16:18:41 -04002449 Returns the filled equivalent of the stroked path.
Cary Clark8032b982017-07-28 11:04:54 -04002450
2451 #Param src Path read to create a filled version ##
2452 #Param dst resulting Path; may be the same as src, but may not be nullptr ##
2453 #Param cullRect optional limit passed to Path_Effect ##
2454 #Param resScale if > 1, increase precision, else if (0 < res < 1) reduce precision
2455 to favor speed and size
2456 ##
2457 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2458
2459 #Example
2460 #Height 192
2461 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002462 A very small Quad stroke is turned into a filled path with increasing levels of precision.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002463 At the lowest precision, the Quad stroke is approximated by a rectangle.
Cary Clark8032b982017-07-28 11:04:54 -04002464 At the highest precision, the filled path has high fidelity compared to the original stroke.
2465 ##
2466 void draw(SkCanvas* canvas) {
2467 SkPaint strokePaint;
2468 strokePaint.setAntiAlias(true);
2469 strokePaint.setStyle(SkPaint::kStroke_Style);
2470 strokePaint.setStrokeWidth(.1f);
2471 SkPath strokePath;
2472 strokePath.moveTo(.08f, .08f);
2473 strokePath.quadTo(.09f, .08f, .17f, .17f);
2474 SkPath fillPath;
2475 SkPaint outlinePaint(strokePaint);
2476 outlinePaint.setStrokeWidth(2);
2477 SkMatrix scale = SkMatrix::MakeScale(300, 300);
2478 for (SkScalar precision : { 0.01f, .1f, 1.f, 10.f, 100.f } ) {
2479 strokePaint.getFillPath(strokePath, &fillPath, nullptr, precision);
2480 fillPath.transform(scale);
2481 canvas->drawPath(fillPath, outlinePaint);
2482 canvas->translate(60, 0);
2483 if (1.f == precision) canvas->translate(-180, 100);
2484 }
2485 strokePath.transform(scale);
2486 strokePaint.setStrokeWidth(30);
2487 canvas->drawPath(strokePath, strokePaint);
2488 }
2489 ##
2490
2491##
2492
2493#Method bool getFillPath(const SkPath& src, SkPath* dst) const
2494
Cary Clarkab2621d2018-01-30 10:08:57 -05002495#In Fill_Path
Cary Clark80247e52018-07-11 16:18:41 -04002496 Returns the filled equivalent of the stroked path.
Cary Clark8032b982017-07-28 11:04:54 -04002497
2498 Replaces dst with the src path modified by Path_Effect and Style_Stroke.
2499 Path_Effect, if any, is not culled. Stroke_Width is created with default precision.
2500
2501 #Param src Path read to create a filled version ##
2502 #Param dst resulting Path dst may be the same as src, but may not be nullptr ##
2503 #Return true if the path represents Style_Fill, or false if it represents Hairline ##
2504
2505 #Example
2506 #Height 128
2507 void draw(SkCanvas* canvas) {
2508 SkPaint paint;
2509 paint.setStyle(SkPaint::kStroke_Style);
2510 paint.setStrokeWidth(10);
2511 SkPath strokePath;
2512 strokePath.moveTo(20, 20);
2513 strokePath.lineTo(100, 100);
2514 canvas->drawPath(strokePath, paint);
2515 SkPath fillPath;
2516 paint.getFillPath(strokePath, &fillPath);
2517 paint.setStrokeWidth(2);
2518 canvas->translate(40, 0);
2519 canvas->drawPath(fillPath, paint);
2520 }
2521 ##
2522
2523##
2524
Cary Clark8032b982017-07-28 11:04:54 -04002525# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002526#Subtopic Shader_Methods
2527#Line # get and set Shader ##
Cary Clark8032b982017-07-28 11:04:54 -04002528
2529Shader defines the colors used when drawing a shape.
2530Shader may be an image, a gradient, or a computed fill.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002531If Paint has no Shader, then Color fills the shape.
Cary Clark8032b982017-07-28 11:04:54 -04002532
2533Shader is modulated by Color_Alpha component of Color.
2534If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
2535the fill.
2536
2537The drawn transparency can be modified without altering Shader, by changing Color_Alpha.
2538
2539#Example
2540void draw(SkCanvas* canvas) {
2541 SkPaint paint;
2542 SkPoint center = { 50, 50 };
2543 SkScalar radius = 50;
2544 const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 };
2545 paint.setShader(SkGradientShader::MakeRadial(center, radius, colors,
2546 nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode));
2547 for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) {
2548 paint.setAlpha((int) (a * 255));
2549 canvas->drawCircle(center.fX, center.fY, radius, paint);
2550 canvas->translate(70, 70);
2551 }
2552}
2553##
2554
2555If Shader generates only Color_Alpha then all components of Color modulate the output.
2556
2557#Example
2558void draw(SkCanvas* canvas) {
2559 SkPaint paint;
2560 SkBitmap bitmap;
2561 bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
2562 uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
2563 bitmap.setPixels(pixels);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002564 paint.setShader(SkShader::MakeBitmapShader(bitmap,
Cary Clark8032b982017-07-28 11:04:54 -04002565 SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
2566 for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
2567 paint.setColor(c); // all components in color affect shader
2568 canvas->drawCircle(50, 50, 50, paint);
2569 canvas->translate(70, 70);
2570 }
2571}
2572##
2573
2574#Method SkShader* getShader() const
2575
Cary Clarkab2621d2018-01-30 10:08:57 -05002576#In Shader_Methods
2577#Line # returns Shader, multiple drawing colors; gradients ##
Cary Clark80247e52018-07-11 16:18:41 -04002578 Returns optional colors used when filling a path, such as a gradient.
Cary Clark8032b982017-07-28 11:04:54 -04002579
2580 Does not alter Shader Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002581
Cary Clark8032b982017-07-28 11:04:54 -04002582 #Return Shader if previously set, nullptr otherwise ##
2583
2584 #Example
2585 void draw(SkCanvas* canvas) {
2586 SkPaint paint;
2587 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2588 paint.setShader(SkShader::MakeEmptyShader());
2589 SkDebugf("nullptr %c= shader\n", paint.getShader() ? '!' : '=');
2590 }
2591
2592 #StdOut
2593 nullptr == shader
2594 nullptr != shader
2595 ##
2596 ##
2597
2598##
2599
2600#Method sk_sp<SkShader> refShader() const
2601
Cary Clarkab2621d2018-01-30 10:08:57 -05002602#In Shader_Methods
2603#Line # references Shader, multiple drawing colors; gradients ##
Cary Clark80247e52018-07-11 16:18:41 -04002604 Returns optional colors used when filling a path, such as a gradient.
Cary Clark8032b982017-07-28 11:04:54 -04002605
2606 Increases Shader Reference_Count by one.
2607
2608 #Return Shader if previously set, nullptr otherwise ##
2609
2610 #Example
2611 void draw(SkCanvas* canvas) {
2612 SkPaint paint1, paint2;
2613 paint1.setShader(SkShader::MakeEmptyShader());
2614 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2615 paint2.setShader(paint1.refShader());
2616 SkDebugf("shader unique: %s\n", paint1.getShader()->unique() ? "true" : "false");
2617 }
2618
2619 #StdOut
2620 shader unique: true
2621 shader unique: false
2622 ##
2623 ##
2624
2625##
2626
2627#Method void setShader(sk_sp<SkShader> shader)
2628
Cary Clarkab2621d2018-01-30 10:08:57 -05002629#In Shader_Methods
2630#Line # sets Shader, multiple drawing colors; gradients ##
Cary Clark80247e52018-07-11 16:18:41 -04002631 Sets optional colors used when filling a path, such as a gradient.
Cary Clark8032b982017-07-28 11:04:54 -04002632
Cary Clarkd0530ba2017-09-14 11:25:39 -04002633 Sets Shader to shader, decreasing Reference_Count of the previous Shader.
Cary Clark6fc50412017-09-21 12:31:06 -04002634 Increments shader Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002635
2636 #Param shader how geometry is filled with color; if nullptr, Color is used instead ##
2637
2638 #Example
2639 #Height 64
2640 void draw(SkCanvas* canvas) {
2641 SkPaint paint;
2642 paint.setColor(SK_ColorBLUE);
2643 paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
2644 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2645 paint.setShader(nullptr);
2646 canvas->translate(50, 0);
2647 canvas->drawRect(SkRect::MakeWH(40, 40), paint);
2648 }
2649 ##
2650
2651##
2652
Cary Clark08895c42018-02-01 09:37:32 -05002653#Subtopic Shader_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002654# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002655#Subtopic Color_Filter_Methods
2656#Line # get and set Color_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002657
2658Color_Filter alters the color used when drawing a shape.
2659Color_Filter may apply Blend_Mode, transform the color through a matrix, or composite multiple filters.
2660If Paint has no Color_Filter, the color is unaltered.
2661
2662The drawn transparency can be modified without altering Color_Filter, by changing Color_Alpha.
2663
2664#Example
2665#Height 128
2666void draw(SkCanvas* canvas) {
2667 SkPaint paint;
2668 paint.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(0xFFFFFF, 0xFF0000));
2669 for (SkColor c : { SK_ColorBLACK, SK_ColorGREEN } ) {
2670 paint.setColor(c);
2671 canvas->drawRect(SkRect::MakeXYWH(10, 10, 50, 50), paint);
2672 paint.setAlpha(0x80);
2673 canvas->drawRect(SkRect::MakeXYWH(60, 60, 50, 50), paint);
2674 canvas->translate(100, 0);
2675 }
2676}
2677##
2678
2679#Method SkColorFilter* getColorFilter() const
2680
Cary Clarkab2621d2018-01-30 10:08:57 -05002681#In Color_Filter_Methods
2682#Line # returns Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002683 Returns Color_Filter if set, or nullptr.
2684 Does not alter Color_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002685
Cary Clark8032b982017-07-28 11:04:54 -04002686 #Return Color_Filter if previously set, nullptr otherwise ##
2687
2688 #Example
2689 void draw(SkCanvas* canvas) {
2690 SkPaint paint;
2691 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2692 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2693 SkDebugf("nullptr %c= color filter\n", paint.getColorFilter() ? '!' : '=');
2694 }
2695
2696 #StdOut
2697 nullptr == color filter
2698 nullptr != color filter
2699 ##
2700 ##
2701##
2702
2703#Method sk_sp<SkColorFilter> refColorFilter() const
2704
Cary Clarkab2621d2018-01-30 10:08:57 -05002705#In Color_Filter_Methods
2706#Line # references Color_Filter, how colors are altered ##
Cary Clark8032b982017-07-28 11:04:54 -04002707 Returns Color_Filter if set, or nullptr.
2708 Increases Color_Filter Reference_Count by one.
2709
2710 #Return Color_Filter if set, or nullptr ##
2711
2712 #Example
2713 void draw(SkCanvas* canvas) {
2714 SkPaint paint1, paint2;
2715 paint1.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
2716 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2717 paint2.setColorFilter(paint1.refColorFilter());
2718 SkDebugf("color filter unique: %s\n", paint1.getColorFilter()->unique() ? "true" : "false");
2719 }
2720
2721 #StdOut
2722 color filter unique: true
2723 color filter unique: false
2724 ##
2725 ##
2726##
2727
2728#Method void setColorFilter(sk_sp<SkColorFilter> colorFilter)
2729
Cary Clarkab2621d2018-01-30 10:08:57 -05002730#In Color_Filter_Methods
2731#Line # sets Color_Filter, alters color ##
Cary Clark6fc50412017-09-21 12:31:06 -04002732Sets Color_Filter to filter, decreasing Reference_Count of the previous
2733Color_Filter. Pass nullptr to clear Color_Filter.
2734
2735Increments filter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002736
2737 #Param colorFilter Color_Filter to apply to subsequent draw ##
2738
2739 #Example
2740 #Height 64
2741 void draw(SkCanvas* canvas) {
2742 SkPaint paint;
2743 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorLTGRAY, SkBlendMode::kSrcIn));
2744 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2745 paint.setColorFilter(nullptr);
2746 canvas->translate(70, 0);
2747 canvas->drawRect(SkRect::MakeWH(50, 50), paint);
2748 }
2749 ##
2750
2751##
2752
Cary Clark08895c42018-02-01 09:37:32 -05002753#Subtopic Color_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002754# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002755#Subtopic Blend_Mode_Methods
2756#Line # get and set Blend_Mode ##
Cary Clark8032b982017-07-28 11:04:54 -04002757
2758Blend_Mode describes how Color combines with the destination color.
2759The default setting, SkBlendMode::kSrcOver, draws the source color
2760over the destination color.
2761
2762#Example
2763void draw(SkCanvas* canvas) {
2764 SkPaint normal, blender;
2765 normal.setColor(0xFF58a889);
2766 blender.setColor(0xFF8958a8);
2767 canvas->clear(0);
2768 for (SkBlendMode m : { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn, SkBlendMode::kSrcOut } ) {
2769 normal.setBlendMode(SkBlendMode::kSrcOver);
2770 canvas->drawOval(SkRect::MakeXYWH(30, 30, 30, 80), normal);
2771 blender.setBlendMode(m);
2772 canvas->drawOval(SkRect::MakeXYWH(10, 50, 80, 30), blender);
2773 canvas->translate(70, 70);
2774 }
2775}
2776##
2777
2778#SeeAlso Blend_Mode
2779
2780#Method SkBlendMode getBlendMode() const
2781
Cary Clarkab2621d2018-01-30 10:08:57 -05002782#In Blend_Mode_Methods
2783#Line # returns Blend_Mode, how colors combine with Device ##
Cary Clark8032b982017-07-28 11:04:54 -04002784 Returns Blend_Mode.
Cary Clark579985c2017-07-31 11:48:27 -04002785 By default, returns SkBlendMode::kSrcOver.
Cary Clark8032b982017-07-28 11:04:54 -04002786
2787 #Return mode used to combine source color with destination color ##
2788
2789 #Example
2790 void draw(SkCanvas* canvas) {
2791 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04002792 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002793 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2794 paint.setBlendMode(SkBlendMode::kSrc);
Herb Derbyfcac00f2018-05-01 11:57:56 -04002795 SkDebugf("kSrcOver %c= getBlendMode\n",
Cary Clark8032b982017-07-28 11:04:54 -04002796 SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
2797 }
2798
2799 #StdOut
2800 kSrcOver == getBlendMode
2801 kSrcOver != getBlendMode
2802 ##
2803 ##
2804
2805##
2806
2807#Method bool isSrcOver() const
2808
Cary Clarkab2621d2018-01-30 10:08:57 -05002809#In Blend_Mode_Methods
2810#Line # returns true if Blend_Mode is SkBlendMode::kSrcOver ##
Cary Clark8032b982017-07-28 11:04:54 -04002811 Returns true if Blend_Mode is SkBlendMode::kSrcOver, the default.
2812
2813 #Return true if Blend_Mode is SkBlendMode::kSrcOver ##
2814
2815 #Example
2816 void draw(SkCanvas* canvas) {
2817 SkPaint paint;
2818 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2819 paint.setBlendMode(SkBlendMode::kSrc);
2820 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2821 }
2822
2823 #StdOut
2824 isSrcOver == true
2825 isSrcOver != true
2826 ##
2827 ##
2828
2829##
2830
2831#Method void setBlendMode(SkBlendMode mode)
2832
Cary Clarkab2621d2018-01-30 10:08:57 -05002833#In Blend_Mode_Methods
2834#Line # sets Blend_Mode, how colors combine with destination ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04002835 Sets Blend_Mode to mode.
Cary Clark8032b982017-07-28 11:04:54 -04002836 Does not check for valid input.
2837
2838 #Param mode SkBlendMode used to combine source color and destination ##
2839
2840 #Example
2841 void draw(SkCanvas* canvas) {
2842 SkPaint paint;
2843 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2844 paint.setBlendMode(SkBlendMode::kSrc);
2845 SkDebugf("isSrcOver %c= true\n", paint.isSrcOver() ? '=' : '!');
2846 }
2847
2848 #StdOut
2849 isSrcOver == true
2850 isSrcOver != true
2851 ##
2852 ##
2853
2854##
2855
Cary Clark08895c42018-02-01 09:37:32 -05002856#Subtopic Blend_Mode_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002857# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002858#Subtopic Path_Effect_Methods
2859#Line # get and set Path_Effect ##
Cary Clark8032b982017-07-28 11:04:54 -04002860
2861Path_Effect modifies the path geometry before drawing it.
2862Path_Effect may implement dashing, custom fill effects and custom stroke effects.
2863If Paint has no Path_Effect, the path geometry is unaltered when filled or stroked.
2864
2865#Example
2866#Height 160
2867 void draw(SkCanvas* canvas) {
2868 SkPaint paint;
2869 paint.setStyle(SkPaint::kStroke_Style);
2870 paint.setStrokeWidth(16);
2871 SkScalar intervals[] = {30, 10};
2872 paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));
2873 canvas->drawRoundRect({20, 20, 120, 120}, 20, 20, paint);
2874 }
2875##
2876
2877#SeeAlso Path_Effect
2878
2879#Method SkPathEffect* getPathEffect() const
2880
Cary Clarkab2621d2018-01-30 10:08:57 -05002881#In Path_Effect_Methods
2882#Line # returns Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002883 Returns Path_Effect if set, or nullptr.
2884 Does not alter Path_Effect Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002885
Cary Clark8032b982017-07-28 11:04:54 -04002886 #Return Path_Effect if previously set, nullptr otherwise ##
2887
2888 #Example
2889 void draw(SkCanvas* canvas) {
2890 SkPaint paint;
2891 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2892 paint.setPathEffect(SkCornerPathEffect::Make(10));
2893 SkDebugf("nullptr %c= path effect\n", paint.getPathEffect() ? '!' : '=');
2894 }
2895
2896 #StdOut
2897 nullptr == path effect
2898 nullptr != path effect
2899 ##
2900 ##
2901
2902##
2903
2904
2905#Method sk_sp<SkPathEffect> refPathEffect() const
2906
Cary Clarkab2621d2018-01-30 10:08:57 -05002907#In Path_Effect_Methods
2908#Line # references Path_Effect, modifications to path geometry; dashing ##
Cary Clark8032b982017-07-28 11:04:54 -04002909 Returns Path_Effect if set, or nullptr.
2910 Increases Path_Effect Reference_Count by one.
2911
2912 #Return Path_Effect if previously set, nullptr otherwise ##
2913
2914 #Example
2915 void draw(SkCanvas* canvas) {
2916 SkPaint paint1, paint2;
Cary Clarka560c472017-11-27 10:44:06 -05002917 SkScalar intervals[] = {1, 2};
2918 paint1.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 10));
Cary Clark8032b982017-07-28 11:04:54 -04002919 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2920 paint2.setPathEffect(paint1.refPathEffect());
2921 SkDebugf("path effect unique: %s\n", paint1.getPathEffect()->unique() ? "true" : "false");
2922 }
2923
2924 #StdOut
2925 path effect unique: true
2926 path effect unique: false
2927 ##
2928 ##
2929
2930##
2931
2932
2933#Method void setPathEffect(sk_sp<SkPathEffect> pathEffect)
2934
Cary Clarkab2621d2018-01-30 10:08:57 -05002935#In Path_Effect_Methods
2936#Line # sets Path_Effect, modifications to path geometry; dashing ##
Cary Clark6fc50412017-09-21 12:31:06 -04002937Sets Path_Effect to pathEffect, decreasing Reference_Count of the previous
2938Path_Effect. Pass nullptr to leave the path geometry unaltered.
2939
2940Increments pathEffect Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04002941
2942 #Param pathEffect replace Path with a modification when drawn ##
2943
2944 #Example
2945 void draw(SkCanvas* canvas) {
2946 SkPaint paint;
2947 paint.setPathEffect(SkDiscretePathEffect::Make(3, 5));
2948 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2949 }
2950 ##
2951
2952##
2953
Cary Clark08895c42018-02-01 09:37:32 -05002954#Subtopic Path_Effect_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04002955# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002956#Subtopic Mask_Filter_Methods
2957#Line # get and set Mask_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04002958
Cary Clarkce101242017-09-01 15:51:02 -04002959Mask_Filter uses coverage of the shape drawn to create Mask_Alpha.
Mike Reed8ad91a92018-01-19 19:09:32 -05002960Mask_Filter takes a Mask, and returns a Mask.
Cary Clark6fc50412017-09-21 12:31:06 -04002961
2962Mask_Filter may change the geometry and transparency of the shape, such as
2963creating a blur effect. Set Mask_Filter to nullptr to prevent Mask_Filter from
2964modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04002965
2966#Example
2967 void draw(SkCanvas* canvas) {
2968 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04002969 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04002970 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
2971 }
2972##
2973
2974#Method SkMaskFilter* getMaskFilter() const
2975
Cary Clarkab2621d2018-01-30 10:08:57 -05002976#In Mask_Filter_Methods
2977#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04002978 Returns Mask_Filter if set, or nullptr.
2979 Does not alter Mask_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04002980
Cary Clark8032b982017-07-28 11:04:54 -04002981 #Return Mask_Filter if previously set, nullptr otherwise ##
2982
2983 #Example
2984 void draw(SkCanvas* canvas) {
2985 SkPaint paint;
2986 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
Cary Clark681287e2018-03-16 11:34:15 -04002987 paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3));
Cary Clark8032b982017-07-28 11:04:54 -04002988 SkDebugf("nullptr %c= mask filter\n", paint.getMaskFilter() ? '!' : '=');
2989 }
2990
2991 #StdOut
2992 nullptr == mask filter
2993 nullptr != mask filter
2994 ##
2995 ##
2996
2997##
2998
2999#Method sk_sp<SkMaskFilter> refMaskFilter() const
3000
Cary Clarkab2621d2018-01-30 10:08:57 -05003001#In Mask_Filter_Methods
3002#Line # references Mask_Filter, alterations to Mask_Alpha ##
Cary Clark8032b982017-07-28 11:04:54 -04003003 Returns Mask_Filter if set, or nullptr.
Cary Clark6fc50412017-09-21 12:31:06 -04003004
Cary Clark8032b982017-07-28 11:04:54 -04003005 Increases Mask_Filter Reference_Count by one.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003006
Cary Clark8032b982017-07-28 11:04:54 -04003007 #Return Mask_Filter if previously set, nullptr otherwise ##
3008
3009 #Example
3010 void draw(SkCanvas* canvas) {
3011 SkPaint paint1, paint2;
Cary Clark681287e2018-03-16 11:34:15 -04003012 paint1.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1));
Cary Clark8032b982017-07-28 11:04:54 -04003013 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3014 paint2.setMaskFilter(paint1.refMaskFilter());
3015 SkDebugf("mask filter unique: %s\n", paint1.getMaskFilter()->unique() ? "true" : "false");
3016 }
3017
3018 #StdOut
3019 mask filter unique: true
3020 mask filter unique: false
3021 ##
3022 ##
3023
3024##
3025
3026#Method void setMaskFilter(sk_sp<SkMaskFilter> maskFilter)
3027
Cary Clarkab2621d2018-01-30 10:08:57 -05003028#In Mask_Filter_Methods
3029#Line # sets Mask_Filter, alterations to Mask_Alpha ##
Cary Clark6fc50412017-09-21 12:31:06 -04003030Sets Mask_Filter to maskFilter, decreasing Reference_Count of the previous
3031Mask_Filter. Pass nullptr to clear Mask_Filter and leave Mask_Filter effect on
3032Mask_Alpha unaltered.
3033
Cary Clark6fc50412017-09-21 12:31:06 -04003034Increments maskFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003035
3036 #Param maskFilter modifies clipping mask generated from drawn geometry ##
3037
3038 #Example
3039 void draw(SkCanvas* canvas) {
3040 SkPaint paint;
3041 paint.setStyle(SkPaint::kStroke_Style);
3042 paint.setStrokeWidth(10);
Cary Clark681287e2018-03-16 11:34:15 -04003043 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Cary Clark8032b982017-07-28 11:04:54 -04003044 canvas->drawRect(SkRect::MakeXYWH(40, 40, 175, 175), paint);
3045 }
3046 ##
3047
3048##
3049
Cary Clark08895c42018-02-01 09:37:32 -05003050#Subtopic Mask_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003051# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003052#Subtopic Typeface_Methods
3053#Line # get and set Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003054
3055Typeface identifies the font used when drawing and measuring text.
3056Typeface may be specified by name, from a file, or from a data stream.
3057The default Typeface defers to the platform-specific default font
3058implementation.
3059
3060#Example
3061#Height 100
3062 void draw(SkCanvas* canvas) {
3063 SkPaint paint;
Ben Wagner700ff172017-11-08 15:37:22 -05003064 paint.setTypeface(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003065 paint.setAntiAlias(true);
3066 paint.setTextSize(36);
3067 canvas->drawString("A Big Hello!", 10, 40, paint);
3068 paint.setTypeface(nullptr);
3069 paint.setFakeBoldText(true);
3070 canvas->drawString("A Big Hello!", 10, 80, paint);
3071 }
3072##
3073
3074#Method SkTypeface* getTypeface() const
3075
Cary Clarkab2621d2018-01-30 10:08:57 -05003076#In Typeface_Methods
3077#Line # returns Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003078 Returns Typeface if set, or nullptr.
Ben Wagner900b5362018-06-22 14:29:08 -04003079 Does not alter Typeface Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003080
Cary Clark8032b982017-07-28 11:04:54 -04003081 #Return Typeface if previously set, nullptr otherwise ##
3082
3083 #Example
3084 void draw(SkCanvas* canvas) {
3085 SkPaint paint;
3086 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
Cary Clark71961fb2018-01-05 14:21:59 -05003087 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
Cary Clark8032b982017-07-28 11:04:54 -04003088 SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
3089 }
3090
3091 #StdOut
3092 nullptr == typeface
3093 nullptr != typeface
3094 ##
3095 ##
3096
3097##
3098
3099#Method sk_sp<SkTypeface> refTypeface() const
3100
Cary Clarkab2621d2018-01-30 10:08:57 -05003101#In Typeface_Methods
3102#Line # references Typeface, font description ##
Cary Clark8032b982017-07-28 11:04:54 -04003103 Increases Typeface Reference_Count by one.
3104
3105 #Return Typeface if previously set, nullptr otherwise ##
3106
3107 #Example
3108 void draw(SkCanvas* canvas) {
3109 SkPaint paint1, paint2;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003110 paint1.setTypeface(SkTypeface::MakeFromName("monospace",
Cary Clark8032b982017-07-28 11:04:54 -04003111 SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
3112 SkFontStyle::kItalic_Slant)));
3113 SkDebugf("typeface1 %c= typeface2\n",
3114 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3115 paint2.setTypeface(paint1.refTypeface());
3116 SkDebugf("typeface1 %c= typeface2\n",
3117 paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
3118 }
3119
3120 #StdOut
3121 typeface1 != typeface2
3122 typeface1 == typeface2
3123 ##
3124 ##
3125
3126##
3127
3128#Method void setTypeface(sk_sp<SkTypeface> typeface)
3129
Cary Clarkab2621d2018-01-30 10:08:57 -05003130#In Typeface_Methods
3131#Line # sets Typeface, font description ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003132Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
Cary Clark6fc50412017-09-21 12:31:06 -04003133Pass nullptr to clear Typeface and use the default typeface. Increments
3134typeface Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003135
3136 #Param typeface font and style used to draw text ##
3137
3138 #Example
3139 #Height 64
3140 void draw(SkCanvas* canvas) {
3141 SkPaint paint;
Cary Clark71961fb2018-01-05 14:21:59 -05003142 paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
3143 canvas->drawString("hamburgerfons", 10, 30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003144 paint.setTypeface(nullptr);
Cary Clark71961fb2018-01-05 14:21:59 -05003145 canvas->drawString("hamburgerfons", 10, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003146 }
3147 ##
3148
3149##
3150
Cary Clark08895c42018-02-01 09:37:32 -05003151#Subtopic Typeface_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003152# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003153#Subtopic Image_Filter_Methods
3154#Line # get and set Image_Filter ##
Cary Clark8032b982017-07-28 11:04:54 -04003155
3156Image_Filter operates on the pixel representation of the shape, as modified by Paint
3157with Blend_Mode set to SkBlendMode::kSrcOver. Image_Filter creates a new bitmap,
3158which is drawn to the device using the set Blend_Mode.
Cary Clark6fc50412017-09-21 12:31:06 -04003159
Cary Clark8032b982017-07-28 11:04:54 -04003160Image_Filter is higher level than Mask_Filter; for instance, an Image_Filter
Cary Clarkce101242017-09-01 15:51:02 -04003161can operate on all channels of Color, while Mask_Filter generates Alpha only.
Cary Clark8032b982017-07-28 11:04:54 -04003162Image_Filter operates independently of and can be used in combination with
Mike Reed8ad91a92018-01-19 19:09:32 -05003163Mask_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04003164
3165#Example
3166 #ToDo explain why the two draws are so different ##
Cary Clark81abc432018-06-25 16:30:08 -04003167 #Function
3168 ###$
3169 #include "SkBlurImageFilter.h"
3170 $$$#
3171 ##
Cary Clark8032b982017-07-28 11:04:54 -04003172 void draw(SkCanvas* canvas) {
3173 SkPaint paint;
3174 paint.setStyle(SkPaint::kStroke_Style);
3175 paint.setStrokeWidth(2);
3176 SkRegion region;
3177 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3178 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
Cary Clarka560c472017-11-27 10:44:06 -05003179 paint.setImageFilter(SkBlurImageFilter::Make(5.0f, 5.0f, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003180 canvas->drawRegion(region, paint);
3181 paint.setImageFilter(nullptr);
Cary Clarka7b84c52018-03-18 11:46:54 -04003182 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5));
Cary Clark8032b982017-07-28 11:04:54 -04003183 canvas->translate(100, 100);
3184 canvas->drawRegion(region, paint);
3185 }
3186##
3187
3188#Method SkImageFilter* getImageFilter() const
3189
Cary Clarkab2621d2018-01-30 10:08:57 -05003190#In Image_Filter_Methods
3191#Line # returns Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003192 Returns Image_Filter if set, or nullptr.
3193 Does not alter Image_Filter Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003194
Cary Clark8032b982017-07-28 11:04:54 -04003195 #Return Image_Filter if previously set, nullptr otherwise ##
3196
3197 #Example
Cary Clark81abc432018-06-25 16:30:08 -04003198 #Function
3199 ###$
3200 #include "SkBlurImageFilter.h"
3201 $$$#
3202 ##
Cary Clark8032b982017-07-28 11:04:54 -04003203 void draw(SkCanvas* canvas) {
3204 SkPaint paint;
3205 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
Cary Clarka560c472017-11-27 10:44:06 -05003206 paint.setImageFilter(SkBlurImageFilter::Make(kOuter_SkBlurStyle, 3, nullptr, nullptr));
Cary Clark8032b982017-07-28 11:04:54 -04003207 SkDebugf("nullptr %c= image filter\n", paint.getImageFilter() ? '!' : '=');
3208 }
3209
3210 #StdOut
3211 nullptr == image filter
3212 nullptr != image filter
3213 ##
3214 ##
3215
3216##
3217
3218#Method sk_sp<SkImageFilter> refImageFilter() const
3219
Cary Clarkab2621d2018-01-30 10:08:57 -05003220#In Image_Filter_Methods
3221#Line # references Image_Filter, alter pixels; blur ##
Cary Clark8032b982017-07-28 11:04:54 -04003222 Returns Image_Filter if set, or nullptr.
3223 Increases Image_Filter Reference_Count by one.
3224
3225 #Return Image_Filter if previously set, nullptr otherwise ##
3226
3227 #Example
3228 void draw(SkCanvas* canvas) {
3229 SkPaint paint1, paint2;
3230 paint1.setImageFilter(SkOffsetImageFilter::Make(25, 25, nullptr));
3231 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3232 paint2.setImageFilter(paint1.refImageFilter());
3233 SkDebugf("image filter unique: %s\n", paint1.getImageFilter()->unique() ? "true" : "false");
3234 }
3235
3236 #StdOut
3237 image filter unique: true
3238 image filter unique: false
3239 ##
3240 ##
3241
3242##
3243
3244#Method void setImageFilter(sk_sp<SkImageFilter> imageFilter)
3245
Cary Clarkab2621d2018-01-30 10:08:57 -05003246#In Image_Filter_Methods
3247#Line # sets Image_Filter, alter pixels; blur ##
Cary Clark6fc50412017-09-21 12:31:06 -04003248Sets Image_Filter to imageFilter, decreasing Reference_Count of the previous
3249Image_Filter. Pass nullptr to clear Image_Filter, and remove Image_Filter effect
3250on drawing.
3251
Cary Clark6fc50412017-09-21 12:31:06 -04003252Increments imageFilter Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003253
3254 #Param imageFilter how Image is sampled when transformed ##
3255
3256 #Example
3257 #Height 160
3258 void draw(SkCanvas* canvas) {
3259 SkBitmap bitmap;
3260 bitmap.allocN32Pixels(100, 100);
3261 SkCanvas offscreen(bitmap);
3262 SkPaint paint;
3263 paint.setAntiAlias(true);
3264 paint.setColor(SK_ColorWHITE);
3265 paint.setTextSize(96);
3266 offscreen.clear(0);
3267 offscreen.drawString("e", 20, 70, paint);
3268 paint.setImageFilter(
3269 SkLightingImageFilter::MakePointLitDiffuse(SkPoint3::Make(80, 100, 10),
3270 SK_ColorWHITE, 1, 2, nullptr, nullptr));
3271 canvas->drawBitmap(bitmap, 0, 0, &paint);
3272 }
3273 ##
3274
3275##
3276
Cary Clark08895c42018-02-01 09:37:32 -05003277#Subtopic Image_Filter_Methods ##
Cary Clark8032b982017-07-28 11:04:54 -04003278# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003279#Subtopic Draw_Looper_Methods
3280#Line # get and set Draw_Looper ##
Cary Clark8032b982017-07-28 11:04:54 -04003281
3282Draw_Looper sets a modifier that communicates state from one Draw_Layer
3283to another to construct the draw.
Cary Clark6fc50412017-09-21 12:31:06 -04003284
Cary Clark8032b982017-07-28 11:04:54 -04003285Draw_Looper draws one or more times, modifying the canvas and paint each time.
3286Draw_Looper may be used to draw multiple colors or create a colored shadow.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003287Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
Cary Clark8032b982017-07-28 11:04:54 -04003288
3289#Example
3290#Height 128
3291 void draw(SkCanvas* canvas) {
3292 SkLayerDrawLooper::LayerInfo info;
3293 info.fPaintBits = (SkLayerDrawLooper::BitFlags) SkLayerDrawLooper::kColorFilter_Bit;
3294 info.fColorMode = SkBlendMode::kSrc;
3295 SkLayerDrawLooper::Builder looperBuilder;
3296 SkPaint* loopPaint = looperBuilder.addLayer(info);
3297 loopPaint->setColor(SK_ColorRED);
3298 info.fOffset.set(20, 20);
3299 loopPaint = looperBuilder.addLayer(info);
3300 loopPaint->setColor(SK_ColorBLUE);
3301 SkPaint paint;
3302 paint.setDrawLooper(looperBuilder.detach());
3303 canvas->drawCircle(50, 50, 50, paint);
3304 }
3305
3306##
3307
3308#Method SkDrawLooper* getDrawLooper() const
3309
Cary Clarkab2621d2018-01-30 10:08:57 -05003310#In Draw_Looper_Methods
3311#Line # returns Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003312 Returns Draw_Looper if set, or nullptr.
3313 Does not alter Draw_Looper Reference_Count.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003314
Cary Clark8032b982017-07-28 11:04:54 -04003315 #Return Draw_Looper if previously set, nullptr otherwise ##
3316
3317 #Example
3318 void draw(SkCanvas* canvas) {
3319 SkPaint paint;
3320 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3321 SkLayerDrawLooper::Builder looperBuilder;
3322 paint.setDrawLooper(looperBuilder.detach());
3323 SkDebugf("nullptr %c= draw looper\n", paint.getDrawLooper() ? '!' : '=');
3324 }
3325
3326 #StdOut
3327 nullptr == draw looper
3328 nullptr != draw looper
3329 ##
3330 ##
3331
3332##
3333
3334#Method sk_sp<SkDrawLooper> refDrawLooper() const
3335
Cary Clarkab2621d2018-01-30 10:08:57 -05003336#In Draw_Looper_Methods
3337#Line # references Draw_Looper, multiple layers ##
Cary Clark8032b982017-07-28 11:04:54 -04003338 Returns Draw_Looper if set, or nullptr.
3339 Increases Draw_Looper Reference_Count by one.
3340
3341 #Return Draw_Looper if previously set, nullptr otherwise ##
3342
3343 #Example
3344 void draw(SkCanvas* canvas) {
3345 SkPaint paint1, paint2;
3346 SkLayerDrawLooper::Builder looperBuilder;
3347 paint1.setDrawLooper(looperBuilder.detach());
3348 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3349 paint2.setDrawLooper(paint1.refDrawLooper());
3350 SkDebugf("draw looper unique: %s\n", paint1.getDrawLooper()->unique() ? "true" : "false");
3351 }
3352
3353 #StdOut
3354 draw looper unique: true
3355 draw looper unique: false
3356 ##
3357 ##
3358
3359##
3360
3361#Method SkDrawLooper* getLooper() const
Cary Clark4855f782018-02-06 09:41:53 -05003362#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003363#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003364##
3365
3366#Method void setDrawLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clarkab2621d2018-01-30 10:08:57 -05003367#In Draw_Looper_Methods
3368#Line # sets Draw_Looper, multiple layers ##
Cary Clark6fc50412017-09-21 12:31:06 -04003369Sets Draw_Looper to drawLooper, decreasing Reference_Count of the previous
3370drawLooper. Pass nullptr to clear Draw_Looper and leave Draw_Looper effect on
3371drawing unaltered.
3372
3373Increments drawLooper Reference_Count by one.
Cary Clark8032b982017-07-28 11:04:54 -04003374
Cary Clarka523d2d2017-08-30 08:58:10 -04003375 #Param drawLooper iterates through drawing one or more time, altering Paint ##
Cary Clark8032b982017-07-28 11:04:54 -04003376
3377 #Example
3378 #Height 128
3379 void draw(SkCanvas* canvas) {
3380 SkPaint paint;
3381 paint.setDrawLooper(SkBlurDrawLooper::Make(0x7FFF0000, 4, -5, -10));
3382 paint.setStyle(SkPaint::kStroke_Style);
3383 paint.setStrokeWidth(10);
3384 paint.setAntiAlias(true);
3385 paint.setColor(0x7f0000ff);
3386 canvas->drawCircle(70, 70, 50, paint);
3387 }
3388 ##
3389
3390##
3391
3392#Method void setLooper(sk_sp<SkDrawLooper> drawLooper)
Cary Clark4855f782018-02-06 09:41:53 -05003393#Bug 6259
Cary Clark8032b982017-07-28 11:04:54 -04003394#Deprecated
Cary Clark8032b982017-07-28 11:04:54 -04003395##
3396
Cary Clark08895c42018-02-01 09:37:32 -05003397#Subtopic Draw_Looper_Methods ##
Cary Clark4855f782018-02-06 09:41:53 -05003398
Cary Clark8032b982017-07-28 11:04:54 -04003399# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003400#Subtopic Text_Align
3401#Line # text placement relative to position ##
Cary Clark8032b982017-07-28 11:04:54 -04003402
3403#Enum Align
Cary Clark08895c42018-02-01 09:37:32 -05003404#Line # glyph locations relative to text position ##
Cary Clark8032b982017-07-28 11:04:54 -04003405#Code
Cary Clarka90ea222018-10-16 10:30:28 -04003406#Populate
3407##
Cary Clarkd98f78c2018-04-26 08:32:37 -04003408
Cary Clarka90ea222018-10-16 10:30:28 -04003409#Code
3410#In Constant
3411#Filter kAlign
3412#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003413##
3414
3415Align adjusts the text relative to the text position.
Cary Clarkce101242017-09-01 15:51:02 -04003416Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
Cary Clark153e76d2018-08-28 11:48:28 -04003417SkCanvas::drawPosTextH, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
Herb Derbyfcac00f2018-05-01 11:57:56 -04003418and SkCanvas::drawString;
Cary Clarkce101242017-09-01 15:51:02 -04003419as well as calls that place text Glyphs like getTextWidths and getTextPath.
Cary Clark8032b982017-07-28 11:04:54 -04003420
3421The text position is set by the font for both horizontal and vertical text.
3422Typically, for horizontal text, the position is to the left side of the glyph on the
3423base line; and for vertical text, the position is the horizontal center of the glyph
3424at the caps height.
3425
Herb Derbyfcac00f2018-05-01 11:57:56 -04003426Align adjusts the glyph position to center it or move it to abut the position
Cary Clark8032b982017-07-28 11:04:54 -04003427using the metrics returned by the font.
3428
3429Align defaults to kLeft_Align.
3430
3431#Const kLeft_Align 0
Cary Clark682c58d2018-05-16 07:07:07 -04003432#Line # positions glyph by computed font offset ##
Cary Clark8032b982017-07-28 11:04:54 -04003433 Leaves the glyph at the position computed by the font offset by the text position.
3434##
3435
3436#Const kCenter_Align 1
Cary Clark682c58d2018-05-16 07:07:07 -04003437#Line # centers line of glyphs by its width or height ##
Cary Clark8032b982017-07-28 11:04:54 -04003438 Moves the glyph half its width if Flags has kVerticalText_Flag clear, and
3439 half its height if Flags has kVerticalText_Flag set.
3440##
3441
3442#Const kRight_Align 2
Cary Clark682c58d2018-05-16 07:07:07 -04003443#Line # moves lines of glyphs by its width or height ##
Cary Clark8032b982017-07-28 11:04:54 -04003444 Moves the glyph by its width if Flags has kVerticalText_Flag clear,
3445 and by its height if Flags has kVerticalText_Flag set.
3446##
3447
Cary Clark8032b982017-07-28 11:04:54 -04003448#Const kAlignCount 3
Cary Clark682c58d2018-05-16 07:07:07 -04003449#Line # number of different Text_Align values defined ##
Cary Clark137b8742018-05-30 09:21:49 -04003450May be used to verify that Align is a legal value.
Cary Clark8032b982017-07-28 11:04:54 -04003451##
3452
3453#Enum ##
3454
3455#Example
3456 #Height 160
3457 #Description
3458 Each position separately moves the glyph in drawPosText.
3459 ##
3460 void draw(SkCanvas* canvas) {
3461 SkPaint paint;
3462 paint.setTextSize(40);
3463 SkPoint position[] = {{100, 50}, {150, 40}};
3464 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3465 SkPaint::kCenter_Align,
3466 SkPaint::kRight_Align}) {
3467 paint.setTextAlign(a);
3468 canvas->drawPosText("Aa", 2, position, paint);
3469 canvas->translate(0, 50);
3470 }
3471 }
3472##
3473
3474#Example
3475 #Height 160
3476 #Description
3477 Vertical_Text treats kLeft_Align as top align, and kRight_Align as bottom align.
3478 ##
3479 void draw(SkCanvas* canvas) {
3480 SkPaint paint;
3481 paint.setTextSize(40);
3482 paint.setVerticalText(true);
3483 for (SkPaint::Align a : { SkPaint::kLeft_Align,
3484 SkPaint::kCenter_Align,
3485 SkPaint::kRight_Align }) {
3486 paint.setTextAlign(a);
3487 canvas->drawString("Aa", 50, 80, paint);
3488 canvas->translate(50, 0);
3489 }
3490 }
3491##
3492
3493#Method Align getTextAlign() const
3494
Cary Clarkab2621d2018-01-30 10:08:57 -05003495#In Text_Align
3496#Line # returns Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003497 Returns Text_Align.
3498 Returns kLeft_Align if Text_Align has not been set.
3499
3500 #Return text placement relative to position ##
3501
3502 #Example
3503 SkPaint paint;
3504 SkDebugf("kLeft_Align %c= default\n", SkPaint::kLeft_Align == paint.getTextAlign() ? '=' : '!');
3505
3506 #StdOut
3507 kLeft_Align == default
3508 ##
3509 ##
3510##
3511
3512#Method void setTextAlign(Align align)
3513
Cary Clarkab2621d2018-01-30 10:08:57 -05003514#In Text_Align
3515#Line # sets Align: left, center, or right ##
Cary Clark8032b982017-07-28 11:04:54 -04003516 Sets Text_Align to align.
3517 Has no effect if align is an invalid value.
3518
3519 #Param align text placement relative to position ##
3520
3521 #Example
3522 #Height 160
3523 #Description
3524 Text is left-aligned by default, and then set to center. Setting the
3525 alignment out of range has no effect.
3526 ##
3527 void draw(SkCanvas* canvas) {
3528 SkPaint paint;
3529 paint.setTextSize(40);
3530 canvas->drawString("Aa", 100, 50, paint);
3531 paint.setTextAlign(SkPaint::kCenter_Align);
3532 canvas->drawString("Aa", 100, 100, paint);
3533 paint.setTextAlign((SkPaint::Align) SkPaint::kAlignCount);
3534 canvas->drawString("Aa", 100, 150, paint);
3535 }
3536 ##
3537
3538##
3539
Cary Clark08895c42018-02-01 09:37:32 -05003540#Subtopic Text_Align ##
Cary Clark8032b982017-07-28 11:04:54 -04003541# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003542#Subtopic Text_Size
3543#Line # overall height in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003544
3545Text_Size adjusts the overall text size in points.
3546Text_Size can be set to any positive value or zero.
3547Text_Size defaults to 12.
3548Set SkPaintDefaults_TextSize at compile time to change the default setting.
3549
3550#Example
3551#Height 135
3552 void draw(SkCanvas* canvas) {
3553 SkPaint paint;
3554 canvas->drawString("12 point", 10, 20, paint);
3555 paint.setTextSize(24);
3556 canvas->drawString("24 point", 10, 60, paint);
3557 paint.setTextSize(48);
3558 canvas->drawString("48 point", 10, 120, paint);
3559 }
3560##
3561
3562#Method SkScalar getTextSize() const
3563
Cary Clarkab2621d2018-01-30 10:08:57 -05003564#In Text_Size
3565#Line # returns text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003566 Returns Text_Size in points.
3567
3568 #Return typographic height of text ##
3569
3570 #Example
3571 SkPaint paint;
3572 SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
3573 ##
3574
3575##
3576
3577#Method void setTextSize(SkScalar textSize)
3578
Cary Clarkab2621d2018-01-30 10:08:57 -05003579#In Text_Size
3580#Line # sets text size in points ##
Cary Clark8032b982017-07-28 11:04:54 -04003581 Sets Text_Size in points.
3582 Has no effect if textSize is not greater than or equal to zero.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003583
Cary Clark8032b982017-07-28 11:04:54 -04003584 #Param textSize typographic height of text ##
3585
3586 #Example
3587 SkPaint paint;
3588 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3589 paint.setTextSize(-20);
3590 SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
3591 ##
3592
3593##
3594
Cary Clark08895c42018-02-01 09:37:32 -05003595#Subtopic Text_Size ##
Cary Clark8032b982017-07-28 11:04:54 -04003596# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003597#Subtopic Text_Scale_X
3598#Line # text horizontal scale ##
Cary Clark8032b982017-07-28 11:04:54 -04003599
3600Text_Scale_X adjusts the text horizontal scale.
3601Text scaling approximates condensed and expanded type faces when the actual face
3602is not available.
3603Text_Scale_X can be set to any value.
3604Text_Scale_X defaults to 1.
3605
3606#Example
3607#Height 128
3608 void draw(SkCanvas* canvas) {
3609 SkPaint paint;
3610 paint.setAntiAlias(true);
3611 paint.setTextSize(24);
3612 paint.setTextScaleX(.8f);
3613 canvas->drawString("narrow", 10, 20, paint);
3614 paint.setTextScaleX(1);
3615 canvas->drawString("normal", 10, 60, paint);
3616 paint.setTextScaleX(1.2f);
3617 canvas->drawString("wide", 10, 100, paint);
3618 }
3619##
3620
3621#Method SkScalar getTextScaleX() const
3622
Cary Clarkab2621d2018-01-30 10:08:57 -05003623#In Text_Scale_X
3624#Line # returns the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003625 Returns Text_Scale_X.
3626 Default value is 1.
3627
3628 #Return text horizontal scale ##
3629
3630 #Example
3631 SkPaint paint;
3632 SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
3633 ##
3634
3635##
3636
3637
3638#Method void setTextScaleX(SkScalar scaleX)
3639
Cary Clarkab2621d2018-01-30 10:08:57 -05003640#In Text_Scale_X
3641#Line # sets the text horizontal scale; condensed text ##
Cary Clark8032b982017-07-28 11:04:54 -04003642 Sets Text_Scale_X.
3643 Default value is 1.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003644
Cary Clark8032b982017-07-28 11:04:54 -04003645 #Param scaleX text horizontal scale ##
3646
3647 #Example
3648 SkPaint paint;
3649 paint.setTextScaleX(0.f / 0.f);
3650 SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
3651 ##
3652
3653##
3654
Cary Clark08895c42018-02-01 09:37:32 -05003655#Subtopic Text_Scale_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003656
Cary Clark08895c42018-02-01 09:37:32 -05003657#Subtopic Text_Skew_X
3658#Line # text horizontal slant ##
Cary Clark8032b982017-07-28 11:04:54 -04003659
3660
3661Text_Skew_X adjusts the text horizontal slant.
3662Text skewing approximates italic and oblique type faces when the actual face
3663is not available.
3664Text_Skew_X can be set to any value.
3665Text_Skew_X defaults to 0.
3666
3667#Example
3668#Height 128
3669 void draw(SkCanvas* canvas) {
3670 SkPaint paint;
3671 paint.setAntiAlias(true);
3672 paint.setTextSize(24);
3673 paint.setTextSkewX(-.25f);
3674 canvas->drawString("right-leaning", 10, 100, paint);
3675 paint.setTextSkewX(0);
3676 canvas->drawString("normal", 10, 60, paint);
3677 paint.setTextSkewX(.25f);
3678 canvas->drawString("left-leaning", 10, 20, paint);
3679 }
3680##
3681
3682#Method SkScalar getTextSkewX() const
3683
Cary Clarkab2621d2018-01-30 10:08:57 -05003684#In Text_Skew_X
3685#Line # returns the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003686 Returns Text_Skew_X.
3687 Default value is zero.
3688
3689 #Return additional shear in x-axis relative to y-axis ##
3690
3691 #Example
3692 SkPaint paint;
3693 SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
3694 ##
3695
3696##
3697
3698#Method void setTextSkewX(SkScalar skewX)
3699
Cary Clarkab2621d2018-01-30 10:08:57 -05003700#In Text_Skew_X
3701#Line # sets the text horizontal skew; oblique text ##
Cary Clark8032b982017-07-28 11:04:54 -04003702 Sets Text_Skew_X.
3703 Default value is zero.
3704
3705 #Param skewX additional shear in x-axis relative to y-axis ##
3706
3707 #Example
3708 SkPaint paint;
3709 paint.setTextScaleX(1.f / 0.f);
3710 SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
3711 ##
3712
3713##
3714
Cary Clark08895c42018-02-01 09:37:32 -05003715#Subtopic Text_Skew_X ##
Cary Clark8032b982017-07-28 11:04:54 -04003716
3717# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003718#Subtopic Text_Encoding
3719#Line # text encoded as characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04003720
3721#Enum TextEncoding
Cary Clark08895c42018-02-01 09:37:32 -05003722#Line # character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003723
3724#Code
Cary Clarka90ea222018-10-16 10:30:28 -04003725#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003726##
3727
Cary Clark6fc50412017-09-21 12:31:06 -04003728TextEncoding determines whether text specifies character codes and their encoded
Cary Clarkbc5697d2017-10-04 14:31:33 -04003729size, or glyph indices. Characters are encoded as specified by the
Cary Clark682c58d2018-05-16 07:07:07 -04003730#A Unicode standard # https://unicode.org/standard/standard.html ##
Cary Clark6fc50412017-09-21 12:31:06 -04003731.
3732
Cary Clark8032b982017-07-28 11:04:54 -04003733Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
Cary Clarkbc5697d2017-10-04 14:31:33 -04003734All character code formats are able to represent all of Unicode, differing only
Cary Clark8032b982017-07-28 11:04:54 -04003735in the total storage required.
3736
Cary Clark6fc50412017-09-21 12:31:06 -04003737#A UTF-8 (RFC 3629) # https://tools.ietf.org/html/rfc3629 ##
3738 encodes each character as one or more 8-bit bytes.
3739
3740#A UTF-16 (RFC 2781) # https://tools.ietf.org/html/rfc2781 ##
3741 encodes each character as one or two 16-bit words.
3742
Cary Clark682c58d2018-05-16 07:07:07 -04003743#A UTF-32 # https://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
Cary Clark6fc50412017-09-21 12:31:06 -04003744 encodes each character as one 32-bit word.
Cary Clark8032b982017-07-28 11:04:54 -04003745
Herb Derbyfcac00f2018-05-01 11:57:56 -04003746Font_Manager uses font data to convert character code points into glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003747A glyph index is a 16-bit word.
3748
3749TextEncoding is set to kUTF8_TextEncoding by default.
3750
3751#Const kUTF8_TextEncoding 0
Cary Clark682c58d2018-05-16 07:07:07 -04003752#Line # uses bytes to represent UTF-8 or ASCII ##
Cary Clark8032b982017-07-28 11:04:54 -04003753##
3754#Const kUTF16_TextEncoding 1
Cary Clark682c58d2018-05-16 07:07:07 -04003755#Line # uses two byte words to represent most of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003756##
3757#Const kUTF32_TextEncoding 2
Cary Clark682c58d2018-05-16 07:07:07 -04003758#Line # uses four byte words to represent all of Unicode ##
Cary Clark8032b982017-07-28 11:04:54 -04003759##
3760#Const kGlyphID_TextEncoding 3
Cary Clark682c58d2018-05-16 07:07:07 -04003761#Line # uses two byte words to represent glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04003762##
3763
3764#Enum ##
3765
3766#Example
3767#Height 128
3768#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04003769First line is encoded in UTF-8.
3770Second line is encoded in UTF-16.
3771Third line is encoded in UTF-32.
Cary Clark682c58d2018-05-16 07:07:07 -04003772Fourth line has 16-bit glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04003773##
3774void draw(SkCanvas* canvas) {
3775 SkPaint paint;
3776 const char hello8[] = "Hello" "\xE2" "\x98" "\xBA";
3777 const uint16_t hello16[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3778 const uint32_t hello32[] = { 'H', 'e', 'l', 'l', 'o', 0x263A };
3779 paint.setTextSize(24);
3780 canvas->drawText(hello8, sizeof(hello8) - 1, 10, 30, paint);
3781 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
3782 canvas->drawText(hello16, sizeof(hello16), 10, 60, paint);
3783 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
3784 canvas->drawText(hello32, sizeof(hello32), 10, 90, paint);
3785 uint16_t glyphs[SK_ARRAY_COUNT(hello32)];
3786 paint.textToGlyphs(hello32, sizeof(hello32), glyphs);
3787 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3788 canvas->drawText(glyphs, sizeof(glyphs), 10, 120, paint);
3789}
3790##
3791
3792#Method TextEncoding getTextEncoding() const
3793
Cary Clarkab2621d2018-01-30 10:08:57 -05003794#In Text_Encoding
3795#Line # returns character or glyph encoded size ##
Cary Clark8032b982017-07-28 11:04:54 -04003796 Returns Text_Encoding.
3797 Text_Encoding determines how character code points are mapped to font glyph indices.
3798
Herb Derbyfcac00f2018-05-01 11:57:56 -04003799 #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3800 kGlyphID_TextEncoding
Cary Clark8032b982017-07-28 11:04:54 -04003801 ##
3802
3803 #Example
3804 SkPaint paint;
Herb Derbyfcac00f2018-05-01 11:57:56 -04003805 SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003806 SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3807 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04003808 SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
Cary Clark8032b982017-07-28 11:04:54 -04003809 SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
3810
3811 #StdOut
3812 kUTF8_TextEncoding == text encoding
3813 kGlyphID_TextEncoding == text encoding
3814 ##
3815 ##
3816
3817##
3818
3819
3820#Method void setTextEncoding(TextEncoding encoding)
3821
Cary Clarkab2621d2018-01-30 10:08:57 -05003822#In Text_Encoding
3823#Line # sets character or glyph encoded size ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04003824 Sets Text_Encoding to encoding.
Cary Clark8032b982017-07-28 11:04:54 -04003825 Text_Encoding determines how character code points are mapped to font glyph indices.
3826 Invalid values for encoding are ignored.
3827
Herb Derbyfcac00f2018-05-01 11:57:56 -04003828 #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
3829 kGlyphID_TextEncoding
Cary Clark579985c2017-07-31 11:48:27 -04003830 #Param ##
Cary Clark8032b982017-07-28 11:04:54 -04003831
3832 #Example
3833 SkPaint paint;
3834 paint.setTextEncoding((SkPaint::TextEncoding) 4);
Cary Clark75fd4492018-06-20 12:45:16 -04003835 SkDebugf("4 %c= text encoding\n", (SkPaint::TextEncoding) 4 == paint.getTextEncoding() ? '=' : '!');
Cary Clark8032b982017-07-28 11:04:54 -04003836
3837 #StdOut
3838 4 != text encoding
3839 ##
3840 ##
3841
3842##
3843
Cary Clark08895c42018-02-01 09:37:32 -05003844#Subtopic Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04003845# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003846#Subtopic Font_Metrics
3847#Line # common glyph dimensions ##
Cary Clark8032b982017-07-28 11:04:54 -04003848
Cary Clarkce101242017-09-01 15:51:02 -04003849Font_Metrics describe dimensions common to the Glyphs in Typeface.
Herb Derbyfcac00f2018-05-01 11:57:56 -04003850The dimensions are computed by Font_Manager from font data and do not take
Cary Clark8032b982017-07-28 11:04:54 -04003851Paint settings other than Text_Size into account.
3852
3853Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
3854X-axis values to the left of the glyph are negative, and to the right of the left glyph edge
3855are positive.
3856Y-axis values above the baseline are negative, and below the baseline are positive.
Ben Wagnere5806492017-11-09 12:08:31 -05003857
Cary Clark8032b982017-07-28 11:04:54 -04003858#Example
3859#Width 512
3860void draw(SkCanvas* canvas) {
3861 SkPaint paint;
3862 paint.setAntiAlias(true);
3863 paint.setTextSize(120);
3864 SkPaint::FontMetrics fm;
3865 SkScalar lineHeight = paint.getFontMetrics(&fm);
3866 SkPoint pt = { 70, 180 };
3867 canvas->drawString("M", pt.fX, pt.fY, paint);
3868 canvas->drawLine(pt.fX, pt.fY, pt.fX, pt.fY + fm.fTop, paint);
3869 SkScalar ascent = pt.fY + fm.fAscent;
3870 canvas->drawLine(pt.fX - 25, ascent, pt.fX - 25, ascent + lineHeight, paint);
3871 canvas->drawLine(pt.fX - 50, pt.fY, pt.fX - 50, pt.fY + fm.fDescent, paint);
3872 canvas->drawLine(pt.fX + 100, pt.fY, pt.fX + 100, pt.fY + fm.fAscent, paint);
3873 canvas->drawLine(pt.fX + 125, pt.fY, pt.fX + 125, pt.fY - fm.fXHeight, paint);
3874 canvas->drawLine(pt.fX + 150, pt.fY, pt.fX + 150, pt.fY - fm.fCapHeight, paint);
3875 canvas->drawLine(pt.fX + 5, pt.fY, pt.fX + 5, pt.fY + fm.fBottom, paint);
3876 SkScalar xmin = pt.fX + fm.fXMin;
3877 canvas->drawLine(xmin, pt.fY + 60, xmin + fm.fMaxCharWidth, pt.fY + 60, paint);
3878 canvas->drawLine(xmin, pt.fY - 145, pt.fX, pt.fY - 145, paint);
3879 canvas->drawLine(pt.fX + fm.fXMax, pt.fY - 160, pt.fX, pt.fY - 160, paint);
3880 SkScalar upos = pt.fY + fm.fUnderlinePosition;
Ben Wagnere5806492017-11-09 12:08:31 -05003881 canvas->drawLine(pt.fX + 25, upos, pt.fX + 160, upos, paint);
3882 SkScalar ut = fm.fUnderlineThickness;
3883 canvas->drawLine(pt.fX + 130, upos + ut, pt.fX + 160, upos + ut, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003884 paint.setTextSize(12);
3885 canvas->drawString("x-min", pt.fX - 50, pt.fY - 148, paint);
3886 canvas->drawString("x-max", pt.fX + 140, pt.fY - 150, paint);
3887 canvas->drawString("max char width", pt.fX + 120, pt.fY + 57, paint);
3888 canvas->drawString("underline position", pt.fX + 30, pt.fY + 22, paint);
3889 canvas->drawString("underline thickness", pt.fX + 162, pt.fY + 13, paint);
3890 canvas->rotate(-90);
3891 canvas->drawString("descent", -pt.fY - 30, pt.fX - 54, paint);
3892 canvas->drawString("line height", -pt.fY, pt.fX - 29, paint);
3893 canvas->drawString("top", -pt.fY + 30, pt.fX - 4, paint);
3894 canvas->drawString("ascent", -pt.fY, pt.fX + 110, paint);
3895 canvas->drawString("x-height", -pt.fY, pt.fX + 135, paint);
3896 canvas->drawString("cap-height", -pt.fY, pt.fX + 160, paint);
3897 canvas->drawString("bottom", -pt.fY - 50, pt.fX + 15, paint);
3898}
3899##
3900
3901#Struct FontMetrics
Cary Clark08895c42018-02-01 09:37:32 -05003902#Line # values computed by Font_Manager using Typeface ##
Cary Clark8032b982017-07-28 11:04:54 -04003903
3904#Code
Cary Clarka90ea222018-10-16 10:30:28 -04003905#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003906##
3907
Cary Clark154beea2017-10-26 07:58:48 -04003908 FontMetrics is filled out by getFontMetrics. FontMetrics contents reflect the values
3909 computed by Font_Manager using Typeface. Values are set to zero if they are
3910 not available.
Cary Clarke4aa3712017-09-15 02:56:12 -04003911
Cary Clark5538c132018-06-14 12:28:14 -04003912 All vertical values are relative to the baseline, on a y-axis pointing down.
3913 Zero is on the baseline, negative values are above the baseline, and positive
3914 values are below the baseline.
Ben Wagnere5806492017-11-09 12:08:31 -05003915
Cary Clark154beea2017-10-26 07:58:48 -04003916 fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
3917 are valid, since their value may be zero.
Ben Wagnere5806492017-11-09 12:08:31 -05003918
Cary Clark154beea2017-10-26 07:58:48 -04003919 fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
3920 are valid, since their value may be zero.
3921
3922 #Enum FontMetricsFlags
Cary Clark682c58d2018-05-16 07:07:07 -04003923 #Line # valid Font_Metrics ##
Cary Clarke4aa3712017-09-15 02:56:12 -04003924
Cary Clark8032b982017-07-28 11:04:54 -04003925 #Code
Cary Clarka90ea222018-10-16 10:30:28 -04003926 #Populate
Cary Clark8032b982017-07-28 11:04:54 -04003927 ##
3928
Cary Clark154beea2017-10-26 07:58:48 -04003929 FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
3930 the underline or strikeout metric may be valid and zero.
3931 Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
3932
Cary Clark8032b982017-07-28 11:04:54 -04003933 #Const kUnderlineThicknessIsValid_Flag 0x0001
Cary Clark682c58d2018-05-16 07:07:07 -04003934 #Line # set if fUnderlineThickness is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04003935 ##
3936 #Const kUnderlinePositionIsValid_Flag 0x0002
Cary Clark682c58d2018-05-16 07:07:07 -04003937 #Line # set if fUnderlinePosition is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04003938 ##
3939 #Const kStrikeoutThicknessIsValid_Flag 0x0004
Cary Clark682c58d2018-05-16 07:07:07 -04003940 #Line # set if fStrikeoutThickness is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04003941 ##
3942 #Const kStrikeoutPositionIsValid_Flag 0x0008
Cary Clark682c58d2018-05-16 07:07:07 -04003943 #Line # set if fStrikeoutPosition is valid ##
Cary Clark8032b982017-07-28 11:04:54 -04003944 ##
3945
3946 #Enum ##
3947
3948 #Member uint32_t fFlags
Cary Clark682c58d2018-05-16 07:07:07 -04003949 #Line # is set to FontMetricsFlags when metrics are valid ##
Cary Clark8032b982017-07-28 11:04:54 -04003950 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003951
Cary Clark8032b982017-07-28 11:04:54 -04003952 #Member SkScalar fTop
Cary Clark682c58d2018-05-16 07:07:07 -04003953 #Line # extent above baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05003954 Greatest extent above the baseline for any glyph.
3955 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04003956 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003957
Cary Clark8032b982017-07-28 11:04:54 -04003958 #Member SkScalar fAscent
Cary Clark682c58d2018-05-16 07:07:07 -04003959 #Line # distance to reserve above baseline ##
Cary Clark8032b982017-07-28 11:04:54 -04003960 Recommended distance above the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05003961 Typically less than zero.
Cary Clark8032b982017-07-28 11:04:54 -04003962 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003963
Cary Clark8032b982017-07-28 11:04:54 -04003964 #Member SkScalar fDescent
Cary Clark682c58d2018-05-16 07:07:07 -04003965 #Line # distance to reserve below baseline ##
Cary Clark8032b982017-07-28 11:04:54 -04003966 Recommended distance below the baseline to reserve for a line of text.
Ben Wagnere5806492017-11-09 12:08:31 -05003967 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04003968 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003969
Cary Clark8032b982017-07-28 11:04:54 -04003970 #Member SkScalar fBottom
Cary Clark682c58d2018-05-16 07:07:07 -04003971 #Line # extent below baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05003972 Greatest extent below the baseline for any glyph.
3973 Typically greater than zero.
Cary Clark8032b982017-07-28 11:04:54 -04003974 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003975
Cary Clark8032b982017-07-28 11:04:54 -04003976 #Member SkScalar fLeading
Cary Clark682c58d2018-05-16 07:07:07 -04003977 #Line # distance to add between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04003978 Recommended distance to add between lines of text.
Ben Wagnere5806492017-11-09 12:08:31 -05003979 Typically greater than or equal to zero.
Cary Clark8032b982017-07-28 11:04:54 -04003980 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003981
Cary Clark8032b982017-07-28 11:04:54 -04003982 #Member SkScalar fAvgCharWidth
Cary Clark682c58d2018-05-16 07:07:07 -04003983 #Line # average character width ##
Cary Clark8032b982017-07-28 11:04:54 -04003984 Average character width, if it is available.
3985 Zero if no average width is stored in the font.
3986 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003987
Cary Clark8032b982017-07-28 11:04:54 -04003988 #Member SkScalar fMaxCharWidth
Cary Clark682c58d2018-05-16 07:07:07 -04003989 #Line # maximum character width ##
Cary Clark8032b982017-07-28 11:04:54 -04003990 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003991
Cary Clark8032b982017-07-28 11:04:54 -04003992 #Member SkScalar fXMin
Cary Clark682c58d2018-05-16 07:07:07 -04003993 #Line # minimum x ##
Cary Clark5538c132018-06-14 12:28:14 -04003994 Minimum bounding box x-axis value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04003995 Typically less than zero.
3996 ##
Ben Wagnere5806492017-11-09 12:08:31 -05003997
Cary Clark8032b982017-07-28 11:04:54 -04003998 #Member SkScalar fXMax
Cary Clark682c58d2018-05-16 07:07:07 -04003999 #Line # maximum x ##
Cary Clark5538c132018-06-14 12:28:14 -04004000 Maximum bounding box x-axis value for all Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004001 Typically greater than zero.
4002 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004003
Cary Clark8032b982017-07-28 11:04:54 -04004004 #Member SkScalar fXHeight
Cary Clark682c58d2018-05-16 07:07:07 -04004005 #Line # height of lower-case 'x' ##
Cary Clark8032b982017-07-28 11:04:54 -04004006 May be zero if no lower-case height is stored in the font.
4007 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004008
Cary Clark8032b982017-07-28 11:04:54 -04004009 #Member SkScalar fCapHeight
Cary Clark682c58d2018-05-16 07:07:07 -04004010 #Line # height of an upper-case letter ##
Cary Clark8032b982017-07-28 11:04:54 -04004011 May be zero if no upper-case height is stored in the font.
4012 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004013
Cary Clark8032b982017-07-28 11:04:54 -04004014 #Member SkScalar fUnderlineThickness
Cary Clark682c58d2018-05-16 07:07:07 -04004015 #Line # underline thickness ##
Ben Wagnere5806492017-11-09 12:08:31 -05004016 If the metric is valid, the kUnderlineThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004017 If kUnderlineThicknessIsValid_Flag is clear, fUnderlineThickness is zero.
4018 ##
Ben Wagnere5806492017-11-09 12:08:31 -05004019
Cary Clark8032b982017-07-28 11:04:54 -04004020 #Member SkScalar fUnderlinePosition
Cary Clark682c58d2018-05-16 07:07:07 -04004021 #Line # underline position relative to baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004022 Position of the top of the underline stroke relative to the baseline.
4023 Typically positive when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004024
4025 If the metric is valid, the kUnderlinePositionIsValid_Flag is set in fFlags.
4026 If kUnderlinePositionIsValid_Flag is clear, fUnderlinePosition is zero.
4027 ##
4028
4029 #Member SkScalar fStrikeoutThickness
Cary Clark682c58d2018-05-16 07:07:07 -04004030 #Line # strikeout thickness ##
Ben Wagnere5806492017-11-09 12:08:31 -05004031
4032 If the metric is valid, the kStrikeoutThicknessIsValid_Flag is set in fFlags.
Cary Clark8032b982017-07-28 11:04:54 -04004033 If kStrikeoutThicknessIsValid_Flag is clear, fStrikeoutThickness is zero.
4034 ##
4035
4036 #Member SkScalar fStrikeoutPosition
Cary Clark682c58d2018-05-16 07:07:07 -04004037 #Line # strikeout position relative to baseline ##
Ben Wagnere5806492017-11-09 12:08:31 -05004038 Position of the bottom of the strikeout stroke relative to the baseline.
4039 Typically negative when valid.
Cary Clark8032b982017-07-28 11:04:54 -04004040
Ben Wagnere5806492017-11-09 12:08:31 -05004041 If the metric is valid, the kStrikeoutPositionIsValid_Flag is set in fFlags.
4042 If kStrikeoutPositionIsValid_Flag is clear, fStrikeoutPosition is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004043 ##
4044
4045 #Method bool hasUnderlineThickness(SkScalar* thickness) const
Cary Clark682c58d2018-05-16 07:07:07 -04004046 #Line # returns underline thickness if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004047
Cary Clark80247e52018-07-11 16:18:41 -04004048 Returns true if Font_Metrics has a valid underline thickness, and sets
Cary Clarkce101242017-09-01 15:51:02 -04004049 thickness to that value. If the underline thickness is not valid,
4050 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004051
4052 #Param thickness storage for underline width ##
4053
4054 #Return true if font specifies underline width ##
4055
4056 #NoExample
4057 ##
4058 ##
4059
4060 #Method bool hasUnderlinePosition(SkScalar* position) const
Cary Clark682c58d2018-05-16 07:07:07 -04004061 #Line # returns underline position if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004062
Cary Clark80247e52018-07-11 16:18:41 -04004063 Returns true if Font_Metrics has a valid underline position, and sets
Cary Clarkce101242017-09-01 15:51:02 -04004064 position to that value. If the underline position is not valid,
4065 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004066
4067 #Param position storage for underline position ##
4068
4069 #Return true if font specifies underline position ##
4070
4071 #NoExample
4072 ##
4073 ##
4074
4075 #Method bool hasStrikeoutThickness(SkScalar* thickness) const
Cary Clark682c58d2018-05-16 07:07:07 -04004076 #Line # returns strikeout thickness if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004077
Cary Clark80247e52018-07-11 16:18:41 -04004078 Returns true if Font_Metrics has a valid strikeout thickness, and sets
Cary Clarkce101242017-09-01 15:51:02 -04004079 thickness to that value. If the underline thickness is not valid,
4080 return false, and ignore thickness.
Cary Clark8032b982017-07-28 11:04:54 -04004081
4082 #Param thickness storage for strikeout width ##
4083
4084 #Return true if font specifies strikeout width ##
4085
4086 #NoExample
4087 ##
4088 ##
4089
4090 #Method bool hasStrikeoutPosition(SkScalar* position) const
Cary Clark682c58d2018-05-16 07:07:07 -04004091 #Line # returns strikeout position if set ##
Cary Clark8032b982017-07-28 11:04:54 -04004092
Cary Clark80247e52018-07-11 16:18:41 -04004093 Returns true if Font_Metrics has a valid strikeout position, and sets
Cary Clarkce101242017-09-01 15:51:02 -04004094 position to that value. If the underline position is not valid,
4095 return false, and ignore position.
Cary Clark8032b982017-07-28 11:04:54 -04004096
4097 #Param position storage for strikeout position ##
4098
4099 #Return true if font specifies strikeout position ##
4100
4101 #NoExample
4102 ##
4103 ##
4104
4105#Struct ##
4106
4107#Method SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const
4108
Cary Clarkab2621d2018-01-30 10:08:57 -05004109#In Font_Metrics
4110#Line # returns Typeface metrics scaled by text size ##
Cary Clark8032b982017-07-28 11:04:54 -04004111 Returns Font_Metrics associated with Typeface.
4112 The return value is the recommended spacing between lines: the sum of metrics
4113 descent, ascent, and leading.
4114 If metrics is not nullptr, Font_Metrics is copied to metrics.
4115 Results are scaled by Text_Size but does not take into account
4116 dimensions required by Text_Scale_X, Text_Skew_X, Fake_Bold,
4117 Style_Stroke, and Path_Effect.
4118 Results can be additionally scaled by scale; a scale of zero
4119 is ignored.
4120
4121 #Param metrics storage for Font_Metrics from Typeface; may be nullptr ##
4122 #Param scale additional multiplier for returned values ##
4123
4124 #Return recommended spacing between lines ##
4125
4126 #Example
4127 #Height 128
4128 void draw(SkCanvas* canvas) {
4129 SkPaint paint;
4130 paint.setTextSize(32);
4131 SkScalar lineHeight = paint.getFontMetrics(nullptr);
4132 canvas->drawString("line 1", 10, 40, paint);
4133 canvas->drawString("line 2", 10, 40 + lineHeight, paint);
4134 paint.setStyle(SkPaint::kStroke_Style);
4135 paint.setStrokeWidth(10);
4136 lineHeight = paint.getFontMetrics(nullptr, 1.10f); // account for stroke height
4137 canvas->drawString("line 3", 120, 40, paint);
4138 canvas->drawString("line 4", 120, 40 + lineHeight, paint);
4139 }
4140 ##
4141
4142 #SeeAlso Text_Size Typeface Typeface_Methods
4143
4144##
4145
4146
4147#Method SkScalar getFontSpacing() const
4148
Cary Clarkab2621d2018-01-30 10:08:57 -05004149#In Font_Metrics
4150#Line # returns recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004151 Returns the recommended spacing between lines: the sum of metrics
4152 descent, ascent, and leading.
4153 Result is scaled by Text_Size but does not take into account
4154 dimensions required by stroking and Path_Effect.
Cary Clark579985c2017-07-31 11:48:27 -04004155 Returns the same result as getFontMetrics.
Cary Clark8032b982017-07-28 11:04:54 -04004156
Cary Clark0c5f5462017-12-15 11:21:51 -05004157 #Return recommended spacing between lines ##
Cary Clark8032b982017-07-28 11:04:54 -04004158
4159 #Example
4160 SkPaint paint;
4161 for (SkScalar textSize : { 12, 18, 24, 32 } ) {
4162 paint.setTextSize(textSize);
4163 SkDebugf("textSize: %g fontSpacing: %g\n", textSize, paint.getFontSpacing());
4164 }
4165
4166 #StdOut
4167 textSize: 12 fontSpacing: 13.9688
4168 textSize: 18 fontSpacing: 20.9531
4169 textSize: 24 fontSpacing: 27.9375
4170 textSize: 32 fontSpacing: 37.25
4171 ##
4172 ##
4173
4174##
4175
4176
4177#Method SkRect getFontBounds() const
4178
Cary Clarkab2621d2018-01-30 10:08:57 -05004179#In Font_Metrics
4180#Line # returns union all glyph bounds ##
Cary Clarkce101242017-09-01 15:51:02 -04004181Returns the union of bounds of all Glyphs.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004182Returned dimensions are computed by Font_Manager from font data,
Cary Clark579985c2017-07-31 11:48:27 -04004183ignoring Hinting. Includes Text_Size, Text_Scale_X,
Cary Clark8032b982017-07-28 11:04:54 -04004184and Text_Skew_X, but not Fake_Bold or Path_Effect.
4185
4186If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
Herb Derbyfcac00f2018-05-01 11:57:56 -04004187returns the same bounds as Font_Metrics { FontMetrics::fXMin,
Cary Clark8032b982017-07-28 11:04:54 -04004188FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
4189
Cary Clarkce101242017-09-01 15:51:02 -04004190#Return union of bounds of all Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004191
4192#Example
4193 SkPaint paint;
4194 SkPaint::FontMetrics fm;
4195 paint.getFontMetrics(&fm);
4196 SkRect fb = paint.getFontBounds();
4197 SkDebugf("metrics bounds = { %g, %g, %g, %g }\n", fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom );
4198 SkDebugf("font bounds = { %g, %g, %g, %g }\n", fb.fLeft, fb.fTop, fb.fRight, fm.fBottom );
4199
4200 #StdOut
4201 metrics bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4202 font bounds = { -12.2461, -14.7891, 21.5215, 5.55469 }
4203 ##
4204##
4205
4206##
4207
Cary Clark08895c42018-02-01 09:37:32 -05004208#Subtopic Font_Metrics ##
Cary Clark8032b982017-07-28 11:04:54 -04004209# ------------------------------------------------------------------------------
4210
4211#Method int textToGlyphs(const void* text, size_t byteLength,
4212 SkGlyphID glyphs[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004213#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004214#Line # converts text into glyph indices ##
Cary Clark8032b982017-07-28 11:04:54 -04004215
4216Converts text into glyph indices.
4217Returns the number of glyph indices represented by text.
4218Text_Encoding specifies how text represents characters or glyphs.
4219glyphs may be nullptr, to compute the glyph count.
4220
Cary Clarkbc5697d2017-10-04 14:31:33 -04004221Does not check text for valid character codes or valid glyph indices.
Cary Clark8032b982017-07-28 11:04:54 -04004222
Cary Clark579985c2017-07-31 11:48:27 -04004223If byteLength equals zero, returns zero.
Cary Clark8032b982017-07-28 11:04:54 -04004224If byteLength includes a partial character, the partial character is ignored.
4225
4226If Text_Encoding is kUTF8_TextEncoding and
4227text contains an invalid UTF-8 sequence, zero is returned.
4228
Cary Clarkce101242017-09-01 15:51:02 -04004229#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004230#Param byteLength length of character storage in bytes ##
4231#Param glyphs storage for glyph indices; may be nullptr ##
4232
4233#Return number of glyphs represented by text of length byteLength ##
4234
4235 #Example
4236 #Height 64
4237 void draw(SkCanvas* canvas) {
4238 SkPaint paint;
4239 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4240 std::vector<SkGlyphID> glyphs;
4241 int count = paint.textToGlyphs(utf8, sizeof(utf8), nullptr);
4242 glyphs.resize(count);
4243 (void) paint.textToGlyphs(utf8, sizeof(utf8), &glyphs.front());
4244 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4245 paint.setTextSize(32);
4246 canvas->drawText(&glyphs.front(), glyphs.size() * sizeof(SkGlyphID), 10, 40, paint);
4247 }
4248 ##
4249
4250##
4251
4252#Method int countText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004253#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004254#Line # returns number of Glyphs in text ##
Cary Clarkce101242017-09-01 15:51:02 -04004255 Returns the number of Glyphs in text.
4256 Uses Text_Encoding to count the Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04004257 Returns the same result as textToGlyphs.
4258
Cary Clarkce101242017-09-01 15:51:02 -04004259#Param text character storage encoded with Text_Encoding ##
Cary Clark8032b982017-07-28 11:04:54 -04004260#Param byteLength length of character storage in bytes ##
4261
Cary Clarkce101242017-09-01 15:51:02 -04004262#Return number of Glyphs represented by text of length byteLength ##
Cary Clark8032b982017-07-28 11:04:54 -04004263
4264 #Example
4265 SkPaint paint;
4266 const uint8_t utf8[] = { 0x24, 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xC2, 0xA5, 0xC2, 0xA3 };
4267 SkDebugf("count = %d\n", paint.countText(utf8, sizeof(utf8)));
4268
4269 #StdOut
4270 count = 5
4271 ##
4272 ##
4273##
4274
4275# ------------------------------------------------------------------------------
4276
4277#Method bool containsText(const void* text, size_t byteLength) const
Cary Clark78de7512018-02-07 07:27:09 -05004278#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004279#Line # returns if all text corresponds to Glyphs ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004280 Returns true if all text corresponds to a non-zero glyph index.
Cary Clark8032b982017-07-28 11:04:54 -04004281 Returns false if any characters in text are not supported in
4282 Typeface.
4283
Cary Clark579985c2017-07-31 11:48:27 -04004284 If Text_Encoding is kGlyphID_TextEncoding,
4285 returns true if all glyph indices in text are non-zero;
Cary Clark8032b982017-07-28 11:04:54 -04004286 does not check to see if text contains valid glyph indices for Typeface.
4287
Cary Clarkce101242017-09-01 15:51:02 -04004288 Returns true if byteLength is zero.
Cary Clark8032b982017-07-28 11:04:54 -04004289
Cary Clarkce101242017-09-01 15:51:02 -04004290 #Param text array of characters or Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004291 #Param byteLength number of bytes in text array ##
4292
4293 #Return true if all text corresponds to a non-zero glyph index ##
4294
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004295 #NoExample
Cary Clark8032b982017-07-28 11:04:54 -04004296 #Description
4297 containsText succeeds for degree symbol, but cannot find a glyph index
4298 corresponding to the Unicode surrogate code point.
4299 ##
4300 SkPaint paint;
4301 const uint16_t goodChar = 0x00B0; // degree symbol
4302 const uint16_t badChar = 0xD800; // Unicode surrogate
4303 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004304 SkDebugf("0x%04x %c= has char\n", goodChar,
Cary Clark8032b982017-07-28 11:04:54 -04004305 paint.containsText(&goodChar, 2) ? '=' : '!');
4306 SkDebugf("0x%04x %c= has char\n", badChar,
4307 paint.containsText(&badChar, 2) ? '=' : '!');
4308
4309 #StdOut
4310 0x00b0 == has char
4311 0xd800 != has char
4312 ##
4313 ##
4314
4315 #Example
4316 #Description
4317 containsText returns true that glyph index is greater than zero, not
4318 that it corresponds to an entry in Typeface.
4319 ##
4320 SkPaint paint;
4321 const uint16_t goodGlyph = 511;
4322 const uint16_t zeroGlyph = 0;
4323 const uint16_t badGlyph = 65535; // larger than glyph count in font
4324 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyfcac00f2018-05-01 11:57:56 -04004325 SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
Cary Clark8032b982017-07-28 11:04:54 -04004326 paint.containsText(&goodGlyph, 2) ? '=' : '!');
4327 SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
4328 paint.containsText(&zeroGlyph, 2) ? '=' : '!');
4329 SkDebugf("0x%04x %c= has glyph\n", badGlyph,
4330 paint.containsText(&badGlyph, 2) ? '=' : '!');
4331
4332 #StdOut
4333 0x01ff == has glyph
4334 0x0000 != has glyph
4335 0xffff == has glyph
4336 ##
4337 ##
4338
4339#SeeAlso setTextEncoding Typeface
4340
4341##
4342
4343# ------------------------------------------------------------------------------
4344
4345#Method void glyphsToUnichars(const SkGlyphID glyphs[],
4346 int count, SkUnichar text[]) const
Cary Clark78de7512018-02-07 07:27:09 -05004347#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004348#Line # converts Glyphs into text ##
Cary Clark8032b982017-07-28 11:04:54 -04004349
Herb Derbyfcac00f2018-05-01 11:57:56 -04004350 Converts glyphs into text if possible.
4351 Glyph values without direct Unicode equivalents are mapped to zero.
Cary Clark8032b982017-07-28 11:04:54 -04004352 Uses the Typeface, but is unaffected
4353 by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
4354
4355 Only supported on platforms that use FreeType as the Font_Engine.
4356
4357 #Param glyphs array of indices into font ##
4358 #Param count length of glyph array ##
4359 #Param text storage for character codes, one per glyph ##
4360
4361 #Example
4362 #Height 64
4363 #Description
4364 Convert UTF-8 text to glyphs; then convert glyphs to Unichar code points.
4365 ##
4366 void draw(SkCanvas* canvas) {
4367 SkPaint paint;
4368 const char hello[] = "Hello!";
4369 const int count = sizeof(hello) - 1;
4370 SkGlyphID glyphs[count];
4371 if (count != paint.textToGlyphs(hello, count, glyphs)) {
4372 return;
4373 }
4374 SkUnichar unichars[count];
4375 paint.glyphsToUnichars(glyphs, count, unichars);
4376 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
4377 canvas->drawText(unichars, sizeof(unichars), 10, 30, paint);
4378 }
4379 ##
4380
4381##
4382
4383# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004384#Subtopic Measure_Text
4385#Line # width, height, bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004386
4387#Method SkScalar measureText(const void* text, size_t length, SkRect* bounds) const
4388
Cary Clarkab2621d2018-01-30 10:08:57 -05004389#In Measure_Text
4390#Line # returns advance width and bounds of text ##
Cary Clark8032b982017-07-28 11:04:54 -04004391 Returns the advance width of text if kVerticalText_Flag is clear,
4392 and the height of text if kVerticalText_Flag is set.
4393 The advance is the normal distance to move before drawing additional text.
4394 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4395 and Text_Size, Text_Scale_X, Text_Skew_X, Stroke_Width, and
4396 Path_Effect to scale the metrics and bounds.
4397 Returns the bounding box of text if bounds is not nullptr.
4398 The bounding box is computed as if the text was drawn at the origin.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004399
Cary Clark8032b982017-07-28 11:04:54 -04004400 #Param text character codes or glyph indices to be measured ##
4401 #Param length number of bytes of text to measure ##
4402 #Param bounds returns bounding box relative to (0, 0) if not nullptr ##
4403
4404 #Return advance width or height ##
4405
4406 #Example
4407 #Height 64
4408 void draw(SkCanvas* canvas) {
4409 SkPaint paint;
4410 paint.setAntiAlias(true);
4411 paint.setTextSize(50);
4412 const char str[] = "ay^jZ";
4413 const int count = sizeof(str) - 1;
4414 canvas->drawText(str, count, 25, 50, paint);
4415 SkRect bounds;
4416 paint.measureText(str, count, &bounds);
4417 canvas->translate(25, 50);
4418 paint.setStyle(SkPaint::kStroke_Style);
4419 canvas->drawRect(bounds, paint);
4420 }
4421 ##
4422
4423##
4424
4425#Method SkScalar measureText(const void* text, size_t length) const
4426
Cary Clarkab2621d2018-01-30 10:08:57 -05004427#In Measure_Text
Cary Clark8032b982017-07-28 11:04:54 -04004428 Returns the advance width of text if kVerticalText_Flag is clear,
4429 and the height of text if kVerticalText_Flag is set.
4430 The advance is the normal distance to move before drawing additional text.
4431 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4432 and Text_Size to scale the metrics.
4433 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4434
4435 #Param text character codes or glyph indices to be measured ##
4436 #Param length number of bytes of text to measure ##
4437
4438 #Return advance width or height ##
4439
4440 #Example
4441 SkPaint paint;
4442 SkDebugf("default width = %g\n", paint.measureText("!", 1));
4443 paint.setTextSize(paint.getTextSize() * 2);
4444 SkDebugf("double width = %g\n", paint.measureText("!", 1));
4445
4446 #StdOut
4447 default width = 5
4448 double width = 10
4449 ##
4450 ##
4451
4452##
4453
4454#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
Cary Clark73fa9722017-08-29 17:36:51 -04004455 SkScalar* measuredWidth = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004456#In Measure_Text
4457#Line # returns text that fits in a width ##
Cary Clark8032b982017-07-28 11:04:54 -04004458
4459 Returns the bytes of text that fit within maxWidth.
4460 If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
4461 equal to maxWidth.
4462 If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or
4463 equal to maxWidth.
4464 Measures only while the advance is less than or equal to maxWidth.
4465 Returns the advance or the text fragment in measuredWidth if it not nullptr.
4466 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4467 and Text_Size to scale the metrics.
4468 Does not scale the advance or bounds by Fake_Bold or Path_Effect.
4469
4470 #Param text character codes or glyph indices to be measured ##
4471 #Param length number of bytes of text to measure ##
4472 #Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
4473 #Param measuredWidth returns the width of the text less than or equal to maxWidth ##
4474 #Return bytes of text that fit, always less than or equal to length ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004475
Cary Clark8032b982017-07-28 11:04:54 -04004476 #Example
4477 #Description
4478 Line under "Breakfast" shows desired width, shorter than available characters.
4479 Line under "Bre" shows measured width after breaking text.
4480 ##
4481 #Height 128
4482 #Width 280
4483 void draw(SkCanvas* canvas) {
4484 SkPaint paint;
4485 paint.setAntiAlias(true);
4486 paint.setTextSize(50);
4487 const char str[] = "Breakfast";
4488 const int count = sizeof(str) - 1;
4489 canvas->drawText(str, count, 25, 50, paint);
4490 SkScalar measuredWidth;
4491 int partialBytes = paint.breakText(str, count, 100, &measuredWidth);
4492 canvas->drawText(str, partialBytes, 25, 100, paint);
4493 canvas->drawLine(25, 60, 25 + 100, 60, paint);
4494 canvas->drawLine(25, 110, 25 + measuredWidth, 110, paint);
4495 }
4496 ##
4497
4498##
4499
4500#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
Cary Clark73fa9722017-08-29 17:36:51 -04004501 SkRect bounds[] = nullptr) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004502#In Measure_Text
4503#Line # returns advance and bounds for each glyph in text ##
Cary Clark8032b982017-07-28 11:04:54 -04004504
4505 Retrieves the advance and bounds for each glyph in text, and returns
4506 the glyph count in text.
4507 Both widths and bounds may be nullptr.
4508 If widths is not nullptr, widths must be an array of glyph count entries.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004509 if bounds is not nullptr, bounds must be an array of glyph count entries.
Cary Clark8032b982017-07-28 11:04:54 -04004510 If kVerticalText_Flag is clear, widths returns the horizontal advance.
4511 If kVerticalText_Flag is set, widths returns the vertical advance.
4512 Uses Text_Encoding to decode text, Typeface to get the font metrics,
4513 and Text_Size to scale the widths and bounds.
4514 Does not scale the advance by Fake_Bold or Path_Effect.
4515 Does include Fake_Bold and Path_Effect in the bounds.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004516
Cary Clark8032b982017-07-28 11:04:54 -04004517 #Param text character codes or glyph indices to be measured ##
4518 #Param byteLength number of bytes of text to measure ##
4519 #Param widths returns text advances for each glyph; may be nullptr ##
4520 #Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004521
Cary Clark8032b982017-07-28 11:04:54 -04004522 #Return glyph count in text ##
4523
4524 #Example
4525 #Height 160
4526 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004527 Bounds of Glyphs increase for stroked text, but text advance remains the same.
Cary Clark8032b982017-07-28 11:04:54 -04004528 The underlines show the text advance, spaced to keep them distinct.
4529 ##
4530 void draw(SkCanvas* canvas) {
4531 SkPaint paint;
4532 paint.setAntiAlias(true);
4533 paint.setTextSize(50);
4534 const char str[] = "abc";
4535 const int bytes = sizeof(str) - 1;
4536 int count = paint.getTextWidths(str, bytes, nullptr);
4537 std::vector<SkScalar> widths;
4538 std::vector<SkRect> bounds;
4539 widths.resize(count);
4540 bounds.resize(count);
4541 for (int loop = 0; loop < 2; ++loop) {
4542 (void) paint.getTextWidths(str, count, &widths.front(), &bounds.front());
4543 SkPoint loc = { 25, 50 };
4544 canvas->drawText(str, bytes, loc.fX, loc.fY, paint);
4545 paint.setStyle(SkPaint::kStroke_Style);
4546 paint.setStrokeWidth(0);
4547 SkScalar advanceY = loc.fY + 10;
4548 for (int index = 0; index < count; ++index) {
4549 bounds[index].offset(loc.fX, loc.fY);
4550 canvas->drawRect(bounds[index], paint);
4551 canvas->drawLine(loc.fX, advanceY, loc.fX + widths[index], advanceY, paint);
4552 loc.fX += widths[index];
4553 advanceY += 5;
4554 }
4555 canvas->translate(0, 80);
4556 paint.setStrokeWidth(3);
4557 }
4558 }
4559 ##
4560
4561##
4562
Cary Clark08895c42018-02-01 09:37:32 -05004563#Subtopic Measure_Text ##
Cary Clark8032b982017-07-28 11:04:54 -04004564# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004565#Subtopic Text_Path
4566#Line # geometry of Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004567
Cary Clarkce101242017-09-01 15:51:02 -04004568Text_Path describes the geometry of Glyphs used to draw text.
Cary Clark8032b982017-07-28 11:04:54 -04004569
4570#Method void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
4571 SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004572#In Text_Path
4573#Line # returns Path equivalent to text ##
Cary Clark8032b982017-07-28 11:04:54 -04004574
4575Returns the geometry as Path equivalent to the drawn text.
4576Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4577and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4578All of the glyph paths are stored in path.
Cary Clark579985c2017-07-31 11:48:27 -04004579Uses x, y, and Text_Align to position path.
Cary Clark8032b982017-07-28 11:04:54 -04004580
4581 #Param text character codes or glyph indices ##
4582 #Param length number of bytes of text ##
Cary Clark5538c132018-06-14 12:28:14 -04004583 #Param x x-axis value of the origin of the text ##
4584 #Param y y-axis value of the origin of the text ##
Cary Clarkce101242017-09-01 15:51:02 -04004585 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004586
4587 #Example
4588 #Description
4589 Text is added to Path, offset, and subtracted from Path, then added at
4590 the offset location. The result is rendered with one draw call.
4591 ##
4592 #Height 128
4593 void draw(SkCanvas* canvas) {
4594 SkPaint paint;
4595 paint.setTextSize(80);
4596 SkPath path, path2;
4597 paint.getTextPath("ABC", 3, 20, 80, &path);
4598 path.offset(20, 20, &path2);
4599 Op(path, path2, SkPathOp::kDifference_SkPathOp, &path);
4600 path.addPath(path2);
4601 paint.setStyle(SkPaint::kStroke_Style);
4602 canvas->drawPath(path, paint);
4603 }
4604 ##
4605
4606##
4607
4608#Method void getPosTextPath(const void* text, size_t length,
4609 const SkPoint pos[], SkPath* path) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004610#In Text_Path
4611#Line # returns Path equivalent to positioned text ##
Cary Clark8032b982017-07-28 11:04:54 -04004612
4613Returns the geometry as Path equivalent to the drawn text.
4614Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4615and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4616All of the glyph paths are stored in path.
4617Uses pos array and Text_Align to position path.
4618pos contains a position for each glyph.
4619
4620 #Param text character codes or glyph indices ##
4621 #Param length number of bytes of text ##
4622 #Param pos positions of each glyph ##
Cary Clarkce101242017-09-01 15:51:02 -04004623 #Param path geometry of the Glyphs ##
Cary Clark8032b982017-07-28 11:04:54 -04004624
4625 #Example
4626 #Height 85
4627 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004628 Simplifies three Glyphs to eliminate overlaps, and strokes the result.
Cary Clark8032b982017-07-28 11:04:54 -04004629 ##
4630 void draw(SkCanvas* canvas) {
4631 SkPaint paint;
4632 paint.setTextSize(80);
4633 SkPath path, path2;
4634 SkPoint pos[] = {{20, 60}, {30, 70}, {40, 80}};
4635 paint.getPosTextPath("ABC", 3, pos, &path);
4636 Simplify(path, &path);
4637 paint.setStyle(SkPaint::kStroke_Style);
4638 canvas->drawPath(path, paint);
4639 }
4640 ##
4641
4642##
4643
Cary Clark08895c42018-02-01 09:37:32 -05004644#Subtopic Text_Path ##
Cary Clark8032b982017-07-28 11:04:54 -04004645# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004646#Subtopic Text_Intercepts
4647#Line # advanced underline, strike through ##
Cary Clark8032b982017-07-28 11:04:54 -04004648
Cary Clarkce101242017-09-01 15:51:02 -04004649Text_Intercepts describe the intersection of drawn text Glyphs with a pair
Cary Clark8032b982017-07-28 11:04:54 -04004650of lines parallel to the text advance. Text_Intercepts permits creating a
Cary Clarkce101242017-09-01 15:51:02 -04004651underline that skips Descenders.
Cary Clark8032b982017-07-28 11:04:54 -04004652
4653#Method int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
4654 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004655#In Text_Intercepts
4656#Line # returns where lines intersect text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004657
4658 Returns the number of intervals that intersect bounds.
4659 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004660 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004661 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004662 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4663 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4664 Uses x, y, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004665
Cary Clark8032b982017-07-28 11:04:54 -04004666 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004667
Cary Clark8032b982017-07-28 11:04:54 -04004668 intervals are cached to improve performance for multiple calls.
4669
4670 #Param text character codes or glyph indices ##
4671 #Param length number of bytes of text ##
Cary Clark5538c132018-06-14 12:28:14 -04004672 #Param x x-axis value of the origin of the text ##
4673 #Param y y-axis value of the origin of the text ##
Cary Clark8032b982017-07-28 11:04:54 -04004674 #Param bounds lower and upper line parallel to the advance ##
4675 #Param intervals returned intersections; may be nullptr ##
4676
4677 #Return number of intersections; may be zero ##
4678
4679#Example
4680#Height 128
4681#Description
Cary Clarkce101242017-09-01 15:51:02 -04004682Underline uses intercepts to draw on either side of the glyph Descender.
Cary Clark8032b982017-07-28 11:04:54 -04004683##
4684void draw(SkCanvas* canvas) {
4685 SkPaint paint;
4686 paint.setTextSize(120);
4687 SkPoint textOrigin = { 20, 100 };
4688 SkScalar bounds[] = { 100, 108 };
4689 int count = paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds, nullptr);
4690 std::vector<SkScalar> intervals;
4691 intervals.resize(count);
4692 (void) paint.getTextIntercepts("y", 1, textOrigin.fX, textOrigin.fY, bounds,
4693 &intervals.front());
4694 canvas->drawString("y", textOrigin.fX, textOrigin.fY, paint);
4695 paint.setColor(SK_ColorRED);
4696 SkScalar x = textOrigin.fX;
4697 for (int i = 0; i < count; i += 2) {
4698 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4699 x = intervals[i + 1];
4700 }
4701 canvas->drawRect({intervals[count - 1], bounds[0],
4702 textOrigin.fX + paint.measureText("y", 1), bounds[1]}, paint);
4703}
4704##
4705
4706##
4707
4708#Method int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
4709 const SkScalar bounds[2], SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004710#In Text_Intercepts
4711#Line # returns where lines intersect positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004712
4713 Returns the number of intervals that intersect bounds.
4714 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004715 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004716 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004717 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4718 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4719 Uses pos array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004720
Cary Clark8032b982017-07-28 11:04:54 -04004721 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004722
Cary Clark8032b982017-07-28 11:04:54 -04004723 intervals are cached to improve performance for multiple calls.
4724
4725 #Param text character codes or glyph indices ##
4726 #Param length number of bytes of text ##
4727 #Param pos positions of each glyph ##
4728 #Param bounds lower and upper line parallel to the advance ##
4729 #Param intervals returned intersections; may be nullptr ##
4730
Cary Clarka523d2d2017-08-30 08:58:10 -04004731 #Return number of intersections; may be zero ##
Cary Clark8032b982017-07-28 11:04:54 -04004732
4733 #Example
4734 #Description
Cary Clarkce101242017-09-01 15:51:02 -04004735 Text intercepts draw on either side of, but not inside, Glyphs in a run.
Cary Clark8032b982017-07-28 11:04:54 -04004736 ##
4737 void draw(SkCanvas* canvas) {
4738 SkPaint paint;
4739 paint.setTextSize(120);
4740 paint.setVerticalText(true);
4741 SkPoint textPos[] = {{ 60, 40 }, { 60, 140 }};
4742 SkScalar bounds[] = { 56, 64 };
4743 const char str[] = "A-";
4744 int len = sizeof(str) - 1;
4745 int count = paint.getPosTextIntercepts(str, len, textPos, bounds, nullptr);
4746 std::vector<SkScalar> intervals;
4747 intervals.resize(count);
4748 (void) paint.getPosTextIntercepts(str, len, textPos, bounds, &intervals.front());
4749 canvas->drawPosText(str, len, textPos, paint);
4750 paint.setColor(SK_ColorRED);
4751 SkScalar y = textPos[0].fY;
4752 for (int i = 0; i < count; i+= 2) {
4753 canvas->drawRect({bounds[0], y, bounds[1], intervals[i]}, paint);
4754 y = intervals[i + 1];
4755 }
4756 canvas->drawRect({bounds[0], intervals[count - 1], bounds[1], 240}, paint);
4757 }
4758 ##
4759
4760##
4761
4762#Method int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
4763 SkScalar constY, const SkScalar bounds[2],
4764 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004765#In Text_Intercepts
4766#Line # returns where lines intersect horizontally positioned text; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004767
4768 Returns the number of intervals that intersect bounds.
4769 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004770 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004771 the string.
Cary Clark8032b982017-07-28 11:04:54 -04004772 Uses Text_Encoding to decode text, Typeface to get the glyph paths,
4773 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
4774 Uses xpos array, constY, and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004775
Cary Clark8032b982017-07-28 11:04:54 -04004776 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004777
Cary Clark8032b982017-07-28 11:04:54 -04004778 intervals are cached to improve performance for multiple calls.
4779
4780 #Param text character codes or glyph indices ##
4781 #Param length number of bytes of text ##
4782 #Param xpos positions of each glyph in x ##
4783 #Param constY position of each glyph in y ##
4784 #Param bounds lower and upper line parallel to the advance ##
4785 #Param intervals returned intersections; may be nullptr ##
4786
4787 #Return number of intersections; may be zero ##
4788
4789 #Example
4790 #Height 128
4791 #Description
4792 Text intercepts do not take stroke thickness into consideration.
4793 ##
4794 void draw(SkCanvas* canvas) {
4795 SkPaint paint;
4796 paint.setTextSize(120);
4797 paint.setStyle(SkPaint::kStroke_Style);
4798 paint.setStrokeWidth(4);
4799 SkScalar textPosH[] = { 20, 80, 140 };
4800 SkScalar y = 100;
4801 SkScalar bounds[] = { 56, 78 };
4802 const char str[] = "\\-/";
4803 int len = sizeof(str) - 1;
4804 int count = paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, nullptr);
4805 std::vector<SkScalar> intervals;
4806 intervals.resize(count);
4807 (void) paint.getPosTextHIntercepts(str, len, textPosH, y, bounds, &intervals.front());
4808 canvas->drawPosTextH(str, len, textPosH, y, paint);
4809 paint.setColor(0xFFFF7777);
4810 paint.setStyle(SkPaint::kFill_Style);
4811 SkScalar x = textPosH[0];
4812 for (int i = 0; i < count; i+= 2) {
4813 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4814 x = intervals[i + 1];
4815 }
4816 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4817 }
4818 ##
4819
4820##
4821
4822
4823#Method int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
4824 SkScalar* intervals) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004825#In Text_Intercepts
4826#Line # returns where lines intersect Text_Blob; underlines ##
Cary Clark8032b982017-07-28 11:04:54 -04004827
4828 Returns the number of intervals that intersect bounds.
4829 bounds describes a pair of lines parallel to the text advance.
Cary Clarkce101242017-09-01 15:51:02 -04004830 The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
Herb Derbyfcac00f2018-05-01 11:57:56 -04004831 the string.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004832 Uses Typeface to get the glyph paths,
Cary Clark8032b982017-07-28 11:04:54 -04004833 and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Cary Clarkce101242017-09-01 15:51:02 -04004834 Uses run array and Text_Align to position intervals.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004835
Cary Clark3cd22cc2017-12-01 11:49:58 -05004836 Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4837
Cary Clark8032b982017-07-28 11:04:54 -04004838 Pass nullptr for intervals to determine the size of the interval array.
Herb Derbyfcac00f2018-05-01 11:57:56 -04004839
Cary Clark8032b982017-07-28 11:04:54 -04004840 intervals are cached to improve performance for multiple calls.
4841
Cary Clarkce101242017-09-01 15:51:02 -04004842 #Param blob Glyphs, positions, and text paint attributes ##
Cary Clark8032b982017-07-28 11:04:54 -04004843 #Param bounds lower and upper line parallel to the advance ##
4844 #Param intervals returned intersections; may be nullptr ##
4845
4846 #Return number of intersections; may be zero ##
4847
4848 #Example
4849 #Height 143
4850 void draw(SkCanvas* canvas) {
4851 SkPaint paint;
Cary Clark3cd22cc2017-12-01 11:49:58 -05004852 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Cary Clark8032b982017-07-28 11:04:54 -04004853 paint.setTextSize(120);
4854 SkPoint textPos = { 20, 110 };
4855 int len = 3;
4856 SkTextBlobBuilder textBlobBuilder;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004857 const SkTextBlobBuilder::RunBuffer& run =
Cary Clark8032b982017-07-28 11:04:54 -04004858 textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
4859 run.glyphs[0] = 10;
4860 run.glyphs[1] = 20;
Herb Derbyfcac00f2018-05-01 11:57:56 -04004861 run.glyphs[2] = 30;
Cary Clark8032b982017-07-28 11:04:54 -04004862 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4863 canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
4864 SkScalar bounds[] = { 116, 134 };
4865 int count = paint.getTextBlobIntercepts(blob.get(), bounds, nullptr);
4866 std::vector<SkScalar> intervals;
4867 intervals.resize(count);
4868 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
4869 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4870 paint.setColor(0xFFFF7777);
4871 SkScalar x = textPos.fX;
4872 for (int i = 0; i < count; i+= 2) {
4873 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
4874 x = intervals[i + 1];
4875 }
4876 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
4877 }
4878 ##
4879
4880##
4881
Cary Clark08895c42018-02-01 09:37:32 -05004882#Subtopic Text_Intercepts ##
Cary Clark8032b982017-07-28 11:04:54 -04004883# ------------------------------------------------------------------------------
4884
4885#Method bool nothingToDraw() const
Cary Clark78de7512018-02-07 07:27:09 -05004886#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004887#Line # returns true if Paint prevents all drawing ##
Cary Clark579985c2017-07-31 11:48:27 -04004888 Returns true if Paint prevents all drawing;
4889 otherwise, the Paint may or may not allow drawing.
Cary Clark8032b982017-07-28 11:04:54 -04004890
Cary Clarkce101242017-09-01 15:51:02 -04004891 Returns true if, for example, Blend_Mode combined with Color_Alpha computes a
4892 new Alpha of zero.
Cary Clark8032b982017-07-28 11:04:54 -04004893
4894 #Return true if Paint prevents all drawing ##
4895
4896 #Example
4897 void draw(SkCanvas* canvas) {
4898 auto debugster = [](const char* prefix, const SkPaint& p) -> void {
Herb Derbyfcac00f2018-05-01 11:57:56 -04004899 SkDebugf("%s nothing to draw: %s\n", prefix,
Cary Clark8032b982017-07-28 11:04:54 -04004900 p.nothingToDraw() ? "true" : "false");
4901 };
4902 SkPaint paint;
4903 debugster("initial", paint);
4904 paint.setBlendMode(SkBlendMode::kDst);
4905 debugster("blend dst", paint);
4906 paint.setBlendMode(SkBlendMode::kSrcOver);
4907 debugster("blend src over", paint);
4908 paint.setAlpha(0);
4909 debugster("alpha 0", paint);
4910 }
4911
4912 #StdOut
4913 initial nothing to draw: false
4914 blend dst nothing to draw: true
4915 blend src over nothing to draw: false
4916 alpha 0 nothing to draw: true
4917 #StdOut ##
4918 ##
4919
4920##
4921
4922# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05004923#Subtopic Fast_Bounds
4924#Line # approximate area required by Paint ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004925 #Private
4926 To be made private.
Cary Clark8032b982017-07-28 11:04:54 -04004927 ##
4928
Cary Clark682c58d2018-05-16 07:07:07 -04004929Fast_Bounds functions conservatively outset a drawing bounds by additional area
Cary Clark8032b982017-07-28 11:04:54 -04004930Paint may draw to.
4931
4932#Method bool canComputeFastBounds() const
Herb Derbyfcac00f2018-05-01 11:57:56 -04004933
Cary Clarkab2621d2018-01-30 10:08:57 -05004934#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05004935#Line # returns true if settings allow for fast bounds computation ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004936 #Private
Cary Clark8032b982017-07-28 11:04:54 -04004937 (to be made private)
4938 ##
4939
4940 Returns true if Paint does not include elements requiring extensive computation
4941 to compute Device bounds of drawn geometry. For instance, Paint with Path_Effect
4942 always returns false.
4943
4944 #Return true if Paint allows for fast computation of bounds ##
4945##
4946
4947#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
Herb Derbyfcac00f2018-05-01 11:57:56 -04004948
Cary Clarkab2621d2018-01-30 10:08:57 -05004949#In Fast_Bounds
Cary Clark1a8d7622018-03-05 13:26:16 -05004950#Line # returns fill bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004951 #Private
Cary Clark8032b982017-07-28 11:04:54 -04004952 (to be made private)
4953 ##
4954
4955 Only call this if canComputeFastBounds returned true. This takes a
4956 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
4957 effects in the paint (e.g. stroking). If needed, it uses the storage
Cary Clarkce101242017-09-01 15:51:02 -04004958 parameter. It returns the adjusted bounds that can then be used
Cary Clark8032b982017-07-28 11:04:54 -04004959 for SkCanvas::quickReject tests.
4960
Cary Clarkce101242017-09-01 15:51:02 -04004961 The returned Rect will either be orig or storage, thus the caller
Cary Clark8032b982017-07-28 11:04:54 -04004962 should not rely on storage being set to the result, but should always
Cary Clarkce101242017-09-01 15:51:02 -04004963 use the returned value. It is legal for orig and storage to be the same
4964 Rect.
Cary Clark8032b982017-07-28 11:04:54 -04004965
Herb Derbyfcac00f2018-05-01 11:57:56 -04004966 #Private
Cary Clark682c58d2018-05-16 07:07:07 -04004967 For example:
4968 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
4969 SkRect storage;
4970 if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
Cary Clark137b8742018-05-30 09:21:49 -04004971 return; // do not draw the path
Cary Clark682c58d2018-05-16 07:07:07 -04004972 }
Cary Clark8032b982017-07-28 11:04:54 -04004973 }
Cary Clark682c58d2018-05-16 07:07:07 -04004974 // draw the path
Cary Clark8032b982017-07-28 11:04:54 -04004975 ##
4976
4977 #Param orig geometry modified by Paint when drawn ##
4978 #Param storage computed bounds of geometry; may not be nullptr ##
4979
4980 #Return fast computed bounds ##
4981##
4982
4983#Method const SkRect& computeFastStrokeBounds(const SkRect& orig,
4984 SkRect* storage) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004985#In Fast_Bounds
4986#Line # returns stroke bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04004987 #Private
Cary Clark8032b982017-07-28 11:04:54 -04004988 (to be made private)
4989 ##
4990
4991 #Param orig geometry modified by Paint when drawn ##
4992 #Param storage computed bounds of geometry ##
4993
4994 #Return fast computed bounds ##
4995##
4996
4997#Method const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
4998 Style style) const
Cary Clarkab2621d2018-01-30 10:08:57 -05004999#In Fast_Bounds
5000#Line # returns bounds for quick reject tests ##
Herb Derbyfcac00f2018-05-01 11:57:56 -04005001 #Private
Cary Clark8032b982017-07-28 11:04:54 -04005002 (to be made private)
5003 ##
5004
Cary Clarkce101242017-09-01 15:51:02 -04005005 Computes the bounds, overriding the Paint Style. This can be used to
5006 account for additional width required by stroking orig, without
5007 altering Style set to fill.
Cary Clark8032b982017-07-28 11:04:54 -04005008
5009 #Param orig geometry modified by Paint when drawn ##
5010 #Param storage computed bounds of geometry ##
5011 #Param style overrides Style ##
5012
5013 #Return fast computed bounds ##
5014##
5015
Cary Clark1a8d7622018-03-05 13:26:16 -05005016#Subtopic Fast_Bounds ##
Cary Clark8032b982017-07-28 11:04:54 -04005017
5018# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05005019#Subtopic Utility
Cary Clark78de7512018-02-07 07:27:09 -05005020#Line # rarely called management functions ##
5021##
Cary Clark8032b982017-07-28 11:04:54 -04005022
Cary Clark8032b982017-07-28 11:04:54 -04005023# ------------------------------------------------------------------------------
5024
5025#Class SkPaint ##
5026
5027#Topic Paint ##
Cary Clark4855f782018-02-06 09:41:53 -05005028